camelagi 0.5.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 (249) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +224 -0
  3. package/camelagi.mjs +2 -0
  4. package/config.example.yaml +107 -0
  5. package/dist/agent/agent-openai.js +206 -0
  6. package/dist/agent/agent-openai.js.map +1 -0
  7. package/dist/agent/agent-sdk.js +209 -0
  8. package/dist/agent/agent-sdk.js.map +1 -0
  9. package/dist/agent/tool-adapter.js +31 -0
  10. package/dist/agent/tool-adapter.js.map +1 -0
  11. package/dist/agent/types.js +3 -0
  12. package/dist/agent/types.js.map +1 -0
  13. package/dist/agent.js +17 -0
  14. package/dist/agent.js.map +1 -0
  15. package/dist/approval-forward.js +42 -0
  16. package/dist/approval-forward.js.map +1 -0
  17. package/dist/approvals.js +151 -0
  18. package/dist/approvals.js.map +1 -0
  19. package/dist/boot.js +34 -0
  20. package/dist/boot.js.map +1 -0
  21. package/dist/bootstrap.js +451 -0
  22. package/dist/bootstrap.js.map +1 -0
  23. package/dist/camelagi-gateway.mjs +93611 -0
  24. package/dist/camelagi-gateway.mjs.map +7 -0
  25. package/dist/channels/adapter.js +10 -0
  26. package/dist/channels/adapter.js.map +1 -0
  27. package/dist/channels/discord.js +232 -0
  28. package/dist/channels/discord.js.map +1 -0
  29. package/dist/channels/handler.js +349 -0
  30. package/dist/channels/handler.js.map +1 -0
  31. package/dist/channels/index.js +19 -0
  32. package/dist/channels/index.js.map +1 -0
  33. package/dist/channels/registry.js +71 -0
  34. package/dist/channels/registry.js.map +1 -0
  35. package/dist/channels/telegram.js +83 -0
  36. package/dist/channels/telegram.js.map +1 -0
  37. package/dist/channels/types.js +3 -0
  38. package/dist/channels/types.js.map +1 -0
  39. package/dist/chunker.js +102 -0
  40. package/dist/chunker.js.map +1 -0
  41. package/dist/cli/cmd-agents.js +65 -0
  42. package/dist/cli/cmd-agents.js.map +1 -0
  43. package/dist/cli/cmd-bootstrap.js +10 -0
  44. package/dist/cli/cmd-bootstrap.js.map +1 -0
  45. package/dist/cli/cmd-chat.js +32 -0
  46. package/dist/cli/cmd-chat.js.map +1 -0
  47. package/dist/cli/cmd-config.js +88 -0
  48. package/dist/cli/cmd-config.js.map +1 -0
  49. package/dist/cli/cmd-cron.js +120 -0
  50. package/dist/cli/cmd-cron.js.map +1 -0
  51. package/dist/cli/cmd-daemon.js +37 -0
  52. package/dist/cli/cmd-daemon.js.map +1 -0
  53. package/dist/cli/cmd-doctor.js +18 -0
  54. package/dist/cli/cmd-doctor.js.map +1 -0
  55. package/dist/cli/cmd-logs.js +30 -0
  56. package/dist/cli/cmd-logs.js.map +1 -0
  57. package/dist/cli/cmd-pairing.js +41 -0
  58. package/dist/cli/cmd-pairing.js.map +1 -0
  59. package/dist/cli/cmd-reset.js +39 -0
  60. package/dist/cli/cmd-reset.js.map +1 -0
  61. package/dist/cli/cmd-serve.js +30 -0
  62. package/dist/cli/cmd-serve.js.map +1 -0
  63. package/dist/cli/cmd-sessions.js +56 -0
  64. package/dist/cli/cmd-sessions.js.map +1 -0
  65. package/dist/cli/cmd-setup.js +11 -0
  66. package/dist/cli/cmd-setup.js.map +1 -0
  67. package/dist/cli/cmd-soul.js +43 -0
  68. package/dist/cli/cmd-soul.js.map +1 -0
  69. package/dist/cli/parse.js +50 -0
  70. package/dist/cli/parse.js.map +1 -0
  71. package/dist/cli/registry.js +15 -0
  72. package/dist/cli/registry.js.map +1 -0
  73. package/dist/cli.js +103 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/compact.js +92 -0
  76. package/dist/compact.js.map +1 -0
  77. package/dist/config.js +153 -0
  78. package/dist/config.js.map +1 -0
  79. package/dist/constants.js +21 -0
  80. package/dist/constants.js.map +1 -0
  81. package/dist/core/config.js +212 -0
  82. package/dist/core/config.js.map +1 -0
  83. package/dist/core/constants.js +21 -0
  84. package/dist/core/constants.js.map +1 -0
  85. package/dist/core/errors.js +5 -0
  86. package/dist/core/errors.js.map +1 -0
  87. package/dist/core/log.js +41 -0
  88. package/dist/core/log.js.map +1 -0
  89. package/dist/core/models.js +123 -0
  90. package/dist/core/models.js.map +1 -0
  91. package/dist/core/types.js +3 -0
  92. package/dist/core/types.js.map +1 -0
  93. package/dist/core/update-check.js +51 -0
  94. package/dist/core/update-check.js.map +1 -0
  95. package/dist/cron.js +81 -0
  96. package/dist/cron.js.map +1 -0
  97. package/dist/daemon.js +109 -0
  98. package/dist/daemon.js.map +1 -0
  99. package/dist/doctor.js +194 -0
  100. package/dist/doctor.js.map +1 -0
  101. package/dist/errors.js +5 -0
  102. package/dist/errors.js.map +1 -0
  103. package/dist/extensions/approval-forward.js +42 -0
  104. package/dist/extensions/approval-forward.js.map +1 -0
  105. package/dist/extensions/approvals.js +144 -0
  106. package/dist/extensions/approvals.js.map +1 -0
  107. package/dist/extensions/cron.js +306 -0
  108. package/dist/extensions/cron.js.map +1 -0
  109. package/dist/extensions/hooks.js +72 -0
  110. package/dist/extensions/hooks.js.map +1 -0
  111. package/dist/extensions/skills.js +97 -0
  112. package/dist/extensions/skills.js.map +1 -0
  113. package/dist/gateway/csrf.js +44 -0
  114. package/dist/gateway/csrf.js.map +1 -0
  115. package/dist/gateway/logger.js +81 -0
  116. package/dist/gateway/logger.js.map +1 -0
  117. package/dist/gateway/rate-limit.js +33 -0
  118. package/dist/gateway/rate-limit.js.map +1 -0
  119. package/dist/gateway/routes.js +315 -0
  120. package/dist/gateway/routes.js.map +1 -0
  121. package/dist/gateway/state.js +54 -0
  122. package/dist/gateway/state.js.map +1 -0
  123. package/dist/gateway/ws-handler.js +200 -0
  124. package/dist/gateway/ws-handler.js.map +1 -0
  125. package/dist/gateway-entry.js +16 -0
  126. package/dist/gateway-entry.js.map +1 -0
  127. package/dist/hooks.js +72 -0
  128. package/dist/hooks.js.map +1 -0
  129. package/dist/lanes.js +62 -0
  130. package/dist/lanes.js.map +1 -0
  131. package/dist/model.js +30 -0
  132. package/dist/model.js.map +1 -0
  133. package/dist/policy.js +22 -0
  134. package/dist/policy.js.map +1 -0
  135. package/dist/queue.js +45 -0
  136. package/dist/queue.js.map +1 -0
  137. package/dist/retry.js +96 -0
  138. package/dist/retry.js.map +1 -0
  139. package/dist/runs.js +83 -0
  140. package/dist/runs.js.map +1 -0
  141. package/dist/runtime/compact.js +99 -0
  142. package/dist/runtime/compact.js.map +1 -0
  143. package/dist/runtime/lanes.js +66 -0
  144. package/dist/runtime/lanes.js.map +1 -0
  145. package/dist/runtime/orchestrate.js +121 -0
  146. package/dist/runtime/orchestrate.js.map +1 -0
  147. package/dist/runtime/queue.js +50 -0
  148. package/dist/runtime/queue.js.map +1 -0
  149. package/dist/runtime/retry.js +127 -0
  150. package/dist/runtime/retry.js.map +1 -0
  151. package/dist/runtime/runs.js +105 -0
  152. package/dist/runtime/runs.js.map +1 -0
  153. package/dist/serve.js +209 -0
  154. package/dist/serve.js.map +1 -0
  155. package/dist/session.js +75 -0
  156. package/dist/session.js.map +1 -0
  157. package/dist/setup.js +254 -0
  158. package/dist/setup.js.map +1 -0
  159. package/dist/skills.js +89 -0
  160. package/dist/skills.js.map +1 -0
  161. package/dist/subagent.js +71 -0
  162. package/dist/subagent.js.map +1 -0
  163. package/dist/system-prompt.js +157 -0
  164. package/dist/system-prompt.js.map +1 -0
  165. package/dist/telegram/admin-bot.js +705 -0
  166. package/dist/telegram/admin-bot.js.map +1 -0
  167. package/dist/telegram/agent-bot.js +551 -0
  168. package/dist/telegram/agent-bot.js.map +1 -0
  169. package/dist/telegram/bot-approval.js +63 -0
  170. package/dist/telegram/bot-approval.js.map +1 -0
  171. package/dist/telegram/draft-stream.js +86 -0
  172. package/dist/telegram/draft-stream.js.map +1 -0
  173. package/dist/telegram/format.js +106 -0
  174. package/dist/telegram/format.js.map +1 -0
  175. package/dist/telegram/helpers.js +87 -0
  176. package/dist/telegram/helpers.js.map +1 -0
  177. package/dist/telegram/pairing-notify.js +52 -0
  178. package/dist/telegram/pairing-notify.js.map +1 -0
  179. package/dist/telegram/pairing.js +138 -0
  180. package/dist/telegram/pairing.js.map +1 -0
  181. package/dist/telegram/resolve.js +33 -0
  182. package/dist/telegram/resolve.js.map +1 -0
  183. package/dist/telegram/transcribe.js +77 -0
  184. package/dist/telegram/transcribe.js.map +1 -0
  185. package/dist/telegram/types.js +3 -0
  186. package/dist/telegram/types.js.map +1 -0
  187. package/dist/telegram/voice-wizard.js +84 -0
  188. package/dist/telegram/voice-wizard.js.map +1 -0
  189. package/dist/telegram/wizard.js +89 -0
  190. package/dist/telegram/wizard.js.map +1 -0
  191. package/dist/telegram/wizards.js +297 -0
  192. package/dist/telegram/wizards.js.map +1 -0
  193. package/dist/telegram-admin.js +800 -0
  194. package/dist/telegram-admin.js.map +1 -0
  195. package/dist/telegram.js +118 -0
  196. package/dist/telegram.js.map +1 -0
  197. package/dist/tools/cron.js +94 -0
  198. package/dist/tools/cron.js.map +1 -0
  199. package/dist/tools/edit.js +29 -0
  200. package/dist/tools/edit.js.map +1 -0
  201. package/dist/tools/exec.js +38 -0
  202. package/dist/tools/exec.js.map +1 -0
  203. package/dist/tools/fetch.js +28 -0
  204. package/dist/tools/fetch.js.map +1 -0
  205. package/dist/tools/index.js +16 -0
  206. package/dist/tools/index.js.map +1 -0
  207. package/dist/tools/memory.js +164 -0
  208. package/dist/tools/memory.js.map +1 -0
  209. package/dist/tools/patch.js +284 -0
  210. package/dist/tools/patch.js.map +1 -0
  211. package/dist/tools/read.js +26 -0
  212. package/dist/tools/read.js.map +1 -0
  213. package/dist/tools/search.js +62 -0
  214. package/dist/tools/search.js.map +1 -0
  215. package/dist/tools/subagent.js +48 -0
  216. package/dist/tools/subagent.js.map +1 -0
  217. package/dist/tools/write.js +22 -0
  218. package/dist/tools/write.js.map +1 -0
  219. package/dist/tui/commands.js +450 -0
  220. package/dist/tui/commands.js.map +1 -0
  221. package/dist/tui/components/assistant-message.js +26 -0
  222. package/dist/tui/components/assistant-message.js.map +1 -0
  223. package/dist/tui/components/chat-log.js +94 -0
  224. package/dist/tui/components/chat-log.js.map +1 -0
  225. package/dist/tui/components/custom-editor.js +40 -0
  226. package/dist/tui/components/custom-editor.js.map +1 -0
  227. package/dist/tui/components/hint-bar.js +13 -0
  228. package/dist/tui/components/hint-bar.js.map +1 -0
  229. package/dist/tui/components/tool-execution.js +73 -0
  230. package/dist/tui/components/tool-execution.js.map +1 -0
  231. package/dist/tui/components/user-message.js +19 -0
  232. package/dist/tui/components/user-message.js.map +1 -0
  233. package/dist/tui/components/welcome.js +147 -0
  234. package/dist/tui/components/welcome.js.map +1 -0
  235. package/dist/tui/context.js +3 -0
  236. package/dist/tui/context.js.map +1 -0
  237. package/dist/tui/theme.js +91 -0
  238. package/dist/tui/theme.js.map +1 -0
  239. package/dist/tui/tui.js +389 -0
  240. package/dist/tui/tui.js.map +1 -0
  241. package/dist/tui/ws-handler.js +154 -0
  242. package/dist/tui/ws-handler.js.map +1 -0
  243. package/dist/types.js +3 -0
  244. package/dist/types.js.map +1 -0
  245. package/dist/usage.js +88 -0
  246. package/dist/usage.js.map +1 -0
  247. package/dist/workspace.js +245 -0
  248. package/dist/workspace.js.map +1 -0
  249. package/package.json +74 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CamelAGI Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,224 @@
