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.
- package/LICENSE +21 -0
- package/README.md +224 -0
- package/camelagi.mjs +2 -0
- package/config.example.yaml +107 -0
- package/dist/agent/agent-openai.js +206 -0
- package/dist/agent/agent-openai.js.map +1 -0
- package/dist/agent/agent-sdk.js +209 -0
- package/dist/agent/agent-sdk.js.map +1 -0
- package/dist/agent/tool-adapter.js +31 -0
- package/dist/agent/tool-adapter.js.map +1 -0
- package/dist/agent/types.js +3 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent.js +17 -0
- package/dist/agent.js.map +1 -0
- package/dist/approval-forward.js +42 -0
- package/dist/approval-forward.js.map +1 -0
- package/dist/approvals.js +151 -0
- package/dist/approvals.js.map +1 -0
- package/dist/boot.js +34 -0
- package/dist/boot.js.map +1 -0
- package/dist/bootstrap.js +451 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/camelagi-gateway.mjs +93611 -0
- package/dist/camelagi-gateway.mjs.map +7 -0
- package/dist/channels/adapter.js +10 -0
- package/dist/channels/adapter.js.map +1 -0
- package/dist/channels/discord.js +232 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/handler.js +349 -0
- package/dist/channels/handler.js.map +1 -0
- package/dist/channels/index.js +19 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/channels/registry.js +71 -0
- package/dist/channels/registry.js.map +1 -0
- package/dist/channels/telegram.js +83 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/types.js +3 -0
- package/dist/channels/types.js.map +1 -0
- package/dist/chunker.js +102 -0
- package/dist/chunker.js.map +1 -0
- package/dist/cli/cmd-agents.js +65 -0
- package/dist/cli/cmd-agents.js.map +1 -0
- package/dist/cli/cmd-bootstrap.js +10 -0
- package/dist/cli/cmd-bootstrap.js.map +1 -0
- package/dist/cli/cmd-chat.js +32 -0
- package/dist/cli/cmd-chat.js.map +1 -0
- package/dist/cli/cmd-config.js +88 -0
- package/dist/cli/cmd-config.js.map +1 -0
- package/dist/cli/cmd-cron.js +120 -0
- package/dist/cli/cmd-cron.js.map +1 -0
- package/dist/cli/cmd-daemon.js +37 -0
- package/dist/cli/cmd-daemon.js.map +1 -0
- package/dist/cli/cmd-doctor.js +18 -0
- package/dist/cli/cmd-doctor.js.map +1 -0
- package/dist/cli/cmd-logs.js +30 -0
- package/dist/cli/cmd-logs.js.map +1 -0
- package/dist/cli/cmd-pairing.js +41 -0
- package/dist/cli/cmd-pairing.js.map +1 -0
- package/dist/cli/cmd-reset.js +39 -0
- package/dist/cli/cmd-reset.js.map +1 -0
- package/dist/cli/cmd-serve.js +30 -0
- package/dist/cli/cmd-serve.js.map +1 -0
- package/dist/cli/cmd-sessions.js +56 -0
- package/dist/cli/cmd-sessions.js.map +1 -0
- package/dist/cli/cmd-setup.js +11 -0
- package/dist/cli/cmd-setup.js.map +1 -0
- package/dist/cli/cmd-soul.js +43 -0
- package/dist/cli/cmd-soul.js.map +1 -0
- package/dist/cli/parse.js +50 -0
- package/dist/cli/parse.js.map +1 -0
- package/dist/cli/registry.js +15 -0
- package/dist/cli/registry.js.map +1 -0
- package/dist/cli.js +103 -0
- package/dist/cli.js.map +1 -0
- package/dist/compact.js +92 -0
- package/dist/compact.js.map +1 -0
- package/dist/config.js +153 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +21 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/config.js +212 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/constants.js +21 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/errors.js +5 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/log.js +41 -0
- package/dist/core/log.js.map +1 -0
- package/dist/core/models.js +123 -0
- package/dist/core/models.js.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/update-check.js +51 -0
- package/dist/core/update-check.js.map +1 -0
- package/dist/cron.js +81 -0
- package/dist/cron.js.map +1 -0
- package/dist/daemon.js +109 -0
- package/dist/daemon.js.map +1 -0
- package/dist/doctor.js +194 -0
- package/dist/doctor.js.map +1 -0
- package/dist/errors.js +5 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensions/approval-forward.js +42 -0
- package/dist/extensions/approval-forward.js.map +1 -0
- package/dist/extensions/approvals.js +144 -0
- package/dist/extensions/approvals.js.map +1 -0
- package/dist/extensions/cron.js +306 -0
- package/dist/extensions/cron.js.map +1 -0
- package/dist/extensions/hooks.js +72 -0
- package/dist/extensions/hooks.js.map +1 -0
- package/dist/extensions/skills.js +97 -0
- package/dist/extensions/skills.js.map +1 -0
- package/dist/gateway/csrf.js +44 -0
- package/dist/gateway/csrf.js.map +1 -0
- package/dist/gateway/logger.js +81 -0
- package/dist/gateway/logger.js.map +1 -0
- package/dist/gateway/rate-limit.js +33 -0
- package/dist/gateway/rate-limit.js.map +1 -0
- package/dist/gateway/routes.js +315 -0
- package/dist/gateway/routes.js.map +1 -0
- package/dist/gateway/state.js +54 -0
- package/dist/gateway/state.js.map +1 -0
- package/dist/gateway/ws-handler.js +200 -0
- package/dist/gateway/ws-handler.js.map +1 -0
- package/dist/gateway-entry.js +16 -0
- package/dist/gateway-entry.js.map +1 -0
- package/dist/hooks.js +72 -0
- package/dist/hooks.js.map +1 -0
- package/dist/lanes.js +62 -0
- package/dist/lanes.js.map +1 -0
- package/dist/model.js +30 -0
- package/dist/model.js.map +1 -0
- package/dist/policy.js +22 -0
- package/dist/policy.js.map +1 -0
- package/dist/queue.js +45 -0
- package/dist/queue.js.map +1 -0
- package/dist/retry.js +96 -0
- package/dist/retry.js.map +1 -0
- package/dist/runs.js +83 -0
- package/dist/runs.js.map +1 -0
- package/dist/runtime/compact.js +99 -0
- package/dist/runtime/compact.js.map +1 -0
- package/dist/runtime/lanes.js +66 -0
- package/dist/runtime/lanes.js.map +1 -0
- package/dist/runtime/orchestrate.js +121 -0
- package/dist/runtime/orchestrate.js.map +1 -0
- package/dist/runtime/queue.js +50 -0
- package/dist/runtime/queue.js.map +1 -0
- package/dist/runtime/retry.js +127 -0
- package/dist/runtime/retry.js.map +1 -0
- package/dist/runtime/runs.js +105 -0
- package/dist/runtime/runs.js.map +1 -0
- package/dist/serve.js +209 -0
- package/dist/serve.js.map +1 -0
- package/dist/session.js +75 -0
- package/dist/session.js.map +1 -0
- package/dist/setup.js +254 -0
- package/dist/setup.js.map +1 -0
- package/dist/skills.js +89 -0
- package/dist/skills.js.map +1 -0
- package/dist/subagent.js +71 -0
- package/dist/subagent.js.map +1 -0
- package/dist/system-prompt.js +157 -0
- package/dist/system-prompt.js.map +1 -0
- package/dist/telegram/admin-bot.js +705 -0
- package/dist/telegram/admin-bot.js.map +1 -0
- package/dist/telegram/agent-bot.js +551 -0
- package/dist/telegram/agent-bot.js.map +1 -0
- package/dist/telegram/bot-approval.js +63 -0
- package/dist/telegram/bot-approval.js.map +1 -0
- package/dist/telegram/draft-stream.js +86 -0
- package/dist/telegram/draft-stream.js.map +1 -0
- package/dist/telegram/format.js +106 -0
- package/dist/telegram/format.js.map +1 -0
- package/dist/telegram/helpers.js +87 -0
- package/dist/telegram/helpers.js.map +1 -0
- package/dist/telegram/pairing-notify.js +52 -0
- package/dist/telegram/pairing-notify.js.map +1 -0
- package/dist/telegram/pairing.js +138 -0
- package/dist/telegram/pairing.js.map +1 -0
- package/dist/telegram/resolve.js +33 -0
- package/dist/telegram/resolve.js.map +1 -0
- package/dist/telegram/transcribe.js +77 -0
- package/dist/telegram/transcribe.js.map +1 -0
- package/dist/telegram/types.js +3 -0
- package/dist/telegram/types.js.map +1 -0
- package/dist/telegram/voice-wizard.js +84 -0
- package/dist/telegram/voice-wizard.js.map +1 -0
- package/dist/telegram/wizard.js +89 -0
- package/dist/telegram/wizard.js.map +1 -0
- package/dist/telegram/wizards.js +297 -0
- package/dist/telegram/wizards.js.map +1 -0
- package/dist/telegram-admin.js +800 -0
- package/dist/telegram-admin.js.map +1 -0
- package/dist/telegram.js +118 -0
- package/dist/telegram.js.map +1 -0
- package/dist/tools/cron.js +94 -0
- package/dist/tools/cron.js.map +1 -0
- package/dist/tools/edit.js +29 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/exec.js +38 -0
- package/dist/tools/exec.js.map +1 -0
- package/dist/tools/fetch.js +28 -0
- package/dist/tools/fetch.js.map +1 -0
- package/dist/tools/index.js +16 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/memory.js +164 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/patch.js +284 -0
- package/dist/tools/patch.js.map +1 -0
- package/dist/tools/read.js +26 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/search.js +62 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/subagent.js +48 -0
- package/dist/tools/subagent.js.map +1 -0
- package/dist/tools/write.js +22 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/tui/commands.js +450 -0
- package/dist/tui/commands.js.map +1 -0
- package/dist/tui/components/assistant-message.js +26 -0
- package/dist/tui/components/assistant-message.js.map +1 -0
- package/dist/tui/components/chat-log.js +94 -0
- package/dist/tui/components/chat-log.js.map +1 -0
- package/dist/tui/components/custom-editor.js +40 -0
- package/dist/tui/components/custom-editor.js.map +1 -0
- package/dist/tui/components/hint-bar.js +13 -0
- package/dist/tui/components/hint-bar.js.map +1 -0
- package/dist/tui/components/tool-execution.js +73 -0
- package/dist/tui/components/tool-execution.js.map +1 -0
- package/dist/tui/components/user-message.js +19 -0
- package/dist/tui/components/user-message.js.map +1 -0
- package/dist/tui/components/welcome.js +147 -0
- package/dist/tui/components/welcome.js.map +1 -0
- package/dist/tui/context.js +3 -0
- package/dist/tui/context.js.map +1 -0
- package/dist/tui/theme.js +91 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/tui.js +389 -0
- package/dist/tui/tui.js.map +1 -0
- package/dist/tui/ws-handler.js +154 -0
- package/dist/tui/ws-handler.js.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/usage.js +88 -0
- package/dist/usage.js.map +1 -0
- package/dist/workspace.js +245 -0
- package/dist/workspace.js.map +1 -0
- 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,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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"}
|