@songsid/agend 0.0.1

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 (232) hide show
  1. package/README.md +210 -0
  2. package/README.zh-TW.md +134 -0
  3. package/dist/access-path.d.ts +10 -0
  4. package/dist/access-path.js +32 -0
  5. package/dist/access-path.js.map +1 -0
  6. package/dist/adapter-world.d.ts +25 -0
  7. package/dist/adapter-world.js +41 -0
  8. package/dist/adapter-world.js.map +1 -0
  9. package/dist/agent-cli-instructions.md +50 -0
  10. package/dist/agent-cli.d.ts +2 -0
  11. package/dist/agent-cli.js +200 -0
  12. package/dist/agent-cli.js.map +1 -0
  13. package/dist/agent-endpoint.d.ts +25 -0
  14. package/dist/agent-endpoint.js +162 -0
  15. package/dist/agent-endpoint.js.map +1 -0
  16. package/dist/backend/antigravity.d.ts +17 -0
  17. package/dist/backend/antigravity.js +98 -0
  18. package/dist/backend/antigravity.js.map +1 -0
  19. package/dist/backend/claude-code.d.ts +23 -0
  20. package/dist/backend/claude-code.js +171 -0
  21. package/dist/backend/claude-code.js.map +1 -0
  22. package/dist/backend/codex.d.ts +18 -0
  23. package/dist/backend/codex.js +160 -0
  24. package/dist/backend/codex.js.map +1 -0
  25. package/dist/backend/factory.d.ts +2 -0
  26. package/dist/backend/factory.js +28 -0
  27. package/dist/backend/factory.js.map +1 -0
  28. package/dist/backend/gemini-cli.d.ts +17 -0
  29. package/dist/backend/gemini-cli.js +163 -0
  30. package/dist/backend/gemini-cli.js.map +1 -0
  31. package/dist/backend/index.d.ts +7 -0
  32. package/dist/backend/index.js +7 -0
  33. package/dist/backend/index.js.map +1 -0
  34. package/dist/backend/kiro.d.ts +17 -0
  35. package/dist/backend/kiro.js +147 -0
  36. package/dist/backend/kiro.js.map +1 -0
  37. package/dist/backend/marker-utils.d.ts +13 -0
  38. package/dist/backend/marker-utils.js +64 -0
  39. package/dist/backend/marker-utils.js.map +1 -0
  40. package/dist/backend/mock.d.ts +25 -0
  41. package/dist/backend/mock.js +85 -0
  42. package/dist/backend/mock.js.map +1 -0
  43. package/dist/backend/opencode.d.ts +16 -0
  44. package/dist/backend/opencode.js +136 -0
  45. package/dist/backend/opencode.js.map +1 -0
  46. package/dist/backend/types.d.ts +86 -0
  47. package/dist/backend/types.js +33 -0
  48. package/dist/backend/types.js.map +1 -0
  49. package/dist/channel/access-manager.d.ts +18 -0
  50. package/dist/channel/access-manager.js +153 -0
  51. package/dist/channel/access-manager.js.map +1 -0
  52. package/dist/channel/adapters/telegram.d.ts +63 -0
  53. package/dist/channel/adapters/telegram.js +646 -0
  54. package/dist/channel/adapters/telegram.js.map +1 -0
  55. package/dist/channel/attachment-handler.d.ts +15 -0
  56. package/dist/channel/attachment-handler.js +88 -0
  57. package/dist/channel/attachment-handler.js.map +1 -0
  58. package/dist/channel/factory.d.ts +12 -0
  59. package/dist/channel/factory.js +67 -0
  60. package/dist/channel/factory.js.map +1 -0
  61. package/dist/channel/ipc-bridge.d.ts +26 -0
  62. package/dist/channel/ipc-bridge.js +220 -0
  63. package/dist/channel/ipc-bridge.js.map +1 -0
  64. package/dist/channel/mcp-server.d.ts +10 -0
  65. package/dist/channel/mcp-server.js +288 -0
  66. package/dist/channel/mcp-server.js.map +1 -0
  67. package/dist/channel/mcp-tools.d.ts +17 -0
  68. package/dist/channel/mcp-tools.js +110 -0
  69. package/dist/channel/mcp-tools.js.map +1 -0
  70. package/dist/channel/message-bus.d.ts +17 -0
  71. package/dist/channel/message-bus.js +86 -0
  72. package/dist/channel/message-bus.js.map +1 -0
  73. package/dist/channel/message-queue.d.ts +39 -0
  74. package/dist/channel/message-queue.js +253 -0
  75. package/dist/channel/message-queue.js.map +1 -0
  76. package/dist/channel/tool-router.d.ts +6 -0
  77. package/dist/channel/tool-router.js +75 -0
  78. package/dist/channel/tool-router.js.map +1 -0
  79. package/dist/channel/tool-tracker.d.ts +13 -0
  80. package/dist/channel/tool-tracker.js +58 -0
  81. package/dist/channel/tool-tracker.js.map +1 -0
  82. package/dist/channel/types.d.ts +118 -0
  83. package/dist/channel/types.js +2 -0
  84. package/dist/channel/types.js.map +1 -0
  85. package/dist/chat-export.d.ts +4 -0
  86. package/dist/chat-export.js +91 -0
  87. package/dist/chat-export.js.map +1 -0
  88. package/dist/classic-channel-manager.d.ts +59 -0
  89. package/dist/classic-channel-manager.js +193 -0
  90. package/dist/classic-channel-manager.js.map +1 -0
  91. package/dist/cli.d.ts +2 -0
  92. package/dist/cli.js +1833 -0
  93. package/dist/cli.js.map +1 -0
  94. package/dist/config.d.ts +9 -0
  95. package/dist/config.js +118 -0
  96. package/dist/config.js.map +1 -0
  97. package/dist/context-guardian.d.ts +26 -0
  98. package/dist/context-guardian.js +73 -0
  99. package/dist/context-guardian.js.map +1 -0
  100. package/dist/cost-guard.d.ts +36 -0
  101. package/dist/cost-guard.js +147 -0
  102. package/dist/cost-guard.js.map +1 -0
  103. package/dist/daemon-entry.d.ts +1 -0
  104. package/dist/daemon-entry.js +29 -0
  105. package/dist/daemon-entry.js.map +1 -0
  106. package/dist/daemon.d.ts +152 -0
  107. package/dist/daemon.js +1714 -0
  108. package/dist/daemon.js.map +1 -0
  109. package/dist/daily-summary.d.ts +13 -0
  110. package/dist/daily-summary.js +55 -0
  111. package/dist/daily-summary.js.map +1 -0
  112. package/dist/event-log.d.ts +36 -0
  113. package/dist/event-log.js +100 -0
  114. package/dist/event-log.js.map +1 -0
  115. package/dist/export-import.d.ts +2 -0
  116. package/dist/export-import.js +162 -0
  117. package/dist/export-import.js.map +1 -0
  118. package/dist/fleet-context.d.ts +61 -0
  119. package/dist/fleet-context.js +4 -0
  120. package/dist/fleet-context.js.map +1 -0
  121. package/dist/fleet-dashboard-html.d.ts +6 -0
  122. package/dist/fleet-dashboard-html.js +443 -0
  123. package/dist/fleet-dashboard-html.js.map +1 -0
  124. package/dist/fleet-health-server.d.ts +35 -0
  125. package/dist/fleet-health-server.js +290 -0
  126. package/dist/fleet-health-server.js.map +1 -0
  127. package/dist/fleet-instructions.d.ts +5 -0
  128. package/dist/fleet-instructions.js +161 -0
  129. package/dist/fleet-instructions.js.map +1 -0
  130. package/dist/fleet-manager.d.ts +212 -0
  131. package/dist/fleet-manager.js +3655 -0
  132. package/dist/fleet-manager.js.map +1 -0
  133. package/dist/fleet-rpc-handlers.d.ts +42 -0
  134. package/dist/fleet-rpc-handlers.js +356 -0
  135. package/dist/fleet-rpc-handlers.js.map +1 -0
  136. package/dist/fleet-system-prompt.d.ts +11 -0
  137. package/dist/fleet-system-prompt.js +61 -0
  138. package/dist/fleet-system-prompt.js.map +1 -0
  139. package/dist/general-knowledge/skills.md +177 -0
  140. package/dist/hang-detector.d.ts +16 -0
  141. package/dist/hang-detector.js +53 -0
  142. package/dist/hang-detector.js.map +1 -0
  143. package/dist/index.d.ts +8 -0
  144. package/dist/index.js +6 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/instance-lifecycle.d.ts +90 -0
  147. package/dist/instance-lifecycle.js +592 -0
  148. package/dist/instance-lifecycle.js.map +1 -0
  149. package/dist/instructions.d.ts +15 -0
  150. package/dist/instructions.js +90 -0
  151. package/dist/instructions.js.map +1 -0
  152. package/dist/logger.d.ts +7 -0
  153. package/dist/logger.js +84 -0
  154. package/dist/logger.js.map +1 -0
  155. package/dist/outbound-handlers.d.ts +51 -0
  156. package/dist/outbound-handlers.js +739 -0
  157. package/dist/outbound-handlers.js.map +1 -0
  158. package/dist/outbound-schemas.d.ts +238 -0
  159. package/dist/outbound-schemas.js +248 -0
  160. package/dist/outbound-schemas.js.map +1 -0
  161. package/dist/paths.d.ts +10 -0
  162. package/dist/paths.js +42 -0
  163. package/dist/paths.js.map +1 -0
  164. package/dist/plugin/agend/.claude-plugin/plugin.json +5 -0
  165. package/dist/quickstart.d.ts +1 -0
  166. package/dist/quickstart.js +595 -0
  167. package/dist/quickstart.js.map +1 -0
  168. package/dist/routing-engine.d.ts +22 -0
  169. package/dist/routing-engine.js +44 -0
  170. package/dist/routing-engine.js.map +1 -0
  171. package/dist/safe-async.d.ts +6 -0
  172. package/dist/safe-async.js +20 -0
  173. package/dist/safe-async.js.map +1 -0
  174. package/dist/scheduler/db.d.ts +37 -0
  175. package/dist/scheduler/db.js +360 -0
  176. package/dist/scheduler/db.js.map +1 -0
  177. package/dist/scheduler/db.test.d.ts +1 -0
  178. package/dist/scheduler/db.test.js +92 -0
  179. package/dist/scheduler/db.test.js.map +1 -0
  180. package/dist/scheduler/index.d.ts +4 -0
  181. package/dist/scheduler/index.js +4 -0
  182. package/dist/scheduler/index.js.map +1 -0
  183. package/dist/scheduler/scheduler.d.ts +44 -0
  184. package/dist/scheduler/scheduler.js +197 -0
  185. package/dist/scheduler/scheduler.js.map +1 -0
  186. package/dist/scheduler/scheduler.test.d.ts +1 -0
  187. package/dist/scheduler/scheduler.test.js +119 -0
  188. package/dist/scheduler/scheduler.test.js.map +1 -0
  189. package/dist/scheduler/types.d.ts +107 -0
  190. package/dist/scheduler/types.js +7 -0
  191. package/dist/scheduler/types.js.map +1 -0
  192. package/dist/service-installer.d.ts +17 -0
  193. package/dist/service-installer.js +182 -0
  194. package/dist/service-installer.js.map +1 -0
  195. package/dist/setup-wizard.d.ts +48 -0
  196. package/dist/setup-wizard.js +701 -0
  197. package/dist/setup-wizard.js.map +1 -0
  198. package/dist/statusline-watcher.d.ts +34 -0
  199. package/dist/statusline-watcher.js +73 -0
  200. package/dist/statusline-watcher.js.map +1 -0
  201. package/dist/stt.d.ts +10 -0
  202. package/dist/stt.js +33 -0
  203. package/dist/stt.js.map +1 -0
  204. package/dist/tmux-control.d.ts +52 -0
  205. package/dist/tmux-control.js +207 -0
  206. package/dist/tmux-control.js.map +1 -0
  207. package/dist/tmux-manager.d.ts +44 -0
  208. package/dist/tmux-manager.js +218 -0
  209. package/dist/tmux-manager.js.map +1 -0
  210. package/dist/topic-archiver.d.ts +40 -0
  211. package/dist/topic-archiver.js +103 -0
  212. package/dist/topic-archiver.js.map +1 -0
  213. package/dist/topic-commands.d.ts +28 -0
  214. package/dist/topic-commands.js +359 -0
  215. package/dist/topic-commands.js.map +1 -0
  216. package/dist/transcript-monitor.d.ts +23 -0
  217. package/dist/transcript-monitor.js +164 -0
  218. package/dist/transcript-monitor.js.map +1 -0
  219. package/dist/types.d.ts +211 -0
  220. package/dist/types.js +2 -0
  221. package/dist/types.js.map +1 -0
  222. package/dist/ui/dashboard.html +719 -0
  223. package/dist/web-api.d.ts +101 -0
  224. package/dist/web-api.js +648 -0
  225. package/dist/web-api.js.map +1 -0
  226. package/dist/webhook-emitter.d.ts +15 -0
  227. package/dist/webhook-emitter.js +41 -0
  228. package/dist/webhook-emitter.js.map +1 -0
  229. package/dist/workflow-templates/default.md +35 -0
  230. package/package.json +76 -0
  231. package/templates/launchd.plist.ejs +31 -0
  232. package/templates/systemd.service.ejs +16 -0
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ <p align="center">
2
+ <h1 align="center">AgEnD</h1>
3
+ <p align="center">
4
+ <strong>Run a fleet of AI coding agents from your phone.</strong>
5
+ </p>
6
+ <p align="center">
7
+ <a href="https://www.npmjs.com/package/@suzuke/agend"><img src="https://img.shields.io/npm/v/@suzuke/agend" alt="npm"></a>
8
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
9
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%2020-green.svg" alt="Node.js >= 20"></a>
10
+ </p>
11
+ </p>
12
+
13
+ AgEnD (**Agent Engineering Daemon**) turns your Telegram or Discord into a command center for AI coding agents. One bot, multiple CLI backends, unlimited projects — each running as an independent session with crash recovery and zero babysitting.
14
+
15
+ <p align="center">
16
+ <code>You → Telegram/Discord → AgEnD → Fleet of AI Agents → Results back to your phone</code>
17
+ </p>
18
+
19
+ [繁體中文](README.zh-TW.md) · [Documentation](docs/features.md) · [CLI Reference](docs/cli.md)
20
+
21
+ ---
22
+
23
+ ## Why AgEnD?
24
+
25
+ | Without AgEnD | With AgEnD |
26
+ |---|---|
27
+ | Close the terminal, agent goes offline | Runs as a system service — survives reboots |
28
+ | One terminal = one project | One bot, unlimited projects running in parallel |
29
+ | Long-running sessions accumulate stale context | CLI auto-compact + crash recovery with context snapshots |
30
+ | No idea what your agents are doing overnight | Daily cost reports + hang detection alerts |
31
+ | Agents work in silos, can't coordinate | Peer-to-peer collaboration via MCP tools |
32
+ | Runaway costs from unattended sessions | Per-instance daily spending limits with auto-pause |
33
+
34
+ ## Feature Highlights
35
+
36
+ 🚀 **Fleet Management** — One bot, N projects. Each Telegram Forum Topic is an isolated agent session.
37
+
38
+ 🔄 **Multi-Backend** — Claude Code, Gemini CLI, Codex, OpenCode, Kiro CLI. Switch or mix freely.
39
+
40
+ 🤝 **Agent Collaboration** — Agents discover, wake, and message each other via MCP tools. A General Topic routes tasks to the right agent using natural language.
41
+
42
+ 📱 **Mobile Control** — Approve tool use, restart sessions, and manage your fleet from Telegram inline buttons.
43
+
44
+ 🛡️ **Autonomous & Safe** — Cost guards, hang detection, model failover, and crash recovery keep your fleet running without babysitting.
45
+
46
+ ⏰ **Persistent Schedules** — Cron-based tasks backed by SQLite. Survives restarts.
47
+
48
+ 🎤 **Voice Messages** — Talk to your agents with Groq Whisper transcription.
49
+
50
+ 📄 **HTML Chat Export** — Export any agent session as a self-contained HTML file for sharing or archiving.
51
+
52
+ 🪞 **Mirror Topic** — Cross-instance visibility. Watch another agent's work in real time from a separate topic.
53
+
54
+ 🖥️ **Web Dashboard** — Live fleet monitoring in the browser with SSE updates and integrated chat UI.
55
+
56
+ 🔌 **Extensible** — Discord adapter, webhook notifications, health endpoint, external session support via IPC.
57
+
58
+ 👥 **Teams & Task Board** — Named groups for targeted broadcasting. Shared task board for multi-step work tracking across instances.
59
+
60
+ 📋 **Fleet Templates** — Define reusable fleet configurations. Deploy multi-instance setups with one command, each with its own git worktree.
61
+
62
+ ## Quick Start
63
+
64
+ One-liner (macOS / Linux — installs Node.js via nvm + tmux + agend, then runs quickstart):
65
+
66
+ ```bash
67
+ curl -fsSL https://suzuke.github.io/AgEnD/install.sh | bash
68
+ ```
69
+
70
+ Or install manually:
71
+
72
+ ```bash
73
+ # Option A: One-line install (Linux / macOS / WSL)
74
+ curl -fsSL https://suzuke.github.io/AgEnD/install.sh | bash
75
+
76
+ # Option B: Manual install
77
+ npm install -g @suzuke/agend # 1. Install
78
+ agend quickstart # 2. Setup — bot token, backend, done
79
+ agend fleet start # 3. Launch your fleet 🎉
80
+ ```
81
+
82
+ Open Telegram, send a message to your bot, and start coding from your phone.
83
+
84
+ > **Discord?** `agend quickstart` supports Discord too — install the plugin first: `npm install -g @suzuke/agend-plugin-discord`. See [Discord setup guide](docs/features.md#discord-adapter-mvp).
85
+
86
+ ## How It Works
87
+
88
+ ```mermaid
89
+ graph LR
90
+ You["You<br/>(Phone / PC)"] <-->|messages| Channel["Telegram / Discord<br/>/ Web UI"]
91
+ Channel <-->|routing| Daemon["AgEnD Daemon"]
92
+
93
+ subgraph Fleet
94
+ Daemon --> General["General<br/>Dispatcher"]
95
+ Daemon --> A["Instance A<br/>Claude Code<br/>Project X"]
96
+ Daemon --> B["Instance B<br/>Gemini CLI<br/>Project Y"]
97
+ A <-.->|MCP Tools| B
98
+ General -.->|routes tasks| A
99
+ General -.->|routes tasks| B
100
+ end
101
+ ```
102
+
103
+ 1. **You send a message** to your Telegram/Discord bot
104
+ 2. Messages sent to the **General Topic** are interpreted and routed to the right agent. Messages to a specific topic go directly to that instance.
105
+ 3. **Agent instances** run in isolated tmux sessions, each with its own project and CLI backend
106
+ 4. **Agents collaborate** peer-to-peer via MCP tools — delegating tasks, sharing context, reporting results
107
+ 5. **Results flow back** to your chat. Permission requests arrive as inline buttons.
108
+
109
+ ## Supported Backends
110
+
111
+ | Backend | Install | Auth |
112
+ |---------|---------|------|
113
+ | Claude Code | `curl -fsSL https://claude.ai/install.sh \| bash` | `claude` (OAuth) or `ANTHROPIC_API_KEY` |
114
+ | OpenAI Codex | `npm i -g @openai/codex` | `codex` (ChatGPT login) or `OPENAI_API_KEY` |
115
+ | Gemini CLI | `npm i -g @google/gemini-cli` | `gemini` (Google OAuth) |
116
+ | OpenCode | `curl -fsSL https://opencode.ai/install \| bash` | `opencode` (configure provider) |
117
+ | Kiro CLI | `brew install --cask kiro-cli` | `kiro-cli login` (AWS Builder ID) |
118
+
119
+ ## Requirements
120
+
121
+ - Node.js >= 20
122
+ - tmux
123
+ - One of the supported AI coding CLIs (installed and authenticated)
124
+ - Telegram bot token ([@BotFather](https://t.me/BotFather)) or Discord bot token
125
+ - Groq API key (optional, for voice)
126
+
127
+ > **⚠️** All CLI backends run with `--dangerously-skip-permissions` (or equivalent). See [Security](SECURITY.md).
128
+
129
+ > **WSL (Windows Subsystem for Linux):** Fully supported. The install script auto-detects WSL and avoids using Windows `node.exe` from PATH. If you encounter PATH issues, add to `/etc/wsl.conf`:
130
+ > ```ini
131
+ > [interop]
132
+ > appendWindowsPath=false
133
+ > ```
134
+ > Then restart WSL (`wsl --shutdown`). Install with: `curl -fsSL https://suzuke.github.io/AgEnD/install.sh | bash`
135
+
136
+ ## Documentation
137
+
138
+ - [Features](docs/features.md) — detailed feature documentation
139
+ - [CLI Reference](docs/cli.md) — all commands and options
140
+ - [Configuration](docs/configuration.md) — fleet.yaml complete reference
141
+ - [Security](SECURITY.md) — trust model and hardening
142
+
143
+ ## Discord ClassicBot
144
+
145
+ ClassicBot lets users start AI agents in any Discord text channel using slash commands — no forum topics required.
146
+
147
+ ### Setup
148
+
149
+ ```bash
150
+ # 1. Install Discord plugin
151
+ npm install -g @suzuke/agend-plugin-discord
152
+
153
+ # 2. Run quickstart (select Discord)
154
+ agend quickstart
155
+
156
+ # 3. Start the fleet
157
+ agend fleet start
158
+ ```
159
+
160
+ The quickstart will set up both `fleet.yaml` and `classicBot.yaml`. Run `agend quickstart` again to add users or guilds to existing config.
161
+
162
+ ### Usage
163
+
164
+ | Command | Description |
165
+ |---------|-------------|
166
+ | `/start` | Start an agent in the current channel |
167
+ | `/chat <message>` | Send a message to the agent |
168
+ | `/stop` | Stop the agent in the current channel |
169
+
170
+ ### Server Whitelist
171
+
172
+ Control which Discord servers can use ClassicBot via `~/.agend/classicBot.yaml`:
173
+
174
+ ```yaml
175
+ defaults:
176
+ backend: claude-code
177
+ allowed_guilds: # Only these servers can /start
178
+ - "1496855124440780912"
179
+ - "9876543210123456789"
180
+ ```
181
+
182
+ - **Empty or omitted** `allowed_guilds` → all servers allowed (default)
183
+ - **Primary guild** (fleet.yaml `group_id`) → full access (topic mode + ClassicBot)
184
+ - **Whitelisted guilds** → ClassicBot only (`/start`, `/chat`, `/stop`)
185
+ - **Hot reload** — changes detected every 30 seconds, no restart needed
186
+
187
+ ### Per-Channel Backend
188
+
189
+ Override the backend for specific channels:
190
+
191
+ ```yaml
192
+ defaults:
193
+ backend: claude-code
194
+ channels:
195
+ "1234567890": # Discord channel ID
196
+ name: dev-help
197
+ backend: gemini-cli # Override for this channel
198
+ ```
199
+
200
+ Backend fallback: channel → `defaults.backend` → `fleet.yaml` defaults → `claude-code`
201
+
202
+ ## Known Limitations
203
+
204
+ - macOS (launchd) and Linux (systemd) supported; Windows is not
205
+ - Official Telegram plugin in global `enabledPlugins` causes 409 polling conflicts
206
+ - OpenCode and Kiro CLI do not read MCP server `instructions` field — fleet context and workflow templates are not injected into these backends' system prompts. Awaiting upstream fix.
207
+
208
+ ## License
209
+
210
+ MIT
@@ -0,0 +1,134 @@
1
+ <p align="center">
2
+ <h1 align="center">AgEnD</h1>
3
+ <p align="center">
4
+ <strong>用手機管理一整個 AI coding agent 團隊。</strong>
5
+ </p>
6
+ <p align="center">
7
+ <a href="https://www.npmjs.com/package/@suzuke/agend"><img src="https://img.shields.io/npm/v/@suzuke/agend" alt="npm"></a>
8
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
9
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%2020-green.svg" alt="Node.js >= 20"></a>
10
+ </p>
11
+ </p>
12
+
13
+ AgEnD(**Agent Engineering Daemon**)把你的 Telegram 或 Discord 變成 AI coding agent 的指揮中心。一個 bot,多種 CLI 後端,無限專案 — 每個都是獨立 session,crash 自動恢復,不用顧。
14
+
15
+ <p align="center">
16
+ <code>你 → Telegram/Discord → AgEnD → AI Agent 團隊 → 結果回到你的手機</code>
17
+ </p>
18
+
19
+ [English](README.md) · [功能文件](docs/features.md) · [CLI 參考](docs/cli.md)
20
+
21
+ ---
22
+
23
+ ## 為什麼用 AgEnD?
24
+
25
+ | 沒有 AgEnD | 有 AgEnD |
26
+ |---|---|
27
+ | 關掉終端機,agent 就斷線 | 系統服務常駐,重開機也不怕 |
28
+ | 一個終端機 = 一個專案 | 一個 bot,無限專案同時跑 |
29
+ | 長時間 session 累積過時 context | 依 max age 自動輪替 session,保持新鮮 |
30
+ | 不知道 agent 半夜在幹嘛 | 每日花費報告 + 卡住偵測通知 |
31
+ | Agent 各做各的,無法協作 | 點對點協作,透過 MCP tools |
32
+ | 無人看管時帳單暴增 | 每個 instance 每日花費上限,自動暫停 |
33
+
34
+ ## 功能亮點
35
+
36
+ 🚀 **Fleet 管理** — 一個 bot、N 個專案。每個 Telegram Forum Topic 就是獨立的 agent session。
37
+
38
+ 🔄 **多後端支援** — Claude Code、Gemini CLI、Codex、OpenCode、Kiro CLI,自由切換或混用。
39
+
40
+ 🤝 **Agent 協作** — Agent 之間透過 MCP tools 互相發現、喚醒、傳訊。General Topic 用自然語言把任務路由到對的 agent。
41
+
42
+ 📱 **手機操控** — 從 Telegram inline 按鈕核准工具使用、重啟 session、管理整個 fleet。
43
+
44
+ 🛡️ **自主又安全** — 花費上限、卡住偵測、model failover、context 輪替,fleet 不用顧也能穩穩跑。
45
+
46
+ ⏰ **持久化排程** — cron 排程任務,SQLite 儲存,重啟不遺失。
47
+
48
+ 🎤 **語音訊息** — 用 Groq Whisper 轉文字,用說的跟 agent 溝通。
49
+
50
+ 📄 **HTML 對話匯出** — 把任何 agent session 匯出成獨立 HTML 檔,方便分享或存檔。
51
+
52
+ 🪞 **Mirror Topic** — 跨 instance 可見性。從另一個 topic 即時觀看其他 agent 的工作。
53
+
54
+ 🖥️ **Web Dashboard** — 瀏覽器即時 fleet 監控,SSE 更新 + 整合聊天介面。
55
+
56
+ 🔌 **可擴充** — Discord adapter、webhook 通知、health endpoint、外部 session 透過 IPC 連入。
57
+
58
+ ## 開始用
59
+
60
+ 一行安裝(macOS / Linux — 自動裝 Node.js(經 nvm)+ tmux + agend,完成後跑 quickstart):
61
+
62
+ ```bash
63
+ curl -fsSL https://suzuke.github.io/AgEnD/install.sh | bash
64
+ ```
65
+
66
+ 或手動安裝:
67
+
68
+ ```bash
69
+ npm install -g @suzuke/agend # 1. 安裝
70
+ agend quickstart # 2. 設定 — bot token、backend,搞定
71
+ agend fleet start # 3. 啟動 fleet 🎉
72
+ ```
73
+
74
+ 打開 Telegram,傳訊息給你的 bot,開始用手機寫 code。
75
+
76
+ ## 運作原理
77
+
78
+ ```mermaid
79
+ graph LR
80
+ You["你<br/>(手機 / 電腦)"] <-->|訊息| Channel["Telegram / Discord<br/>/ Web UI"]
81
+ Channel <-->|路由| Daemon["AgEnD Daemon"]
82
+
83
+ subgraph Fleet
84
+ Daemon --> General["General<br/>Dispatcher"]
85
+ Daemon --> A["Instance A<br/>Claude Code<br/>專案 X"]
86
+ Daemon --> B["Instance B<br/>Gemini CLI<br/>專案 Y"]
87
+ A <-.->|MCP Tools| B
88
+ General -.->|路由任務| A
89
+ General -.->|路由任務| B
90
+ end
91
+ ```
92
+
93
+ 1. **你傳訊息**給 Telegram/Discord bot
94
+ 2. 傳到 **General Topic** 的訊息會被解讀並路由到對的 agent。傳到特定 topic 的訊息則直接送到該 instance。
95
+ 3. **Agent instance** 在獨立的 tmux session 跑,各有自己的專案和 CLI 後端
96
+ 4. **Agent 之間協作** — 透過 MCP tools 委派任務、分享 context、回報結果
97
+ 5. **結果回傳**到你的聊天室。權限請求以 inline 按鈕呈現。
98
+
99
+ ## 支援的後端
100
+
101
+ | Backend | 安裝 | 認證 |
102
+ |---------|------|------|
103
+ | Claude Code | `curl -fsSL https://claude.ai/install.sh \| bash` | `claude`(OAuth)或 `ANTHROPIC_API_KEY` |
104
+ | OpenAI Codex | `npm i -g @openai/codex` | `codex`(ChatGPT 登入)或 `OPENAI_API_KEY` |
105
+ | Gemini CLI | `npm i -g @google/gemini-cli` | `gemini`(Google OAuth) |
106
+ | OpenCode | `curl -fsSL https://opencode.ai/install \| bash` | `opencode`(設定 provider) |
107
+ | Kiro CLI | `brew install --cask kiro-cli` | `kiro-cli login`(AWS Builder ID) |
108
+
109
+ ## 系統需求
110
+
111
+ - Node.js >= 20
112
+ - tmux
113
+ - 以下任一 AI coding CLI(需安裝並完成認證)
114
+ - Telegram bot token([@BotFather](https://t.me/BotFather))或 Discord bot token
115
+ - Groq API key(選用,語音轉文字用)
116
+
117
+ > **⚠️** 所有 CLI 後端都以 `--dangerously-skip-permissions`(或等效參數)執行。詳見 [Security](SECURITY.md)。
118
+
119
+ ## 文件
120
+
121
+ - [Features](docs/features.md) — 功能詳細說明
122
+ - [CLI Reference](docs/cli.md) — 所有指令與選項
123
+ - [Configuration](docs/configuration.zh-TW.md) — fleet.yaml 完整設定參考
124
+ - [Security](SECURITY.md) — 信任模型與安全強化
125
+
126
+ ## 已知限制
127
+
128
+ - 支援 macOS(launchd)和 Linux(systemd),不支援 Windows
129
+ - 全域 `enabledPlugins` 裡有官方 Telegram plugin 會造成 409 polling 衝突
130
+ - OpenCode 和 Kiro CLI 不讀取 MCP server 的 `instructions` 欄位 — fleet context 和 workflow template 不會注入到這些 backend 的 system prompt。等待上游修復。
131
+
132
+ ## 授權
133
+
134
+ MIT
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Resolve the access.json path for an instance.
3
+ * Topic mode uses fleet-level access; otherwise per-instance.
4
+ *
5
+ * Throws if `instance` is not a safe path segment (per-instance mode only;
6
+ * topic mode does not embed `instance` in the returned path).
7
+ */
8
+ export declare function resolveAccessPathFromConfig(dataDir: string, instance: string, fleetChannel: {
9
+ mode?: string;
10
+ } | undefined): string;
@@ -0,0 +1,32 @@
1
+ import { join } from "node:path";
2
+ /**
3
+ * Conservative whitelist for an instance name when it is going to be used as a
4
+ * path segment. Allows letters, digits, `_`, `-`, `.`. Empty / pure-`.` /
5
+ * pure-`..` is rejected so we cannot escape `dataDir/instances/`.
6
+ *
7
+ * Defence-in-depth: callers (CLI / fleet config loader) already constrain
8
+ * instance names, but `resolveAccessPathFromConfig` is invoked from several
9
+ * entry points and the consequence of a traversal here is reading or writing
10
+ * an attacker-supplied file path.
11
+ */
12
+ const VALID_INSTANCE_NAME = /^[A-Za-z0-9._-]+$/;
13
+ function assertSafeInstanceName(instance) {
14
+ if (!VALID_INSTANCE_NAME.test(instance) || instance === "." || instance === "..") {
15
+ throw new Error(`Invalid instance name "${instance}" — must match ${VALID_INSTANCE_NAME}`);
16
+ }
17
+ }
18
+ /**
19
+ * Resolve the access.json path for an instance.
20
+ * Topic mode uses fleet-level access; otherwise per-instance.
21
+ *
22
+ * Throws if `instance` is not a safe path segment (per-instance mode only;
23
+ * topic mode does not embed `instance` in the returned path).
24
+ */
25
+ export function resolveAccessPathFromConfig(dataDir, instance, fleetChannel) {
26
+ if (fleetChannel?.mode === "topic") {
27
+ return join(dataDir, "access", "access.json");
28
+ }
29
+ assertSafeInstanceName(instance);
30
+ return join(dataDir, "instances", instance, "access.json");
31
+ }
32
+ //# sourceMappingURL=access-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-path.js","sourceRoot":"","sources":["../src/access-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;GASG;AACH,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEhD,SAAS,sBAAsB,CAAC,QAAgB;IAC9C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,kBAAkB,mBAAmB,EAAE,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAAe,EACf,QAAgB,EAChB,YAA2C;IAE3C,IAAI,YAAY,EAAE,IAAI,KAAK,OAAO,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAChD,CAAC;IACD,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { ChannelAdapter, SendOpts, SentMessage } from "./channel/types.js";
2
+ import type { AccessManager } from "./channel/access-manager.js";
3
+ import type { ChannelConfig } from "./types.js";
4
+ /**
5
+ * AdapterWorld encapsulates a single channel adapter with its associated
6
+ * access manager and config. Each platform (Telegram, Discord) gets its
7
+ * own world. Instances are bound to exactly one world.
8
+ */
9
+ export declare class AdapterWorld {
10
+ readonly id: string;
11
+ readonly adapter: ChannelAdapter;
12
+ readonly accessManager: AccessManager;
13
+ readonly channelConfig: ChannelConfig;
14
+ botUsername?: string;
15
+ botUserId?: string;
16
+ constructor(id: string, adapter: ChannelAdapter, accessManager: AccessManager, channelConfig: ChannelConfig);
17
+ get groupId(): string;
18
+ get type(): string;
19
+ sendText(chatId: string, text: string, opts?: SendOpts): Promise<SentMessage>;
20
+ react(chatId: string, messageId: string, emoji: string): Promise<void>;
21
+ editMessage(chatId: string, messageId: string, text: string): Promise<void>;
22
+ downloadAttachment(fileId: string): Promise<string>;
23
+ isAllowed(userId: string | number): boolean;
24
+ stop(): Promise<void>;
25
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * AdapterWorld encapsulates a single channel adapter with its associated
3
+ * access manager and config. Each platform (Telegram, Discord) gets its
4
+ * own world. Instances are bound to exactly one world.
5
+ */
6
+ export class AdapterWorld {
7
+ id;
8
+ adapter;
9
+ accessManager;
10
+ channelConfig;
11
+ botUsername;
12
+ botUserId;
13
+ constructor(id, adapter, accessManager, channelConfig) {
14
+ this.id = id;
15
+ this.adapter = adapter;
16
+ this.accessManager = accessManager;
17
+ this.channelConfig = channelConfig;
18
+ }
19
+ get groupId() { return String(this.channelConfig.group_id ?? ""); }
20
+ get type() { return this.channelConfig.type; }
21
+ // ── Thin wrappers over adapter ──
22
+ sendText(chatId, text, opts) {
23
+ return this.adapter.sendText(chatId, text, opts);
24
+ }
25
+ react(chatId, messageId, emoji) {
26
+ return this.adapter.react(chatId, messageId, emoji);
27
+ }
28
+ editMessage(chatId, messageId, text) {
29
+ return this.adapter.editMessage(chatId, messageId, text);
30
+ }
31
+ downloadAttachment(fileId) {
32
+ return this.adapter.downloadAttachment(fileId);
33
+ }
34
+ isAllowed(userId) {
35
+ return this.accessManager.isAllowed(userId);
36
+ }
37
+ async stop() {
38
+ await this.adapter.stop();
39
+ }
40
+ }
41
+ //# sourceMappingURL=adapter-world.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-world.js","sourceRoot":"","sources":["../src/adapter-world.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,OAAO,YAAY;IAKZ;IACA;IACA;IACA;IAPX,WAAW,CAAU;IACrB,SAAS,CAAU;IAEnB,YACW,EAAU,EACV,OAAuB,EACvB,aAA4B,EAC5B,aAA4B;QAH5B,OAAE,GAAF,EAAE,CAAQ;QACV,YAAO,GAAP,OAAO,CAAgB;QACvB,kBAAa,GAAb,aAAa,CAAe;QAC5B,kBAAa,GAAb,aAAa,CAAe;IACpC,CAAC;IAEJ,IAAI,OAAO,KAAa,OAAO,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3E,IAAI,IAAI,KAAa,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtD,mCAAmC;IAEnC,QAAQ,CAAC,MAAc,EAAE,IAAY,EAAE,IAAe;QACpD,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,MAAc,EAAE,SAAiB,EAAE,KAAa;QACpD,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAED,WAAW,CAAC,MAAc,EAAE,SAAiB,EAAE,IAAY;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAC3D,CAAC;IAED,kBAAkB,CAAC,MAAc;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,SAAS,CAAC,MAAuB;QAC/B,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,50 @@
1
+ # AgEnD Agent CLI Reference
2
+ <!-- agend-cli instructions v1 -->
3
+
4
+ You are an agent managed by AgEnD. Use `agend-agent` commands in bash to communicate.
5
+ All commands output JSON.
6
+
7
+ ## Message Types You Receive
8
+
9
+ 1. **`[user:NAME via telegram] text`** — A human sent you a message.
10
+ Reply: `agend-agent reply "your response"`
11
+
12
+ 2. **`[from:INSTANCE-NAME] text`** — Another agent sent you a message.
13
+ Reply: `agend-agent send INSTANCE-NAME "your response"`
14
+
15
+ 3. **`[delegate_task] ...`** — You've been assigned a task.
16
+ When done: `agend-agent report REQUESTER "summary of results"`
17
+
18
+ ## Quick Reference
19
+
20
+ ```bash
21
+ # Communication
22
+ agend-agent reply "text" # Reply to user
23
+ agend-agent send TARGET "message" # Message another agent
24
+ agend-agent delegate TARGET "task" # Assign work
25
+ agend-agent report TARGET "summary" # Report results
26
+ agend-agent ask TARGET "question" # Request info
27
+ agend-agent broadcast "message" # Message all agents
28
+
29
+ # Instance Management
30
+ agend-agent list # List running agents
31
+ agend-agent describe NAME # Get agent details
32
+ agend-agent start NAME # Start stopped agent
33
+
34
+ # Task Board
35
+ agend-agent task create "title" # Create task
36
+ agend-agent task list # List tasks
37
+ agend-agent task claim ID # Claim task
38
+ agend-agent task done ID "result" # Complete task
39
+
40
+ # Decisions
41
+ agend-agent decision-post "title" "content" # Post decision
42
+ agend-agent decision-list # List decisions
43
+ ```
44
+
45
+ ## Rules
46
+
47
+ - `[user:... via telegram]` → use `agend-agent reply` (NOT `agend-agent send`)
48
+ - `[from:INSTANCE]` → use `agend-agent send` (NOT `agend-agent reply`)
49
+ - Task flow: `agend-agent delegate` → silent work → `agend-agent report`. Zero messages in between.
50
+ - Never send acknowledgment-only messages. Only send messages with actionable content.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};