1
+ <p align="center">
2
+ <img src="assets/logo-bg.png" alt="CamelAGI Logo" width="200" />
3
+ </p>
4
+ <h1 align="center" style="border: none; padding-bottom: 0; margin-bottom: 0;">CamelAGI</h1>
5
+ <p align="center" style="font-size: 0.9em; color: #b45309; margin-top: 4px;"><strong>OpenClaw Alternative</strong></p>
6
+ <p align="center">
7
+ <strong>Your personal AI agent — powered by Claude Agent SDK.<br>Set it up once, manage everything from Telegram.</strong>
8
+ </p>
9
+ <p align="center">
10
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="MIT License"></a>
11
+ <a href="https://www.typescriptlang.org"><img src="https://img.shields.io/badge/TypeScript-5.7-blue?logo=typescript" alt="TypeScript"></a>
12
+ <a href="https://platform.claude.com/docs/en/agent-sdk/overview"><img src="https://img.shields.io/badge/Built%20with-Claude%20Agent%20SDK-orange?logo=anthropic" alt="Claude Agent SDK"></a>
13
+ <a href="https://core.telegram.org/bots"><img src="https://img.shields.io/badge/Telegram-Admin%20Bot-26A5E4?logo=telegram" alt="Telegram"></a>
14
+ <a href="https://camelagi.net"><img src="https://img.shields.io/badge/Website-camelagi.net-brown" alt="Website"></a>
15
+ </p>
16
+
17
+ <br>
18
+
19
+ CamelAGI is a self-hosted AI assistant that runs on your server and puts you in full control from your phone. One command to set up, then manage everything from Telegram — no terminal needed.
20
+
21
+ <p align="center">
22
+ <a href="https://camelagi.net"><strong>🌐 CamelAGI.net</strong></a>
23
+ </p>
24
+
25
+ ## Contents
26
+
27
+ - [Built on Claude Agent SDK](#built-on-claude-agent-sdk)
28
+ - [Admin Bot — BotFather for Your AI Server](#admin-bot--botfather-for-your-ai-server)
29
+ - [Claude Agent SDK vs pi-agent](#claude-agent-sdk-vs-pi-agent)
30
+ - [Quick Start](#quick-start)
31
+ - [Features](#features)
32
+ - [Terminal UI — `camel chat`](#terminal-ui--camel-chat)
33
+ - [Developer Experience](#developer-experience)
34
+ - [Roadmap](#roadmap)
35
+ - [Documentation](#documentation)
36
+ - [License](#license)
37
+
38
+ <br>
39
+
40
+ ## Built on Claude Agent SDK
41
+
42
+ <p align="center">
43
+ <img src="assets/Claude_Logo.png" alt="Claude Logo" width="200" />
44
+ </p>
45
+
46
+ Powered by [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) — the same runtime behind Claude Code.
47
+
48
+ > **10 tools** · **Two-tier memory** · **Extended thinking** · **Subagents** · **Context compaction** · **Multi-provider**
49
+
50
+ - **Agent Capabilities** — <span style="font-size: 0.9em; color: #d97706;">Powered by Claude Agent SDK</span>
51
+ - 10 built-in tools (shell, files, web, memory, cron)
52
+ - Extended thinking with chain-of-thought
53
+ - Subagent spawning for parallel work
54
+ - Prompt caching for efficiency
55
+ - **Memory System** — <span style="font-size: 0.9em; color: #d97706;">Powered by Claude Agent SDK</span>
56
+ - Curated MEMORY.md per agent
57
+ - Daily auto-journaling with timestamps
58
+ - Recency-boosted search (today 1.5x)
59
+ - Auto memory flush on compaction
60
+
61
+ Each agent gets isolated memory & personality:
62
+
63
+ ```
64
+ ~/.camelagi/
65
+ ├── agents/
66
+ │ ├── coder/
67
+ │ │ ├── SOUL.md ← Coder's personality
68
+ │ │ ├── MEMORY.md ← Coder's curated knowledge
69
+ │ │ └── memory/
70
+ │ │ └── 2026-03-14.md
71
+ │ └── researcher/
72
+ │ ├── SOUL.md ← Researcher's personality
73
+ │ ├── MEMORY.md ← Researcher's curated knowledge
74
+ │ └── memory/
75
+ │ └── 2026-03-14.md
76
+ └── config.yaml
77
+ ```
78
+
79
+ Each agent runs on Claude Agent SDK with its own tools, memory, and conversation history. They don't share context. Fully independent, managed from your single Admin Bot.
80
+
81
+ <br>
82
+
83
+ ## Claude Agent SDK vs pi-agent
84
+
85
+ CamelAGI uses **Claude Agent SDK**. OpenClaw uses **pi-agent-core**. Here's why that matters:
86
+
87
+ | | **Claude Agent SDK** (CamelAGI) | **pi-agent-core** (OpenClaw) |
88
+ |---|---|---|
89
+ | **Built by** | Anthropic | Third-party |
90
+ | **Tool use** | Native function calling with structured outputs | Custom tool protocol |
91
+ | **Thinking** | Extended thinking (low/medium/high) built-in | Not available |
92
+ | **Subagents** | Native agent spawning with isolated context | Custom implementation |
93
+ | **Prompt caching** | Built-in, automatic | Manual |
94
+ | **Memory** | Agent-scoped two-tier memory with recency boost | Vector DB (LanceDB) |
95
+ | **Streaming** | Native SSE streaming | Custom streaming |
96
+ | **Upgrades** | `npm update` — get Anthropic's latest improvements | Maintain custom abstractions |
97
+
98
+ > **The key difference:** Claude Agent SDK is Anthropic's own runtime. When Anthropic ships improvements to tool use, thinking, or context handling, CamelAGI gets them automatically. pi-agent is a third-party layer that must be manually updated to keep up.
99
+
100
+ <br>
101
+
102
+ ## Quick Start
103
+
104
+ **One-Liner**
105
+ ```bash
106
+ curl -fsSL https://camelAGI.ai/install.sh | bash
107
+ ```
108
+
109
+ **npm**
110
+ ```bash
111
+ npm install -g camelagi
112
+ ```
113
+
114
+ **Usage**
115
+ ```bash
116
+ camel bootstrap # Full setup: admin bot + pairing + API config
117
+ camel serve # Start the gateway (after bootstrap)
118
+ camel chat # Terminal UI
119
+ ```
120
+
121
+ <br>
122
+
123
+ ## Admin Bot — BotFather for Your AI Server
124
+
125
+ Create agents, manage config, approve users, monitor sessions, restart bots — all from Telegram. The Admin Bot is a **non-AI Telegram bot** — no LLM calls, no tokens burned, just instant commands. Think [@BotFather](https://t.me/BotFather), but for your entire AI infrastructure.
126
+
127
+ ### Getting Started
128
+
129
+ 1. Create a bot with [@BotFather](https://t.me/BotFather) on Telegram
130
+ 2. Run `camel bootstrap` and paste the bot token
131
+ 3. Send a message to your bot on Telegram — the CLI detects you
132
+ 4. Approve yourself in the CLI, then enter the OTP in Telegram
133
+ 5. Pick your AI provider and model (or skip and do it later via `/setup` in Telegram)
134
+ 6. Done — use `/newagent` in Telegram to create your first AI agent
135
+
136
+ ### Commands
137
+
138
+ | Category | Command | Description |
139
+ |----------|---------|-------------|
140
+ | **Agents** | `/newagent` | Create agent wizard |
141
+ | | `/agents` | List all agents |
142
+ | | `/deleteagent` | Delete an agent |
143
+ | | `/soul` | View/edit agent personality |
144
+ | **Config** | `/config` | View configuration |
145
+ | | `/config <key> <value>` | Update config |
146
+ | | `/setup` | API provider wizard |
147
+ | **Monitor** | `/status` | System health & stats |
148
+ | | `/sessions` | List & manage sessions |
149
+ | | `/restart` | Restart agent bots |
150
+ | **Security** | `/pairing` | Manage access requests |
151
+
152
+ <br>
153
+
154
+ ## Features
155
+
156
+ > Terminal or Telegram — same agent, same tools, same memory.
157
+
158
+ | | Feature | Description |
159
+ |---|---|---|
160
+ | ⌨️ | **camel chat — Terminal UI** | Full TUI with streaming, slash commands, model switching, session management, tool output, and markdown rendering |
161
+ | 🤖 | **Telegram — Admin Bot** | @BotFather for AI agents. Create, configure, and manage agents entirely from Telegram — instant commands, zero tokens burned |
162
+ | 💬 | **Telegram — Agent Bots** | Each agent gets its own Telegram bot. Message it like any chat — it runs tools, reads files, remembers context |
163
+ | ⚙️ | **Same Engine** | Both interfaces run the same agent loop, same 10 tools, same two-tier memory. Switch between terminal and Telegram anytime |
164
+ | 🧠 | **Agent Memory** | Each agent gets isolated two-tier memory — curated MEMORY.md + daily auto-journaling with recency-boosted search |
165
+ | ⏰ | **Cron Jobs** | Schedule AI tasks — daily summaries, monitoring, automations. Manage from Telegram, CLI, or the agent itself |
166
+ | 🛡️ | **Tool Approvals** | Human-in-the-loop safety. Approve dangerous operations from Telegram with inline buttons — even headless |
167
+ | 💭 | **Extended Thinking** | Claude reasons step by step before answering. Configure depth: off, low, medium, high |
168
+ | 🔌 | **Multi-Provider** | Anthropic, OpenAI, OpenRouter, Ollama — any OpenAI-compatible endpoint. Zero vendor lock-in |
169
+ | 🔐 | **Secure Pairing** | OTP-based user verification. No hardcoded IDs — pairing code + 5-digit OTP from Telegram |
170
+ | 🪝 | **Skills & Hooks** | Teach agents skills via Markdown. Run shell/JS hooks before and after tool calls |
171
+ | 🔄 | **Auto Compaction** | Summarizes old turns at 80% capacity. Flushes facts to memory first — nothing is lost |
172
+
173
+ <br>
174
+
175
+ ## Terminal UI — `camel chat`
176
+
177
+ Don't want to use Telegram? `camel chat` gives you a full terminal interface with the same agent capabilities.
178
+
179
+ - Streaming responses with markdown rendering
180
+ - Slash commands (`/model`, `/sessions`, `/tools`, `/compact`, `/status`, `/context`)
181
+ - Model selector overlay (`Ctrl+L`), session switcher (`Ctrl+P`)
182
+ - Tool output toggle (`Ctrl+O`), abort with `Escape`
183
+ - Shell execution with `!command`
184
+ - Agent creation wizard, SOUL.md editing
185
+ - Thinking indicators, subagent progress, approval overlay
186
+ - One-shot mode: `camel "your question"` for quick answers
187
+
188
+ <br>
189
+
190
+ ## Developer Experience
191
+
192
+ | | **CamelAGI** | **OpenClaw** |
193
+ |---|---|---|
194
+ | **Codebase size** | ~10K LOC | ~700K+ LOC |
195
+ | **AI Agent runtime** | [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) — fully documented by Anthropic, easy to extend | pi-agent & custom abstractions |
196
+
197
+ <br>
198
+
199
+ ## Roadmap
200
+
201
+ We're building CamelAGI to be the most capable open-source AI platform — for individuals and businesses alike.
202
+
203
+ | | Feature | Description |
204
+ |---|---|---|
205
+ | 📡 | **More Channels** | WhatsApp, Discord, Slack — connect your AI agents to every platform your team already uses |
206
+ | 🧩 | **ClawHub Skills** | Browse and install community skills from [clawhub.io](https://clawhub.io) — one command to add new capabilities to any agent |
207
+ | 🖥️ | **Native Desktop Apps** | Standalone macOS and Windows apps to run CamelAGI natively — no terminal, no companion app required |
208
+ | 🏢 | **Business Ready** | Deploy CamelAGI for your business — finance, accounting, operations, customer support. AI agents that understand your workflows |
209
+
210
+ <br>
211
+
212
+ ## Documentation
213
+
214
+ | Document | Description |
215
+ |----------|-------------|
216
+ | [DOCS.md](DOCS.md) | Full reference documentation |
217
+ | [GUIDE.md](GUIDE.md) | User guide with examples |
218
+ | [featuresDocs/](featuresDocs/) | Deep-dive feature docs |
219
+
220
+ <br>
221
+
222
+ ## License
223
+
224
+ MIT
package/camelagi.mjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import("./dist/cli.js");
@@ -0,0 +1,107 @@
1
+ # CamelAGI Configuration
2
+ # Copy to ~/.camelagi/config.yaml and customize
3
+
4
+ # ─── Provider & Model ─────────────────────────────────────────────
5
+ provider: anthropic # anthropic | openai
6
+ model: claude-sonnet-4-20250514 # Any model supported by your provider
7
+ apiKey: sk-ant-... # Or set ANTHROPIC_API_KEY / OPENAI_API_KEY env var
8
+ # baseUrl: https://... # Custom endpoint (OpenRouter, Ollama, etc.)
9
+
10
+ # ─── Agent Behavior ───────────────────────────────────────────────
11
+ thinking: "off" # off | low | medium | high (extended thinking)
12
+ effort: high # low | medium | high | max
13
+ maxTurns: 25 # Max tool-use iterations per message
14
+ timeoutSeconds: 300 # Per-run timeout
15
+ # maxBudgetUsd: 5 # Optional spending cap per run
16
+
17
+ # ─── Gateway Server ───────────────────────────────────────────────
18
+ serve:
19
+ port: 18789
20
+ host: 127.0.0.1
21
+ token: your-secret-token-here # Auth token for REST/WS API
22
+ rateLimit:
23
+ windowMs: 60000 # Rate limit window (ms)
24
+ max: 60 # Max requests per window
25
+
26
+ # ─── Telegram ─────────────────────────────────────────────────────
27
+ telegram:
28
+ botToken: "123456:ABC-..." # Main bot token from @BotFather
29
+ allowedUsers: [] # Telegram user IDs (auto-locked on first /start)
30
+ groups:
31
+ mentionOnly: true # In groups, only respond when @mentioned
32
+
33
+ # ─── Context Compaction ───────────────────────────────────────────
34
+ compaction:
35
+ enabled: true
36
+ maxTokens: 80000 # Trigger compaction at 80% of this value
37
+ keepTurns: 6 # Keep last N turns verbatim
38
+
39
+ # ─── Tool Policy ──────────────────────────────────────────────────
40
+ tools:
41
+ allow: [] # Whitelist (empty = all allowed)
42
+ deny: [] # Blacklist (e.g., ["exec"] to disable shell)
43
+
44
+ # ─── Approvals ────────────────────────────────────────────────────
45
+ approvals:
46
+ mode: "off" # off | smart | always
47
+ allowlist: [] # Tools that never need approval (e.g., ["read", "memory_search"])
48
+ timeoutSeconds: 120
49
+ fallback: deny # deny | allow (when approval times out)
50
+ # forwardTo: 12345 # Telegram chat ID for headless approval forwarding
51
+
52
+ # ─── Skills & Hooks ───────────────────────────────────────────────
53
+ skills:
54
+ enabled: true
55
+ deny: [] # Skill names to disable
56
+
57
+ hooks:
58
+ enabled: false # Enable lifecycle hooks (~/.camelagi/hooks/)
59
+
60
+ # ─── Retry ────────────────────────────────────────────────────────
61
+ retry:
62
+ maxRetries: 3
63
+ backoffMs: 1000 # Base backoff (exponential, capped at 30s)
64
+
65
+ # ─── Voice Transcription ─────────────────────────────────────────
66
+ # voice:
67
+ # enabled: true
68
+ # provider: groq # groq (free) | openai | deepgram
69
+ # apiKey: gsk_xxx
70
+ # model: whisper-large-v3 # auto-selected per provider if omitted
71
+ # language: en # optional BCP-47 language hint
72
+
73
+ # ─── Concurrency Lanes ───────────────────────────────────────────
74
+ lanes:
75
+ main: 3 # Max concurrent user chat runs
76
+ cron: 1 # Max concurrent cron runs
77
+ subagent: 5 # Max concurrent sub-agent runs
78
+
79
+ # ─── Boot Script ──────────────────────────────────────────────────
80
+ boot: true # Run ~/.camelagi/BOOT.md on gateway start
81
+
82
+ # ─── Cron Jobs ────────────────────────────────────────────────────
83
+ cron: []
84
+ # cron:
85
+ # - id: daily-summary
86
+ # name: Daily Summary
87
+ # schedule: "0 9 * * *" # Every day at 9 AM
88
+ # prompt: "Summarize yesterday's activity from memory"
89
+ # session: cron-summary # Dedicated session (optional)
90
+ # enabled: true
91
+
92
+ # ─── Named Agents ────────────────────────────────────────────────
93
+ agents: {}
94
+ # agents:
95
+ # coder:
96
+ # name: Coder
97
+ # model: claude-sonnet-4-20250514
98
+ # thinking: medium
99
+ # telegram:
100
+ # botToken: "789012:DEF-..."
101
+ # allowedUsers: []
102
+ # reviewer:
103
+ # name: Reviewer
104
+ # model: claude-sonnet-4-20250514
105
+ # effort: max
106
+ # telegram:
107
+ # botToken: "345678:GHI-..."
@@ -0,0 +1,206 @@
1
+ // Path 2: OpenAI-compatible with tool loop (any provider)
2
+ import OpenAI from "openai";
3
+ import { recordUsage } from "../usage.js";
4
+ import { runHooks } from "../extensions/hooks.js";
5
+ import { DEFAULT_MAX_TURNS } from "../core/constants.js";
6
+ import { adaptToolDefToOpenAI } from "./tool-adapter.js";
7
+ import { memorySearchTool, memoryGetTool, createScopedMemoryTools } from "../tools/memory.js";
8
+ import { agentMemoryDir } from "../workspace.js";
9
+ import { patchTool } from "../tools/patch.js";
10
+ import { cronTool } from "../tools/cron.js";
11
+ /** Get all custom tool definitions for an agent */
12
+ function getToolDefs(agentId) {
13
+ const memRoot = agentMemoryDir(agentId);
14
+ const scopedMemory = agentId
15
+ ? createScopedMemoryTools(memRoot)
16
+ : { search: memorySearchTool, get: memoryGetTool };
17
+ return [scopedMemory.search, scopedMemory.get, patchTool, cronTool];
18
+ }
19
+ export async function runAgentOpenAI(apiKey, model, systemPrompt, history, userMessage, opts) {
20
+ const emit = opts?.onEvent;
21
+ // Use `any[]` for the messages array — OpenAI SDK accepts this and it avoids
22
+ // importing complex union types that differ across SDK versions.
23
+ const messages = [
24
+ { role: "system", content: systemPrompt },
25
+ ];
26
+ for (const m of history) {
27
+ if (m.role === "user" || m.role === "assistant") {
28
+ messages.push({ role: m.role, content: m.content });
29
+ }
30
+ }
31
+ messages.push({ role: "user", content: userMessage });
32
+ let baseUrl = opts?.baseUrl;
33
+ if (!baseUrl) {
34
+ if (opts?.provider === "openai")
35
+ baseUrl = "https://api.openai.com/v1";
36
+ else if (opts?.provider === "anthropic")
37
+ baseUrl = "https://api.anthropic.com/v1/";
38
+ }
39
+ const client = new OpenAI({
40
+ apiKey,
41
+ ...(baseUrl && { baseURL: baseUrl }),
42
+ });
43
+ // Convert tool definitions to OpenAI format
44
+ const toolDefs = getToolDefs(opts?.agentId);
45
+ const tools = toolDefs.map(adaptToolDefToOpenAI);
46
+ const toolMap = new Map(toolDefs.map(t => [t.name, t]));
47
+ const maxTurns = opts?.maxTurns ?? DEFAULT_MAX_TURNS;
48
+ let result = "";
49
+ let toolIdCounter = 0;
50
+ // Tool loop: keep calling until no tool_calls or maxTurns exhausted
51
+ for (let turn = 0; turn < maxTurns; turn++) {
52
+ if (opts?.signal?.aborted)
53
+ throw new Error("Aborted");
54
+ const stream = await client.chat.completions.create({
55
+ model,
56
+ messages,
57
+ stream: true,
58
+ ...(tools.length > 0 && { tools }),
59
+ });
60
+ let content = "";
61
+ const toolCalls = new Map();
62
+ for await (const chunk of stream) {
63
+ if (opts?.signal?.aborted)
64
+ throw new Error("Aborted");
65
+ const choice = chunk.choices?.[0];
66
+ if (!choice)
67
+ continue;
68
+ // Accumulate content
69
+ const delta = choice.delta;
70
+ if (delta?.content) {
71
+ content += delta.content;
72
+ emit?.({ type: "stream_text", text: delta.content });
73
+ }
74
+ // Accumulate tool calls from deltas
75
+ if (delta?.tool_calls) {
76
+ for (const tc of delta.tool_calls) {
77
+ const idx = tc.index;
78
+ if (!toolCalls.has(idx)) {
79
+ toolCalls.set(idx, { id: tc.id ?? `tool-${++toolIdCounter}`, name: tc.function?.name ?? "", args: "" });
80
+ }
81
+ const entry = toolCalls.get(idx);
82
+ if (tc.function?.name)
83
+ entry.name = tc.function.name;
84
+ if (tc.function?.arguments)
85
+ entry.args += tc.function.arguments;
86
+ }
87
+ }
88
+ // Report usage from the final chunk
89
+ if (chunk.usage && opts?.sessionId) {
90
+ recordUsage(opts.sessionId, {
91
+ inputTokens: chunk.usage.prompt_tokens ?? 0,
92
+ outputTokens: chunk.usage.completion_tokens ?? 0,
93
+ cacheReadTokens: 0,
94
+ cacheWriteTokens: 0,
95
+ });
96
+ emit?.({
97
+ type: "usage",
98
+ inputTokens: chunk.usage.prompt_tokens ?? 0,
99
+ outputTokens: chunk.usage.completion_tokens ?? 0,
100
+ });
101
+ }
102
+ }
103
+ // No tool calls — we're done
104
+ if (toolCalls.size === 0) {
105
+ result = content;
106
+ break;
107
+ }
108
+ // Build assistant message with tool calls
109
+ const assistantToolCalls = [];
110
+ for (const [, tc] of toolCalls) {
111
+ assistantToolCalls.push({
112
+ id: tc.id,
113
+ type: "function",
114
+ function: { name: tc.name, arguments: tc.args },
115
+ });
116
+ }
117
+ messages.push({
118
+ role: "assistant",
119
+ content: content || null,
120
+ tool_calls: assistantToolCalls,
121
+ });
122
+ // Execute tool calls and append results
123
+ for (const [, tc] of toolCalls) {
124
+ let parsedArgs;
125
+ try {
126
+ parsedArgs = JSON.parse(tc.args || "{}");
127
+ }
128
+ catch {
129
+ parsedArgs = {};
130
+ }
131
+ // Pre-tool hook
132
+ if (opts?.hooksEnabled) {
133
+ await runHooks("before_tool", {
134
+ sessionId: opts.sessionId,
135
+ toolName: tc.name,
136
+ toolArgs: parsedArgs,
137
+ });
138
+ }
139
+ if (emit) {
140
+ emit({ type: "tool_call", id: tc.id, name: tc.name, args: parsedArgs });
141
+ }
142
+ else {
143
+ const argsStr = JSON.stringify(parsedArgs).slice(0, 120);
144
+ process.stderr.write(`\x1b[36m → ${tc.name}\x1b[0m\x1b[90m(${argsStr})\x1b[0m\n`);
145
+ }
146
+ // Execute tool
147
+ let toolResult;
148
+ const toolDef = toolMap.get(tc.name);
149
+ if (toolDef) {
150
+ try {
151
+ toolResult = await toolDef.execute(parsedArgs);
152
+ }
153
+ catch (err) {
154
+ toolResult = `ERROR: ${err instanceof Error ? err.message : String(err)}`;
155
+ }
156
+ }
157
+ else {
158
+ toolResult = `ERROR: Unknown tool "${tc.name}"`;
159
+ }
160
+ // Post-tool hook
161
+ if (opts?.hooksEnabled) {
162
+ await runHooks("after_tool", {
163
+ sessionId: opts.sessionId,
164
+ toolName: tc.name,
165
+ toolResult,
166
+ });
167
+ }
168
+ const preview = toolResult.slice(0, 150).replace(/\n/g, "↵");
169
+ if (emit) {
170
+ emit({ type: "tool_result", id: tc.id, name: tc.name, preview });
171
+ }
172
+ else {
173
+ process.stderr.write(`\x1b[90m ← ${preview}${toolResult.length > 150 ? "…" : ""}\x1b[0m\n`);
174
+ }
175
+ messages.push({
176
+ role: "tool",
177
+ tool_call_id: tc.id,
178
+ content: toolResult,
179
+ });
180
+ }
181
+ // Last turn — force a final completion without tools
182
+ if (turn === maxTurns - 1) {
183
+ result = content;
184
+ }
185
+ }
186
+ // If we never got a final text response, do one more call without tools
187
+ if (!result && messages[messages.length - 1].role === "tool") {
188
+ const finalStream = await client.chat.completions.create({
189
+ model,
190
+ messages,
191
+ stream: true,
192
+ });
193
+ for await (const chunk of finalStream) {
194
+ const delta = chunk.choices?.[0]?.delta?.content;
195
+ if (delta) {
196
+ result += delta;
197
+ emit?.({ type: "stream_text", text: delta });
198
+ }
199
+ }
200
+ }
201
+ emit?.({ type: "chunk", text: result });
202
+ const userMsg = { role: "user", content: userMessage };
203
+ const aiMsg = { role: "assistant", content: result };
204
+ return { response: result, newMessages: [userMsg, aiMsg], usage: null };
205
+ }
206
+ //# sourceMappingURL=agent-openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-openai.js","sourceRoot":"","sources":["../../src/agent/agent-openai.ts"],"names":[],"mappings":"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"}