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.
Files changed (75) hide show
  1. package/README.md +252 -0
  2. package/bin/ccg-dev.sh +3 -0
  3. package/dist/agents.d.ts +17 -0
  4. package/dist/agents.d.ts.map +1 -0
  5. package/dist/agents.js +45 -0
  6. package/dist/agents.js.map +1 -0
  7. package/dist/chat.d.ts +14 -0
  8. package/dist/chat.d.ts.map +1 -0
  9. package/dist/chat.js +104 -0
  10. package/dist/chat.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +501 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +53 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +70 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/context.d.ts +45 -0
  20. package/dist/context.d.ts.map +1 -0
  21. package/dist/context.js +201 -0
  22. package/dist/context.js.map +1 -0
  23. package/dist/daemon.d.ts +27 -0
  24. package/dist/daemon.d.ts.map +1 -0
  25. package/dist/daemon.js +207 -0
  26. package/dist/daemon.js.map +1 -0
  27. package/dist/heartbeat.d.ts +42 -0
  28. package/dist/heartbeat.d.ts.map +1 -0
  29. package/dist/heartbeat.js +153 -0
  30. package/dist/heartbeat.js.map +1 -0
  31. package/dist/logger.d.ts +15 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +70 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/messaging.d.ts +43 -0
  36. package/dist/messaging.d.ts.map +1 -0
  37. package/dist/messaging.js +132 -0
  38. package/dist/messaging.js.map +1 -0
  39. package/dist/migrate.d.ts +24 -0
  40. package/dist/migrate.d.ts.map +1 -0
  41. package/dist/migrate.js +356 -0
  42. package/dist/migrate.js.map +1 -0
  43. package/dist/plugin.d.ts +63 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +93 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/plugins/discord-gateway.d.ts +32 -0
  48. package/dist/plugins/discord-gateway.d.ts.map +1 -0
  49. package/dist/plugins/discord-gateway.js +208 -0
  50. package/dist/plugins/discord-gateway.js.map +1 -0
  51. package/dist/plugins/slack-gateway.d.ts +35 -0
  52. package/dist/plugins/slack-gateway.d.ts.map +1 -0
  53. package/dist/plugins/slack-gateway.js +291 -0
  54. package/dist/plugins/slack-gateway.js.map +1 -0
  55. package/dist/router.d.ts +44 -0
  56. package/dist/router.d.ts.map +1 -0
  57. package/dist/router.js +103 -0
  58. package/dist/router.js.map +1 -0
  59. package/dist/sessions.d.ts +55 -0
  60. package/dist/sessions.d.ts.map +1 -0
  61. package/dist/sessions.js +160 -0
  62. package/dist/sessions.js.map +1 -0
  63. package/dist/skills.d.ts +58 -0
  64. package/dist/skills.d.ts.map +1 -0
  65. package/dist/skills.js +194 -0
  66. package/dist/skills.js.map +1 -0
  67. package/dist/spawner.d.ts +29 -0
  68. package/dist/spawner.d.ts.map +1 -0
  69. package/dist/spawner.js +54 -0
  70. package/dist/spawner.js.map +1 -0
  71. package/dist/types.d.ts +22 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +4 -0
  74. package/dist/types.js.map +1 -0
  75. 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
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+ SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
3
+ exec npx tsx "$SCRIPT_DIR/../src/cli.ts" "$@"
@@ -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
@@ -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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}