ccgateway 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/README.md +252 -0
- package/bin/ccg-dev.sh +3 -0
- package/dist/agents.d.ts +17 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +45 -0
- package/dist/agents.js.map +1 -0
- package/dist/chat.d.ts +14 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +104 -0
- package/dist/chat.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +501 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +53 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +70 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +45 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +201 -0
- package/dist/context.js.map +1 -0
- package/dist/daemon.d.ts +27 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +207 -0
- package/dist/daemon.js.map +1 -0
- package/dist/heartbeat.d.ts +42 -0
- package/dist/heartbeat.d.ts.map +1 -0
- package/dist/heartbeat.js +153 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/logger.d.ts +15 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +70 -0
- package/dist/logger.js.map +1 -0
- package/dist/messaging.d.ts +43 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +132 -0
- package/dist/messaging.js.map +1 -0
- package/dist/migrate.d.ts +24 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +356 -0
- package/dist/migrate.js.map +1 -0
- package/dist/plugin.d.ts +63 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +93 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugins/discord-gateway.d.ts +32 -0
- package/dist/plugins/discord-gateway.d.ts.map +1 -0
- package/dist/plugins/discord-gateway.js +208 -0
- package/dist/plugins/discord-gateway.js.map +1 -0
- package/dist/plugins/slack-gateway.d.ts +35 -0
- package/dist/plugins/slack-gateway.d.ts.map +1 -0
- package/dist/plugins/slack-gateway.js +291 -0
- package/dist/plugins/slack-gateway.js.map +1 -0
- package/dist/router.d.ts +44 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +103 -0
- package/dist/router.js.map +1 -0
- package/dist/sessions.d.ts +55 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +160 -0
- package/dist/sessions.js.map +1 -0
- package/dist/skills.d.ts +58 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +194 -0
- package/dist/skills.js.map +1 -0
- package/dist/spawner.d.ts +29 -0
- package/dist/spawner.d.ts.map +1 -0
- package/dist/spawner.js +54 -0
- package/dist/spawner.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# ccgateway
|
|
2
|
+
|
|
3
|
+
**Multi-agent orchestration for Claude Code CLI.**
|
|
4
|
+
|
|
5
|
+
You have a Claude Code subscription. You want multiple AI agents with their own identities, Discord/Slack channels, persistent conversations, and cross-agent messaging. ccgateway does that by calling `claude --print` under the hood — no API keys, no third-party harness, just your subscription.
|
|
6
|
+
|
|
7
|
+
## Why ccgateway
|
|
8
|
+
|
|
9
|
+
If you're coming from OpenClaw, you already know what multi-agent orchestration looks like. Same agent identities, same Discord channels, same memory files, same workflows. ccgateway gives you all of that running legitimately on Claude Code CLI.
|
|
10
|
+
|
|
11
|
+
One command migrates your existing setup:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
ccg migrate openclaw
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Your agents, channel bindings, bot tokens, heartbeat schedules, and skills carry over. Workspaces and memory files stay exactly where they are. Start the gateway and your agents are back online.
|
|
18
|
+
|
|
19
|
+
### How is this different?
|
|
20
|
+
|
|
21
|
+
ccgateway doesn't proxy, wrap, or intercept Claude Code sessions. Every agent invocation is a direct call to `claude --print` — the same CLI binary you run in your terminal, using your Claude Code subscription. ccgateway just manages the plumbing: who talks where, what context gets injected, and where conversation history lives.
|
|
22
|
+
|
|
23
|
+
## Comparison
|
|
24
|
+
|
|
25
|
+
| Feature | OpenClaw | ccgateway |
|
|
26
|
+
|---|---|---|
|
|
27
|
+
| Anthropic ToS compliant | No | **Yes** |
|
|
28
|
+
| Uses CC subscription (no API billing) | No | **Yes** |
|
|
29
|
+
| Multi-agent identities | Yes | Yes |
|
|
30
|
+
| Discord gateway | Yes | Yes |
|
|
31
|
+
| Slack gateway | Yes | Yes |
|
|
32
|
+
| Session persistence | Yes | Yes |
|
|
33
|
+
| Cross-agent messaging | Yes | Yes |
|
|
34
|
+
| Memory system | Yes | Yes |
|
|
35
|
+
| Skills system | Yes | Yes |
|
|
36
|
+
| Heartbeats / cron | Yes | Yes |
|
|
37
|
+
| Telegram / WhatsApp | Yes | Roadmap |
|
|
38
|
+
| Browser Tools | Yes | Roadmap |
|
|
39
|
+
| Migration from OpenClaw | — | **One command** |
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Install
|
|
45
|
+
npm install -g ccgateway
|
|
46
|
+
|
|
47
|
+
# New setup
|
|
48
|
+
ccg init
|
|
49
|
+
|
|
50
|
+
# Or migrate from OpenClaw
|
|
51
|
+
ccg migrate openclaw
|
|
52
|
+
|
|
53
|
+
# Load bot tokens and start
|
|
54
|
+
source ~/.ccgateway/.env && ccg start
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
### Multi-Agent Identities
|
|
60
|
+
|
|
61
|
+
Each agent has its own workspace directory with personality, instructions, and memory. ccgateway points Claude Code at the right workspace — identity comes from your files, not from ccgateway.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
ccg agents add --id salt --name Salt --workspace ~/clawd-salt --model claude-opus-4-6 --emoji "🧂"
|
|
65
|
+
ccg agents list
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Agents read their identity from `CLAUDE.md`, `SOUL.md`, `IDENTITY.md`, and `AGENTS.md` in their workspace. Use whatever combination works for you.
|
|
69
|
+
|
|
70
|
+
### Discord & Slack Gateways
|
|
71
|
+
|
|
72
|
+
Each agent can have its own Discord bot (with its own avatar and name) bound to specific channels. Slack works the same way with socket mode — no public URL needed.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"bindings": [
|
|
77
|
+
{ "agent": "salt", "gateway": "discord", "channel": "1465736400014938230", "bot": "salt" },
|
|
78
|
+
{ "agent": "pepper", "gateway": "slack", "channel": "C07ABC123", "bot": "pepper" }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Slash commands in chat: `/new` resets the session, `/reset` does the same, `/status` shows session info.
|
|
84
|
+
|
|
85
|
+
### Session Persistence
|
|
86
|
+
|
|
87
|
+
Conversations are stored as JSONL files — one per agent per channel. Sessions never expire. When the context window fills up (default 200k tokens), older messages drop from what gets sent to Claude, but the full history stays on disk.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ccg sessions list
|
|
91
|
+
ccg sessions inspect salt:discord:1465736400014938230
|
|
92
|
+
ccg sessions reset salt:discord:1465736400014938230
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Cross-Agent Messaging
|
|
96
|
+
|
|
97
|
+
Agents talk to each other by posting to each other's Discord/Slack channels. Salt's bot posts in Pepper's channel with Salt's avatar — the gateway picks it up and routes it to Pepper like any other message.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
ccg send pepper "RCA done for NHD-10763" --from salt
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Agents without gateway bindings fall back to a file-based inbox.
|
|
104
|
+
|
|
105
|
+
### Skills System
|
|
106
|
+
|
|
107
|
+
Skills are markdown files with instructions that agents can read and follow. Shared skills are available to all agents. Agent-specific skills override shared ones.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
ccg skills list
|
|
111
|
+
ccg skills add deploy-to-staging.md
|
|
112
|
+
ccg skills add navix-rca.md --agent salt
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Agents can also create skills from chat — they just write a `.md` file to the skills directory.
|
|
116
|
+
|
|
117
|
+
### Memory
|
|
118
|
+
|
|
119
|
+
Memory lives in agent workspaces as plain markdown files. ccgateway injects today's and yesterday's daily logs into each turn so agents have recent context without file reads.
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
~/clawd-salt/
|
|
123
|
+
├── CLAUDE.md # Identity + rules (loaded by CC automatically)
|
|
124
|
+
├── MEMORY.md # Curated long-term memory
|
|
125
|
+
└── memory/
|
|
126
|
+
├── 2026-04-05.md # Today's log
|
|
127
|
+
└── 2026-04-04.md # Yesterday's log
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Heartbeats
|
|
131
|
+
|
|
132
|
+
Minimal cron-based agent wakeups. If `HEARTBEAT.md` exists in the workspace, the agent reads it and acts. If nothing needs attention, the response is silently discarded — no tokens wasted on Discord.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
ccg heartbeat install # Write to system crontab
|
|
136
|
+
ccg heartbeat run salt # Manual trigger
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### CLI Chat
|
|
140
|
+
|
|
141
|
+
Test agents locally without Discord or Slack:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
ccg chat salt
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Same session management, same context building, same agent identity — just in your terminal.
|
|
148
|
+
|
|
149
|
+
## How It Works
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
┌──────────────────────────────────────────────┐
|
|
153
|
+
│ ccgateway (single process) │
|
|
154
|
+
│ │
|
|
155
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────────┐ │
|
|
156
|
+
│ │ Discord │ │ Slack │ │ Future │ │
|
|
157
|
+
│ │ Plugin │ │ Plugin │ │ Plugins │ │
|
|
158
|
+
│ └────┬────┘ └────┬────┘ └──────┬──────┘ │
|
|
159
|
+
│ └────────────┼──────────────┘ │
|
|
160
|
+
│ ↓ │
|
|
161
|
+
│ ┌──────────────┐ │
|
|
162
|
+
│ │ Router │ │
|
|
163
|
+
│ │ (bindings) │ │
|
|
164
|
+
│ └──────┬───────┘ │
|
|
165
|
+
│ ↓ │
|
|
166
|
+
│ ┌───────────────┐ │
|
|
167
|
+
│ │ Session Mgr │ │
|
|
168
|
+
│ │ (JSONL state) │ │
|
|
169
|
+
│ └───────┬───────┘ │
|
|
170
|
+
│ ↓ │
|
|
171
|
+
│ ┌─────────────────┐ │
|
|
172
|
+
│ │ Context Builder │ │
|
|
173
|
+
│ │ identity+history│ │
|
|
174
|
+
│ │ +skills+memory │ │
|
|
175
|
+
│ └────────┬────────┘ │
|
|
176
|
+
│ ↓ │
|
|
177
|
+
│ ┌─────────────────┐ │
|
|
178
|
+
│ │ claude --print │ │
|
|
179
|
+
│ └─────────────────┘ │
|
|
180
|
+
└──────────────────────────────────────────────┘
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Every agent invocation is stateless. ccgateway assembles the full context — identity files, conversation history, skill index, memory — and passes it to `claude --print` via `--append-system-prompt`. Claude Code reads `CLAUDE.md` from the workspace automatically. The response gets appended to the session JSONL and routed back to Discord/Slack.
|
|
184
|
+
|
|
185
|
+
No persistent processes per agent. No session hijacking. No API keys. Just `claude --print` with the right context, in the right directory.
|
|
186
|
+
|
|
187
|
+
## Migration from OpenClaw
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Preview what gets imported
|
|
191
|
+
ccg migrate openclaw --dry-run
|
|
192
|
+
|
|
193
|
+
# Run the migration
|
|
194
|
+
ccg migrate openclaw
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### What gets migrated
|
|
198
|
+
|
|
199
|
+
- **Agents** — IDs, names, emojis, workspaces, model preferences
|
|
200
|
+
- **Channel bindings** — All Discord channel-to-agent mappings (from both `bindings[]` and guild channel configs)
|
|
201
|
+
- **Bot tokens** — Written to `~/.ccgateway/.env` with actual values from your OpenClaw config
|
|
202
|
+
- **Heartbeats** — Cron schedules converted from OpenClaw's job format
|
|
203
|
+
- **Discord gateway plugin** — Auto-configured with your bots, guild, and allowed users
|
|
204
|
+
|
|
205
|
+
### What stays as-is
|
|
206
|
+
|
|
207
|
+
- Agent workspaces (`CLAUDE.md`, `SOUL.md`, `MEMORY.md`, `memory/`) — untouched
|
|
208
|
+
- Git repositories, worktrees, project files — untouched
|
|
209
|
+
- Consolidation of `AGENTS.md` + `SOUL.md` + `IDENTITY.md` into `CLAUDE.md` is optional — ccgateway reads all of them
|
|
210
|
+
|
|
211
|
+
### Both systems can run side by side during transition.
|
|
212
|
+
|
|
213
|
+
## Plugin Architecture
|
|
214
|
+
|
|
215
|
+
Gateway channels are plugins. Discord and Slack ship as built-ins. Adding a new gateway means implementing one interface:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
interface CcgPlugin {
|
|
219
|
+
name: string;
|
|
220
|
+
type: 'gateway' | 'skill' | 'tool';
|
|
221
|
+
init(core: CcgCore): Promise<void>;
|
|
222
|
+
start?(): Promise<void>;
|
|
223
|
+
stop?(): Promise<void>;
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Skill plugins handle capabilities that can't be expressed in a markdown file (e.g., browser automation). Tool plugins expose shell commands agents can call.
|
|
228
|
+
|
|
229
|
+
## Roadmap
|
|
230
|
+
|
|
231
|
+
- **Telegram gateway** — Plugin for Telegram bot API
|
|
232
|
+
- **WhatsApp gateway** — Plugin for WhatsApp Business API
|
|
233
|
+
- **Browser Tools** — Playwright-based browser interaction plugin
|
|
234
|
+
- **Shared skill packs** — Pre-built skill collections (Obsidian integration, Apple Notes, deployment workflows)
|
|
235
|
+
- **Token-accurate context budgeting** — Replace chars/4 estimation with proper tokenizer
|
|
236
|
+
|
|
237
|
+
## Configuration
|
|
238
|
+
|
|
239
|
+
Config lives at `~/.ccgateway/config.json` (or `$CCG_HOME/config.json`).
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
ccg agents list # Agents
|
|
243
|
+
ccg sessions list # Active sessions
|
|
244
|
+
ccg skills list # Available skills
|
|
245
|
+
ccg status # Daemon status
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
See the [design spec](docs/superpowers/specs/2026-04-05-ccgateway-design.md) for the full configuration reference.
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
MIT
|
package/bin/ccg-dev.sh
ADDED
package/dist/agents.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AgentConfig, CcgConfig } from "./config.js";
|
|
2
|
+
export declare class AgentRegistry {
|
|
3
|
+
private agents;
|
|
4
|
+
constructor(config: CcgConfig);
|
|
5
|
+
getAgent(id: string): AgentConfig | undefined;
|
|
6
|
+
listAgents(): AgentConfig[];
|
|
7
|
+
addAgent(agent: AgentConfig): void;
|
|
8
|
+
removeAgent(id: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Validate that the agent's workspace directory exists and contains a CLAUDE.md file.
|
|
11
|
+
*/
|
|
12
|
+
validateWorkspace(id: string): {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
errors: string[];
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI1D,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA2B;gBAE7B,MAAM,EAAE,SAAS;IAO7B,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI7C,UAAU,IAAI,WAAW,EAAE;IAI3B,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAOlC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAkBpE"}
|
package/dist/agents.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
// ── AgentRegistry ──────────────────────────────────────────────────────────
|
|
4
|
+
export class AgentRegistry {
|
|
5
|
+
agents;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.agents = new Map();
|
|
8
|
+
for (const agent of config.agents) {
|
|
9
|
+
this.agents.set(agent.id, agent);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
getAgent(id) {
|
|
13
|
+
return this.agents.get(id);
|
|
14
|
+
}
|
|
15
|
+
listAgents() {
|
|
16
|
+
return Array.from(this.agents.values());
|
|
17
|
+
}
|
|
18
|
+
addAgent(agent) {
|
|
19
|
+
if (this.agents.has(agent.id)) {
|
|
20
|
+
throw new Error(`Agent with id "${agent.id}" already exists`);
|
|
21
|
+
}
|
|
22
|
+
this.agents.set(agent.id, agent);
|
|
23
|
+
}
|
|
24
|
+
removeAgent(id) {
|
|
25
|
+
return this.agents.delete(id);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validate that the agent's workspace directory exists and contains a CLAUDE.md file.
|
|
29
|
+
*/
|
|
30
|
+
validateWorkspace(id) {
|
|
31
|
+
const agent = this.agents.get(id);
|
|
32
|
+
const errors = [];
|
|
33
|
+
if (!agent) {
|
|
34
|
+
return { valid: false, errors: [`Agent "${id}" not found in registry`] };
|
|
35
|
+
}
|
|
36
|
+
if (!existsSync(agent.workspace)) {
|
|
37
|
+
errors.push(`Workspace directory does not exist: ${agent.workspace}`);
|
|
38
|
+
}
|
|
39
|
+
else if (!existsSync(join(agent.workspace, "CLAUDE.md"))) {
|
|
40
|
+
errors.push(`Workspace is missing CLAUDE.md: ${join(agent.workspace, "CLAUDE.md")}`);
|
|
41
|
+
}
|
|
42
|
+
return { valid: errors.length === 0, errors };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,8EAA8E;AAE9E,MAAM,OAAO,aAAa;IAChB,MAAM,CAA2B;IAEzC,YAAY,MAAiB;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACxB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,EAAU;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,UAAU;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ,CAAC,KAAkB;QACzB,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,EAAU;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,UAAU,EAAE,yBAAyB,CAAC,EAAE,CAAC;QAC3E,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,IAAI,CAAC,uCAAuC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QACxE,CAAC;aAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,IAAI,CACT,mCAAmC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,CACxE,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAChD,CAAC;CACF"}
|
package/dist/chat.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AgentRegistry } from "./agents.js";
|
|
2
|
+
import type { SessionManager } from "./sessions.js";
|
|
3
|
+
import type { ContextBuilder } from "./context.js";
|
|
4
|
+
import type { CCSpawner } from "./spawner.js";
|
|
5
|
+
/**
|
|
6
|
+
* Build the session key for CLI chat sessions.
|
|
7
|
+
* Format: {agentId}:cli:manual
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildChatSessionKey(agentId: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Start an interactive chat REPL with the specified agent.
|
|
12
|
+
*/
|
|
13
|
+
export declare function startChat(agentId: string, agents: AgentRegistry, sessions: SessionManager, context: ContextBuilder, spawner: CCSpawner): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,SAAS,GACjB,OAAO,CAAC,IAAI,CAAC,CA2Gf"}
|
package/dist/chat.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
// ── Chat REPL ──────────────────────────────────────────────────────────────
|
|
3
|
+
/**
|
|
4
|
+
* Build the session key for CLI chat sessions.
|
|
5
|
+
* Format: {agentId}:cli:manual
|
|
6
|
+
*/
|
|
7
|
+
export function buildChatSessionKey(agentId) {
|
|
8
|
+
return `${agentId}:cli:manual`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Start an interactive chat REPL with the specified agent.
|
|
12
|
+
*/
|
|
13
|
+
export async function startChat(agentId, agents, sessions, context, spawner) {
|
|
14
|
+
// 1. Validate agent exists
|
|
15
|
+
const agent = agents.getAgent(agentId);
|
|
16
|
+
if (!agent) {
|
|
17
|
+
throw new Error(`Agent "${agentId}" not found`);
|
|
18
|
+
}
|
|
19
|
+
// 2. Create session key
|
|
20
|
+
const sessionKey = buildChatSessionKey(agentId);
|
|
21
|
+
console.log(`Chat with ${agent.name} (${agentId}) — model: ${agent.model}`);
|
|
22
|
+
console.log(`Session: ${sessionKey}`);
|
|
23
|
+
console.log(`Commands: /new or /reset (reset session), /quit or /exit (exit)`);
|
|
24
|
+
console.log(`Tip: end a line with \\ for multi-line input`);
|
|
25
|
+
console.log();
|
|
26
|
+
// 3. REPL loop
|
|
27
|
+
const rl = createInterface({
|
|
28
|
+
input: process.stdin,
|
|
29
|
+
output: process.stdout,
|
|
30
|
+
});
|
|
31
|
+
const prompt = () => new Promise((resolve) => {
|
|
32
|
+
rl.question("you> ", (answer) => resolve(answer));
|
|
33
|
+
rl.once("close", () => resolve(null));
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
while (true) {
|
|
37
|
+
const firstLine = await prompt();
|
|
38
|
+
// EOF (Ctrl+D)
|
|
39
|
+
if (firstLine === null) {
|
|
40
|
+
console.log();
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
// Support multi-line input: if line ends with \, keep reading
|
|
44
|
+
let input = firstLine;
|
|
45
|
+
while (input.endsWith("\\")) {
|
|
46
|
+
input = input.slice(0, -1) + "\n";
|
|
47
|
+
const continuation = await prompt();
|
|
48
|
+
if (continuation === null)
|
|
49
|
+
break;
|
|
50
|
+
input += continuation;
|
|
51
|
+
}
|
|
52
|
+
const trimmed = input.trim();
|
|
53
|
+
// Skip empty input
|
|
54
|
+
if (trimmed === "")
|
|
55
|
+
continue;
|
|
56
|
+
// Handle commands
|
|
57
|
+
if (trimmed === "/quit" || trimmed === "/exit") {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
if (trimmed === "/new" || trimmed === "/reset") {
|
|
61
|
+
await sessions.resetSession(agentId, sessionKey);
|
|
62
|
+
console.log("Session reset.\n");
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Append user message to session
|
|
66
|
+
await sessions.appendMessage(agentId, sessionKey, {
|
|
67
|
+
role: "user",
|
|
68
|
+
content: trimmed,
|
|
69
|
+
ts: Date.now(),
|
|
70
|
+
source: "cli",
|
|
71
|
+
sourceUser: "user",
|
|
72
|
+
});
|
|
73
|
+
// Build context
|
|
74
|
+
const contextStr = await context.build(agentId, sessionKey);
|
|
75
|
+
// Spawn claude --print
|
|
76
|
+
const result = await spawner.spawn({
|
|
77
|
+
workspace: agent.workspace,
|
|
78
|
+
message: trimmed,
|
|
79
|
+
systemPrompt: contextStr,
|
|
80
|
+
model: agent.model,
|
|
81
|
+
allowedTools: agent.allowedTools,
|
|
82
|
+
});
|
|
83
|
+
// Print response
|
|
84
|
+
console.log();
|
|
85
|
+
console.log(result.response);
|
|
86
|
+
console.log();
|
|
87
|
+
// Append assistant response to session
|
|
88
|
+
await sessions.appendMessage(agentId, sessionKey, {
|
|
89
|
+
role: "assistant",
|
|
90
|
+
content: result.response,
|
|
91
|
+
ts: Date.now(),
|
|
92
|
+
source: "cli",
|
|
93
|
+
tokens: result.tokensEstimate,
|
|
94
|
+
});
|
|
95
|
+
// Show token usage estimate
|
|
96
|
+
console.log(` [tokens ~ in: ${result.tokensEstimate.in}, out: ${result.tokensEstimate.out}]`);
|
|
97
|
+
console.log();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
rl.close();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=chat.js.map
|
package/dist/chat.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|