squidclaw 0.1.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 +149 -0
- package/bin/squidclaw.js +512 -0
- package/lib/ai/gateway.js +283 -0
- package/lib/ai/prompt-builder.js +149 -0
- package/lib/api/server.js +235 -0
- package/lib/behavior/engine.js +187 -0
- package/lib/channels/hub-media.js +128 -0
- package/lib/channels/hub.js +89 -0
- package/lib/channels/whatsapp/manager.js +319 -0
- package/lib/channels/whatsapp/media.js +228 -0
- package/lib/cli/agent-cmd.js +182 -0
- package/lib/cli/brain-cmd.js +49 -0
- package/lib/cli/broadcast-cmd.js +28 -0
- package/lib/cli/channels-cmd.js +157 -0
- package/lib/cli/config-cmd.js +26 -0
- package/lib/cli/conversations-cmd.js +27 -0
- package/lib/cli/engine-cmd.js +115 -0
- package/lib/cli/handoff-cmd.js +26 -0
- package/lib/cli/hours-cmd.js +38 -0
- package/lib/cli/key-cmd.js +62 -0
- package/lib/cli/knowledge-cmd.js +59 -0
- package/lib/cli/memory-cmd.js +50 -0
- package/lib/cli/platform-cmd.js +51 -0
- package/lib/cli/setup.js +226 -0
- package/lib/cli/stats-cmd.js +66 -0
- package/lib/cli/tui.js +308 -0
- package/lib/cli/update-cmd.js +25 -0
- package/lib/cli/webhook-cmd.js +40 -0
- package/lib/core/agent-manager.js +83 -0
- package/lib/core/agent.js +162 -0
- package/lib/core/config.js +172 -0
- package/lib/core/logger.js +43 -0
- package/lib/engine.js +117 -0
- package/lib/features/heartbeat.js +71 -0
- package/lib/storage/interface.js +56 -0
- package/lib/storage/sqlite.js +409 -0
- package/package.json +48 -0
- package/templates/BEHAVIOR.md +42 -0
- package/templates/IDENTITY.md +7 -0
- package/templates/RULES.md +9 -0
- package/templates/SOUL.md +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Squidclaw
|
|
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,149 @@
|
|
|
1
|
+
# 🦑 Squidclaw
|
|
2
|
+
|
|
3
|
+
**AI agent platform — human-like agents for WhatsApp & more.**
|
|
4
|
+
|
|
5
|
+
Squidclaw lets you create AI agents that feel like real people. They text naturally, remember conversations, learn over time, and work on WhatsApp out of the box.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -g squidclaw
|
|
11
|
+
squidclaw setup
|
|
12
|
+
squidclaw start
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
That's it. Your AI agent is live.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- 🧠 **10+ AI Providers** — Claude, GPT-4o, Gemini, Llama, Mistral, local models
|
|
20
|
+
- 📱 **WhatsApp** — Multi-session, pairing code + QR, auto-reconnect
|
|
21
|
+
- 💬 **Human-like behavior** — Message splitting, reactions, emotion detection
|
|
22
|
+
- 🧬 **Soul & Personality** — Each agent has its own identity, tone, and rules
|
|
23
|
+
- 🧠 **Memory** — Short-term conversations + long-term learned facts
|
|
24
|
+
- 📚 **Knowledge Base** — Upload docs, RAG-powered answers
|
|
25
|
+
- 🔄 **Auto-fallback** — Claude down? Auto-switch to GPT-4o or free models
|
|
26
|
+
- 🤝 **Handoff** — Escalate to humans when needed
|
|
27
|
+
- 📊 **Usage tracking** — Tokens, costs, per-agent analytics
|
|
28
|
+
- 💓 **Heartbeat** — Proactive check-ins and scheduled messages
|
|
29
|
+
- 🔗 **Webhooks** — Integrate with any system
|
|
30
|
+
- 📢 **Broadcast** — Bulk messages with rate limiting
|
|
31
|
+
- 🌍 **Bilingual** — Arabic + English with auto-detection
|
|
32
|
+
- 🏢 **Platform mode** — Multi-tenant for SaaS builders
|
|
33
|
+
|
|
34
|
+
## Supported AI Models
|
|
35
|
+
|
|
36
|
+
### Paid
|
|
37
|
+
| Provider | Models |
|
|
38
|
+
|----------|--------|
|
|
39
|
+
| Anthropic | Claude Opus 4, Sonnet 4, Haiku 3.5 |
|
|
40
|
+
| OpenAI | GPT-4o, GPT-4o Mini, o3, o4-mini |
|
|
41
|
+
| Google | Gemini 2.5 Pro, 2.5 Flash, 2.0 Flash |
|
|
42
|
+
| Mistral | Large, Medium, Small |
|
|
43
|
+
|
|
44
|
+
### Free
|
|
45
|
+
| Provider | Models | Notes |
|
|
46
|
+
|----------|--------|-------|
|
|
47
|
+
| Groq | Llama 4 Scout, Maverick | Free tier, very fast |
|
|
48
|
+
| Together | Llama 4 Scout, Maverick | Free $5 credit |
|
|
49
|
+
| Cerebras | Llama 3.3 70B | Free, fastest inference |
|
|
50
|
+
| Ollama | Any local model | Runs on your machine |
|
|
51
|
+
| LM Studio | Any local model | Runs on your machine |
|
|
52
|
+
|
|
53
|
+
## Commands
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Engine
|
|
57
|
+
squidclaw start # Start the engine
|
|
58
|
+
squidclaw stop # Stop the engine
|
|
59
|
+
squidclaw status # Show status
|
|
60
|
+
|
|
61
|
+
# Agents
|
|
62
|
+
squidclaw agent create # Create a new agent
|
|
63
|
+
squidclaw agent list # List all agents
|
|
64
|
+
squidclaw agent chat <id> # Chat in terminal
|
|
65
|
+
squidclaw agent edit <id> # Edit agent files
|
|
66
|
+
squidclaw agent delete <id> # Delete an agent
|
|
67
|
+
|
|
68
|
+
# Brain / Models
|
|
69
|
+
squidclaw brain list # Show available models
|
|
70
|
+
squidclaw brain set <model> # Set default model
|
|
71
|
+
squidclaw brain show # Show current model
|
|
72
|
+
|
|
73
|
+
# API Keys
|
|
74
|
+
squidclaw key set <provider> <key> # Set API key
|
|
75
|
+
squidclaw key test # Test connection
|
|
76
|
+
squidclaw key show # Show keys (masked)
|
|
77
|
+
squidclaw key remove <provider> # Remove a key
|
|
78
|
+
|
|
79
|
+
# Channels
|
|
80
|
+
squidclaw channels login whatsapp # Connect WhatsApp
|
|
81
|
+
squidclaw channels status # Show connections
|
|
82
|
+
squidclaw channels logout whatsapp # Disconnect
|
|
83
|
+
|
|
84
|
+
# Usage
|
|
85
|
+
squidclaw usage # Token usage & costs
|
|
86
|
+
squidclaw stats # Detailed analytics
|
|
87
|
+
squidclaw logs # View logs
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## How It Works
|
|
91
|
+
|
|
92
|
+
Each agent gets its own soul (personality), memory, and rules:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
~/.squidclaw/agents/luna/
|
|
96
|
+
├── SOUL.md ← who the agent IS
|
|
97
|
+
├── IDENTITY.md ← name, language, emoji
|
|
98
|
+
├── MEMORY.md ← long-term learned facts
|
|
99
|
+
├── RULES.md ← hard boundaries
|
|
100
|
+
└── BEHAVIOR.md ← behavior config
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
When a WhatsApp message comes in:
|
|
104
|
+
|
|
105
|
+
1. **Route** → identify which agent owns this number
|
|
106
|
+
2. **Understand** → detect language, emotion, intent
|
|
107
|
+
3. **Think** → load soul + memory + knowledge → call AI
|
|
108
|
+
4. **Behave** → split into short messages, add reactions
|
|
109
|
+
5. **Reply** → send human-like responses with natural timing
|
|
110
|
+
|
|
111
|
+
## Platform Mode (for SaaS builders)
|
|
112
|
+
|
|
113
|
+
Squidclaw can run in multi-tenant mode — one process, many agents, many customers:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
squidclaw platform init --supabase-url <url> --supabase-key <key>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Perfect for building your own AI agent SaaS on top of Squidclaw.
|
|
120
|
+
|
|
121
|
+
## REST API
|
|
122
|
+
|
|
123
|
+
When running, Squidclaw exposes a REST API on port 9500:
|
|
124
|
+
|
|
125
|
+
| Endpoint | Description |
|
|
126
|
+
|----------|-------------|
|
|
127
|
+
| `GET /health` | Engine health |
|
|
128
|
+
| `GET /api/agents` | List agents |
|
|
129
|
+
| `POST /api/agents` | Create agent |
|
|
130
|
+
| `POST /api/agents/:id/chat` | Chat with agent |
|
|
131
|
+
| `POST /api/agents/:id/whatsapp/pair` | WhatsApp pairing |
|
|
132
|
+
| `GET /api/usage` | Usage stats |
|
|
133
|
+
| `GET /api/handoffs` | Active handoffs |
|
|
134
|
+
| `POST /api/webhooks` | Add webhook |
|
|
135
|
+
|
|
136
|
+
Full API docs at [squidclaw.dev/docs/api](https://squidclaw.dev/docs/api)
|
|
137
|
+
|
|
138
|
+
## Requirements
|
|
139
|
+
|
|
140
|
+
- Node.js 20+
|
|
141
|
+
- Any AI provider API key (or use free models)
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
Built with 🦑 by [Squidclaw](https://squidclaw.dev)
|
package/bin/squidclaw.js
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 🦑 Squidclaw CLI
|
|
5
|
+
* AI agent platform — human-like agents for WhatsApp & more
|
|
6
|
+
* https://squidclaw.dev
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
import { readFileSync } from 'fs';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
17
|
+
|
|
18
|
+
const program = new Command();
|
|
19
|
+
|
|
20
|
+
program
|
|
21
|
+
.name('squidclaw')
|
|
22
|
+
.description('🦑 AI agent platform — human-like agents for WhatsApp & more')
|
|
23
|
+
.version(pkg.version);
|
|
24
|
+
|
|
25
|
+
// ── Setup ──────────────────────────────────────────────
|
|
26
|
+
program
|
|
27
|
+
.command('setup')
|
|
28
|
+
.description('Interactive first-time setup wizard')
|
|
29
|
+
.action(async () => {
|
|
30
|
+
const { setup } = await import('../lib/cli/setup.js');
|
|
31
|
+
await setup();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// ── Start / Stop / Restart / Status ────────────────────
|
|
35
|
+
program
|
|
36
|
+
.command('start')
|
|
37
|
+
.description('Start the Squidclaw engine')
|
|
38
|
+
.option('-p, --port <port>', 'API port', '9500')
|
|
39
|
+
.option('-d, --daemon', 'Run as background daemon')
|
|
40
|
+
.action(async (opts) => {
|
|
41
|
+
const { start } = await import('../lib/cli/engine-cmd.js');
|
|
42
|
+
await start(opts);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
program
|
|
46
|
+
.command('stop')
|
|
47
|
+
.description('Stop the Squidclaw engine')
|
|
48
|
+
.action(async () => {
|
|
49
|
+
const { stop } = await import('../lib/cli/engine-cmd.js');
|
|
50
|
+
await stop();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
program
|
|
54
|
+
.command('restart')
|
|
55
|
+
.description('Restart the Squidclaw engine')
|
|
56
|
+
.action(async () => {
|
|
57
|
+
const { restart } = await import('../lib/cli/engine-cmd.js');
|
|
58
|
+
await restart();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
program
|
|
62
|
+
.command('status')
|
|
63
|
+
.description('Show engine status, agents, and connections')
|
|
64
|
+
.action(async () => {
|
|
65
|
+
const { status } = await import('../lib/cli/engine-cmd.js');
|
|
66
|
+
await status();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ── Agent Management ───────────────────────────────────
|
|
70
|
+
const agent = program.command('agent').description('Manage agents');
|
|
71
|
+
|
|
72
|
+
agent
|
|
73
|
+
.command('create')
|
|
74
|
+
.description('Create a new agent')
|
|
75
|
+
.option('-n, --name <name>', 'Agent name')
|
|
76
|
+
.option('--soul <text>', 'Soul/personality description')
|
|
77
|
+
.option('-l, --language <lang>', 'Language (en/ar/bilingual)', 'en')
|
|
78
|
+
.action(async (opts) => {
|
|
79
|
+
const { createAgent } = await import('../lib/cli/agent-cmd.js');
|
|
80
|
+
await createAgent(opts);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
agent
|
|
84
|
+
.command('list')
|
|
85
|
+
.description('List all agents')
|
|
86
|
+
.action(async () => {
|
|
87
|
+
const { listAgents } = await import('../lib/cli/agent-cmd.js');
|
|
88
|
+
await listAgents();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
agent
|
|
92
|
+
.command('edit <id>')
|
|
93
|
+
.description('Edit an agent')
|
|
94
|
+
.action(async (id) => {
|
|
95
|
+
const { editAgent } = await import('../lib/cli/agent-cmd.js');
|
|
96
|
+
await editAgent(id);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
agent
|
|
100
|
+
.command('delete <id>')
|
|
101
|
+
.description('Delete an agent')
|
|
102
|
+
.action(async (id) => {
|
|
103
|
+
const { deleteAgent } = await import('../lib/cli/agent-cmd.js');
|
|
104
|
+
await deleteAgent(id);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
agent
|
|
108
|
+
.command('chat <id>')
|
|
109
|
+
.description('Chat with an agent in terminal')
|
|
110
|
+
.action(async (id) => {
|
|
111
|
+
const { chatAgent } = await import('../lib/cli/agent-cmd.js');
|
|
112
|
+
await chatAgent(id);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// ── Brain / Model Management ───────────────────────────
|
|
116
|
+
const brain = program.command('brain').description('Manage AI models');
|
|
117
|
+
|
|
118
|
+
brain
|
|
119
|
+
.command('list')
|
|
120
|
+
.description('List available models')
|
|
121
|
+
.action(async () => {
|
|
122
|
+
const { listBrains } = await import('../lib/cli/brain-cmd.js');
|
|
123
|
+
await listBrains();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
brain
|
|
127
|
+
.command('set <model>')
|
|
128
|
+
.description('Set default model')
|
|
129
|
+
.option('-a, --agent <id>', 'Set for specific agent')
|
|
130
|
+
.option('-f, --fallback <model>', 'Add fallback model', [])
|
|
131
|
+
.action(async (model, opts) => {
|
|
132
|
+
const { setBrain } = await import('../lib/cli/brain-cmd.js');
|
|
133
|
+
await setBrain(model, opts);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
brain
|
|
137
|
+
.command('show')
|
|
138
|
+
.description('Show current model config')
|
|
139
|
+
.action(async () => {
|
|
140
|
+
const { showBrain } = await import('../lib/cli/brain-cmd.js');
|
|
141
|
+
await showBrain();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ── API Key Management ─────────────────────────────────
|
|
145
|
+
const key = program.command('key').description('Manage API keys');
|
|
146
|
+
|
|
147
|
+
key
|
|
148
|
+
.command('set <provider> <apiKey>')
|
|
149
|
+
.description('Set API key for a provider')
|
|
150
|
+
.action(async (provider, apiKey) => {
|
|
151
|
+
const { setKey } = await import('../lib/cli/key-cmd.js');
|
|
152
|
+
await setKey(provider, apiKey);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
key
|
|
156
|
+
.command('test')
|
|
157
|
+
.description('Test current API key')
|
|
158
|
+
.option('-p, --provider <provider>', 'Test specific provider')
|
|
159
|
+
.action(async (opts) => {
|
|
160
|
+
const { testKey } = await import('../lib/cli/key-cmd.js');
|
|
161
|
+
await testKey(opts);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
key
|
|
165
|
+
.command('show')
|
|
166
|
+
.description('Show configured keys (masked)')
|
|
167
|
+
.action(async () => {
|
|
168
|
+
const { showKeys } = await import('../lib/cli/key-cmd.js');
|
|
169
|
+
await showKeys();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
key
|
|
173
|
+
.command('remove <provider>')
|
|
174
|
+
.description('Remove an API key')
|
|
175
|
+
.action(async (provider) => {
|
|
176
|
+
const { removeKey } = await import('../lib/cli/key-cmd.js');
|
|
177
|
+
await removeKey(provider);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// ── Channel Management ─────────────────────────────────
|
|
181
|
+
const channels = program.command('channels').description('Manage messaging channels');
|
|
182
|
+
|
|
183
|
+
channels
|
|
184
|
+
.command('login <channel>')
|
|
185
|
+
.description('Connect a channel (whatsapp, telegram)')
|
|
186
|
+
.option('-a, --agent <id>', 'Agent to connect')
|
|
187
|
+
.option('-m, --method <method>', 'Login method (pairing/qr)', 'pairing')
|
|
188
|
+
.action(async (channel, opts) => {
|
|
189
|
+
const { loginChannel } = await import('../lib/cli/channels-cmd.js');
|
|
190
|
+
await loginChannel(channel, opts);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
channels
|
|
194
|
+
.command('status')
|
|
195
|
+
.description('Show channel connection status')
|
|
196
|
+
.action(async () => {
|
|
197
|
+
const { channelStatus } = await import('../lib/cli/channels-cmd.js');
|
|
198
|
+
await channelStatus();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
channels
|
|
202
|
+
.command('logout <channel>')
|
|
203
|
+
.description('Disconnect a channel')
|
|
204
|
+
.option('-a, --agent <id>', 'Agent to disconnect')
|
|
205
|
+
.action(async (channel, opts) => {
|
|
206
|
+
const { logoutChannel } = await import('../lib/cli/channels-cmd.js');
|
|
207
|
+
await logoutChannel(channel, opts);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// ── Memory Management ──────────────────────────────────
|
|
211
|
+
const memory = program.command('memory').description('Manage agent memory');
|
|
212
|
+
|
|
213
|
+
memory
|
|
214
|
+
.command('show <agentId>')
|
|
215
|
+
.description('Show agent memory')
|
|
216
|
+
.action(async (agentId) => {
|
|
217
|
+
const { showMemory } = await import('../lib/cli/memory-cmd.js');
|
|
218
|
+
await showMemory(agentId);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
memory
|
|
222
|
+
.command('clear <agentId>')
|
|
223
|
+
.description('Clear agent memory')
|
|
224
|
+
.option('--confirm', 'Skip confirmation')
|
|
225
|
+
.action(async (agentId, opts) => {
|
|
226
|
+
const { clearMemory } = await import('../lib/cli/memory-cmd.js');
|
|
227
|
+
await clearMemory(agentId, opts);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
memory
|
|
231
|
+
.command('export <agentId>')
|
|
232
|
+
.description('Export agent memory to file')
|
|
233
|
+
.option('-o, --output <path>', 'Output file path')
|
|
234
|
+
.action(async (agentId, opts) => {
|
|
235
|
+
const { exportMemory } = await import('../lib/cli/memory-cmd.js');
|
|
236
|
+
await exportMemory(agentId, opts);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// ── Knowledge Base ─────────────────────────────────────
|
|
240
|
+
const knowledge = program.command('knowledge').description('Manage knowledge base');
|
|
241
|
+
|
|
242
|
+
knowledge
|
|
243
|
+
.command('upload <file>')
|
|
244
|
+
.description('Upload a document to knowledge base')
|
|
245
|
+
.option('-a, --agent <id>', 'Target agent')
|
|
246
|
+
.action(async (file, opts) => {
|
|
247
|
+
const { uploadKnowledge } = await import('../lib/cli/knowledge-cmd.js');
|
|
248
|
+
await uploadKnowledge(file, opts);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
knowledge
|
|
252
|
+
.command('list')
|
|
253
|
+
.description('List knowledge base documents')
|
|
254
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
255
|
+
.action(async (opts) => {
|
|
256
|
+
const { listKnowledge } = await import('../lib/cli/knowledge-cmd.js');
|
|
257
|
+
await listKnowledge(opts);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
knowledge
|
|
261
|
+
.command('delete <docId>')
|
|
262
|
+
.description('Delete a document')
|
|
263
|
+
.action(async (docId) => {
|
|
264
|
+
const { deleteKnowledge } = await import('../lib/cli/knowledge-cmd.js');
|
|
265
|
+
await deleteKnowledge(docId);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// ── Usage & Stats ──────────────────────────────────────
|
|
269
|
+
program
|
|
270
|
+
.command('usage')
|
|
271
|
+
.description('Show token usage and costs')
|
|
272
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
273
|
+
.option('-p, --period <period>', 'Time period (7d/30d/all)', '30d')
|
|
274
|
+
.action(async (opts) => {
|
|
275
|
+
const { showUsage } = await import('../lib/cli/stats-cmd.js');
|
|
276
|
+
await showUsage(opts);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
program
|
|
280
|
+
.command('stats')
|
|
281
|
+
.description('Show detailed analytics')
|
|
282
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
283
|
+
.option('-p, --period <period>', 'Time period (7d/30d/all)', '7d')
|
|
284
|
+
.action(async (opts) => {
|
|
285
|
+
const { showStats } = await import('../lib/cli/stats-cmd.js');
|
|
286
|
+
await showStats(opts);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
program
|
|
290
|
+
.command('logs')
|
|
291
|
+
.description('Show engine logs')
|
|
292
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
293
|
+
.option('-n, --lines <n>', 'Number of lines', '50')
|
|
294
|
+
.option('-f, --follow', 'Follow log output')
|
|
295
|
+
.action(async (opts) => {
|
|
296
|
+
const { showLogs } = await import('../lib/cli/stats-cmd.js');
|
|
297
|
+
await showLogs(opts);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// ── Broadcast ──────────────────────────────────────────
|
|
301
|
+
const broadcast = program.command('broadcast').description('Send broadcast messages');
|
|
302
|
+
|
|
303
|
+
broadcast
|
|
304
|
+
.command('send')
|
|
305
|
+
.description('Send a broadcast message')
|
|
306
|
+
.requiredOption('-a, --agent <id>', 'Agent to send from')
|
|
307
|
+
.requiredOption('-m, --message <text>', 'Message to send')
|
|
308
|
+
.option('-g, --group <group>', 'Target group')
|
|
309
|
+
.action(async (opts) => {
|
|
310
|
+
const { sendBroadcast } = await import('../lib/cli/broadcast-cmd.js');
|
|
311
|
+
await sendBroadcast(opts);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// ── Handoff ────────────────────────────────────────────
|
|
315
|
+
const handoff = program.command('handoff').description('Manage human handoffs');
|
|
316
|
+
|
|
317
|
+
handoff
|
|
318
|
+
.command('list')
|
|
319
|
+
.description('List pending handoffs')
|
|
320
|
+
.action(async () => {
|
|
321
|
+
const { listHandoffs } = await import('../lib/cli/handoff-cmd.js');
|
|
322
|
+
await listHandoffs();
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
handoff
|
|
326
|
+
.command('resolve <id>')
|
|
327
|
+
.description('Resolve a handoff (hand back to agent)')
|
|
328
|
+
.action(async (id) => {
|
|
329
|
+
const { resolveHandoff } = await import('../lib/cli/handoff-cmd.js');
|
|
330
|
+
await resolveHandoff(id);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// ── Business Hours ─────────────────────────────────────
|
|
334
|
+
const hours = program.command('hours').description('Manage business hours');
|
|
335
|
+
|
|
336
|
+
hours
|
|
337
|
+
.command('set <schedule>')
|
|
338
|
+
.description('Set business hours (e.g. "sun-thu 9:00-18:00")')
|
|
339
|
+
.option('-a, --agent <id>', 'Agent')
|
|
340
|
+
.option('-t, --timezone <tz>', 'Timezone', 'UTC')
|
|
341
|
+
.action(async (schedule, opts) => {
|
|
342
|
+
const { setHours } = await import('../lib/cli/hours-cmd.js');
|
|
343
|
+
await setHours(schedule, opts);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
hours
|
|
347
|
+
.command('show')
|
|
348
|
+
.description('Show business hours')
|
|
349
|
+
.option('-a, --agent <id>', 'Agent')
|
|
350
|
+
.action(async (opts) => {
|
|
351
|
+
const { showHours } = await import('../lib/cli/hours-cmd.js');
|
|
352
|
+
await showHours(opts);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
hours
|
|
356
|
+
.command('off')
|
|
357
|
+
.description('Set 24/7 mode (no business hours)')
|
|
358
|
+
.option('-a, --agent <id>', 'Agent')
|
|
359
|
+
.action(async (opts) => {
|
|
360
|
+
const { setAlwaysOn } = await import('../lib/cli/hours-cmd.js');
|
|
361
|
+
await setAlwaysOn(opts);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// ── Webhook ────────────────────────────────────────────
|
|
365
|
+
const webhook = program.command('webhook').description('Manage webhooks');
|
|
366
|
+
|
|
367
|
+
webhook
|
|
368
|
+
.command('add <url>')
|
|
369
|
+
.description('Add a webhook endpoint')
|
|
370
|
+
.action(async (url) => {
|
|
371
|
+
const { addWebhook } = await import('../lib/cli/webhook-cmd.js');
|
|
372
|
+
await addWebhook(url);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
webhook
|
|
376
|
+
.command('list')
|
|
377
|
+
.description('List webhooks')
|
|
378
|
+
.action(async () => {
|
|
379
|
+
const { listWebhooks } = await import('../lib/cli/webhook-cmd.js');
|
|
380
|
+
await listWebhooks();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
webhook
|
|
384
|
+
.command('remove <id>')
|
|
385
|
+
.description('Remove a webhook')
|
|
386
|
+
.action(async (id) => {
|
|
387
|
+
const { removeWebhook } = await import('../lib/cli/webhook-cmd.js');
|
|
388
|
+
await removeWebhook(id);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// ── Config ─────────────────────────────────────────────
|
|
392
|
+
const config = program.command('config').description('Manage configuration');
|
|
393
|
+
|
|
394
|
+
config
|
|
395
|
+
.command('get [key]')
|
|
396
|
+
.description('Get config value')
|
|
397
|
+
.action(async (key) => {
|
|
398
|
+
const { getConfig } = await import('../lib/cli/config-cmd.js');
|
|
399
|
+
await getConfig(key);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
config
|
|
403
|
+
.command('set <key> <value>')
|
|
404
|
+
.description('Set config value')
|
|
405
|
+
.action(async (key, value) => {
|
|
406
|
+
const { setConfig } = await import('../lib/cli/config-cmd.js');
|
|
407
|
+
await setConfig(key, value);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
config
|
|
411
|
+
.command('edit')
|
|
412
|
+
.description('Open config in editor')
|
|
413
|
+
.action(async () => {
|
|
414
|
+
const { editConfig } = await import('../lib/cli/config-cmd.js');
|
|
415
|
+
await editConfig();
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// ── Conversations ──────────────────────────────────────
|
|
419
|
+
const conversations = program.command('conversations').description('Manage conversations');
|
|
420
|
+
|
|
421
|
+
conversations
|
|
422
|
+
.command('list')
|
|
423
|
+
.description('List recent conversations')
|
|
424
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
425
|
+
.option('-n, --limit <n>', 'Limit results', '20')
|
|
426
|
+
.action(async (opts) => {
|
|
427
|
+
const { listConversations } = await import('../lib/cli/conversations-cmd.js');
|
|
428
|
+
await listConversations(opts);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
conversations
|
|
432
|
+
.command('search <query>')
|
|
433
|
+
.description('Search conversations')
|
|
434
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
435
|
+
.action(async (query, opts) => {
|
|
436
|
+
const { searchConversations } = await import('../lib/cli/conversations-cmd.js');
|
|
437
|
+
await searchConversations(query, opts);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
conversations
|
|
441
|
+
.command('export')
|
|
442
|
+
.description('Export conversations')
|
|
443
|
+
.option('-a, --agent <id>', 'Filter by agent')
|
|
444
|
+
.option('-f, --format <format>', 'Export format (csv/json)', 'json')
|
|
445
|
+
.option('-o, --output <path>', 'Output file')
|
|
446
|
+
.action(async (opts) => {
|
|
447
|
+
const { exportConversations } = await import('../lib/cli/conversations-cmd.js');
|
|
448
|
+
await exportConversations(opts);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// ── Platform Mode ──────────────────────────────────────
|
|
452
|
+
const platform = program.command('platform').description('Platform integration (multi-tenant)');
|
|
453
|
+
|
|
454
|
+
platform
|
|
455
|
+
.command('init')
|
|
456
|
+
.description('Initialize platform mode')
|
|
457
|
+
.option('--supabase-url <url>', 'Supabase project URL')
|
|
458
|
+
.option('--supabase-key <key>', 'Supabase service role key')
|
|
459
|
+
.action(async (opts) => {
|
|
460
|
+
const { initPlatform } = await import('../lib/cli/platform-cmd.js');
|
|
461
|
+
await initPlatform(opts);
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
platform
|
|
465
|
+
.command('agents')
|
|
466
|
+
.description('List all platform agents')
|
|
467
|
+
.action(async () => {
|
|
468
|
+
const { platformAgents } = await import('../lib/cli/platform-cmd.js');
|
|
469
|
+
await platformAgents();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
platform
|
|
473
|
+
.command('usage')
|
|
474
|
+
.description('Platform-wide usage stats')
|
|
475
|
+
.action(async () => {
|
|
476
|
+
const { platformUsage } = await import('../lib/cli/platform-cmd.js');
|
|
477
|
+
await platformUsage();
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
// ── Update ─────────────────────────────────────────────
|
|
481
|
+
program
|
|
482
|
+
.command('update')
|
|
483
|
+
.description('Update Squidclaw to latest version')
|
|
484
|
+
.action(async () => {
|
|
485
|
+
const { update } = await import('../lib/cli/update-cmd.js');
|
|
486
|
+
await update();
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// ── Splash ─────────────────────────────────────────────
|
|
490
|
+
if (process.argv.length <= 2) {
|
|
491
|
+
console.log(chalk.cyan(`
|
|
492
|
+
🦑 Squidclaw v${pkg.version}
|
|
493
|
+
AI agent platform — human-like agents for WhatsApp & more
|
|
494
|
+
|
|
495
|
+
${chalk.gray('Get started:')} squidclaw setup
|
|
496
|
+
${chalk.gray('Help:')} squidclaw --help
|
|
497
|
+
${chalk.gray('Docs:')} https://squidclaw.dev
|
|
498
|
+
`));
|
|
499
|
+
process.exit(0);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
program.parse();
|
|
503
|
+
|
|
504
|
+
// ── TUI ────────────────────────────────────────────────
|
|
505
|
+
program
|
|
506
|
+
.command('tui')
|
|
507
|
+
.description('Open terminal chat UI')
|
|
508
|
+
.option('-a, --agent <id>', 'Start with specific agent')
|
|
509
|
+
.action(async (opts) => {
|
|
510
|
+
const { tui } = await import('../lib/cli/tui.js');
|
|
511
|
+
await tui(opts);
|
|
512
|
+
});
|