aicp-claude-agent 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 +161 -0
- package/dist/claude/sdk.d.ts +34 -0
- package/dist/claude/sdk.d.ts.map +1 -0
- package/dist/claude/sdk.js +112 -0
- package/dist/claude/sdk.js.map +1 -0
- package/dist/commands/index.d.ts +10 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +32 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/resume.d.ts +6 -0
- package/dist/commands/resume.d.ts.map +1 -0
- package/dist/commands/resume.js +75 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +118 -0
- package/dist/config.js.map +1 -0
- package/dist/history.d.ts +9 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +87 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +344 -0
- package/dist/main.js.map +1 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +129 -0
- package/dist/setup.js.map +1 -0
- package/dist/terminal/prompt.d.ts +29 -0
- package/dist/terminal/prompt.d.ts.map +1 -0
- package/dist/terminal/prompt.js +764 -0
- package/dist/terminal/prompt.js.map +1 -0
- package/dist/terminal/spinner.d.ts +7 -0
- package/dist/terminal/spinner.d.ts.map +1 -0
- package/dist/terminal/spinner.js +114 -0
- package/dist/terminal/spinner.js.map +1 -0
- package/dist/types/protocol.d.ts +59 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +4 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/update.d.ts +2 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +65 -0
- package/dist/update.js.map +1 -0
- package/dist/websocket/client.d.ts +8 -0
- package/dist/websocket/client.d.ts.map +1 -0
- package/dist/websocket/client.js +120 -0
- package/dist/websocket/client.js.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# aicp-claude-agent
|
|
2
|
+
|
|
3
|
+
**Claude Conductor Agent (CCA)** --- local CLI wrapper that connects Claude Code to the AICP backend via WebSocket.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
CCA runs on your local machine alongside Claude Code. It:
|
|
8
|
+
|
|
9
|
+
1. Executes prompts via the Claude Agent SDK (`@anthropic-ai/claude-agent-sdk`).
|
|
10
|
+
2. Opens a persistent WebSocket connection to the AICP backend (`aicp-app`).
|
|
11
|
+
3. Authenticates using an API key generated in the AICP web UI.
|
|
12
|
+
4. Registers as an agent for a specific project.
|
|
13
|
+
5. Receives `execute_prompt` commands from the backend and executes them via the SDK.
|
|
14
|
+
6. Streams Claude Code output back to the backend in real time.
|
|
15
|
+
7. Reports execution completion with token usage, cost, and duration stats.
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- Node.js 22+
|
|
20
|
+
- Claude Code CLI installed and accessible as `claude` in your PATH
|
|
21
|
+
- A running AICP backend (`aicp-app`)
|
|
22
|
+
- An API key generated from the AICP web UI (Avatar > API Keys)
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install
|
|
28
|
+
npm run dev -- --setup
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The interactive setup prompts for:
|
|
32
|
+
|
|
33
|
+
| Step | Description | Saved to |
|
|
34
|
+
|------|-------------|----------|
|
|
35
|
+
| Backend URL | WebSocket URL (e.g., `ws://localhost:8080/ws`) | `~/.aicp/config.json` |
|
|
36
|
+
| Machine name | Label for this agent (defaults to hostname) | `~/.aicp/config.json` |
|
|
37
|
+
| API key | Paste from AICP web UI, must start with `aicp_` | `~/.aicp/config.json` |
|
|
38
|
+
| Project | Select from list fetched via authenticated API | `.aicp/aicp.json` (local dir) |
|
|
39
|
+
|
|
40
|
+
## Running
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Development
|
|
44
|
+
npm run dev
|
|
45
|
+
|
|
46
|
+
# Note: the SDK always runs with bypassPermissions mode
|
|
47
|
+
|
|
48
|
+
# Production
|
|
49
|
+
npm run build
|
|
50
|
+
npm start
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
### Config Files
|
|
56
|
+
|
|
57
|
+
| File | Scope | Contains |
|
|
58
|
+
|------|-------|----------|
|
|
59
|
+
| `~/.aicp/config.json` | Global (all projects) | `backend_url`, `machine_name`, `api_key` |
|
|
60
|
+
| `.aicp/aicp.json` | Per-directory (project) | `project_id` |
|
|
61
|
+
|
|
62
|
+
The agent searches up the directory tree for `.aicp/aicp.json` (or legacy `.aicp.json`), so you can place it at your repo root.
|
|
63
|
+
|
|
64
|
+
### Environment Variables
|
|
65
|
+
|
|
66
|
+
Environment variables override config file values:
|
|
67
|
+
|
|
68
|
+
| Variable | Config file key | Description |
|
|
69
|
+
|----------|----------------|-------------|
|
|
70
|
+
| `BACKEND_WS_URL` | `backend_url` | WebSocket URL to AICP backend |
|
|
71
|
+
| `MACHINE_NAME` | `machine_name` | Agent machine label |
|
|
72
|
+
| `AICP_API_KEY` | `api_key` | API key for authentication |
|
|
73
|
+
| `PROJECT_ID` | `project_id` | Project to register with |
|
|
74
|
+
| `AGENT_ID` | --- | Override agent UUID (auto-generated if not set) |
|
|
75
|
+
|
|
76
|
+
Create a `.env.local` file for local development:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
BACKEND_WS_URL=ws://localhost:8080/ws
|
|
80
|
+
AICP_API_KEY=aicp_your_key_here
|
|
81
|
+
PROJECT_ID=your_project_id
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Architecture
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
┌──────────────────────────────────────────────────┐
|
|
88
|
+
│ aicp-claude-agent │
|
|
89
|
+
│ │
|
|
90
|
+
│ ┌──────────┐ ┌──────────────┐ │
|
|
91
|
+
│ │ index.ts │────>│ main.ts │ │
|
|
92
|
+
│ │ (entry) │ │ (orchestrator)│ │
|
|
93
|
+
│ └──────────┘ └──────┬───────┘ │
|
|
94
|
+
│ │ │ │
|
|
95
|
+
│ ┌──────┴──┐ ┌──┴───────────┐ │
|
|
96
|
+
│ │ claude/ │ │ websocket/ │ │
|
|
97
|
+
│ │ sdk.ts │ │ client.ts │ │
|
|
98
|
+
│ │ (SDK) │ │ (WS conn) │ │
|
|
99
|
+
│ └──────────┘ └──────────────┘ │
|
|
100
|
+
│ │ │ │
|
|
101
|
+
│ Claude Agent AICP Backend │
|
|
102
|
+
│ SDK (WebSocket) │
|
|
103
|
+
└──────────────────────────────────────────────────┘
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Source Files
|
|
107
|
+
|
|
108
|
+
| File | Purpose |
|
|
109
|
+
|------|---------|
|
|
110
|
+
| `src/index.ts` | Entry point — loads dotenv, routes to `--setup` or `main` |
|
|
111
|
+
| `src/main.ts` | Orchestrator — SDK↔WS bridge, execution lifecycle, terminal UI |
|
|
112
|
+
| `src/config.ts` | Config loading — merges env vars, global config, local config |
|
|
113
|
+
| `src/setup.ts` | Interactive setup wizard |
|
|
114
|
+
| `src/history.ts` | Persistent input history |
|
|
115
|
+
| `src/claude/sdk.ts` | Claude Agent SDK — execute prompts, list sessions |
|
|
116
|
+
| `src/commands/index.ts` | Slash command dispatcher (`/help`, `/resume`) |
|
|
117
|
+
| `src/commands/resume.ts` | `/resume` command — resume previous sessions |
|
|
118
|
+
| `src/terminal/prompt.ts` | Styled readline prompt, banner, status bar |
|
|
119
|
+
| `src/terminal/spinner.ts` | Animated execution spinner with tool/token info |
|
|
120
|
+
| `src/websocket/client.ts` | WebSocket client — connect, reconnect, heartbeat, send/receive |
|
|
121
|
+
| `src/types/protocol.ts` | Strict TypeScript types for the WS protocol |
|
|
122
|
+
|
|
123
|
+
## WebSocket Protocol
|
|
124
|
+
|
|
125
|
+
### Agent -> Backend
|
|
126
|
+
|
|
127
|
+
| Message | Fields | When |
|
|
128
|
+
|---------|--------|------|
|
|
129
|
+
| `register` | `agent_id`, `project_id`, `machine_name` | On connect |
|
|
130
|
+
| `heartbeat` | --- | Every 10 seconds |
|
|
131
|
+
| `status` | `status` (`idle`/`busy`/`offline`) | On state change |
|
|
132
|
+
| `message` | `session_id`, `role`, `content`, `timestamp` | During execution |
|
|
133
|
+
| `execution_complete` | `prompt_id`, `session_id`, `token_usage?`, `cost_usd?`, `num_turns?`, `duration_ms?` | When execution finishes |
|
|
134
|
+
| `local_prompt` | `text` | When user types a prompt locally |
|
|
135
|
+
|
|
136
|
+
### Backend -> Agent
|
|
137
|
+
|
|
138
|
+
| Message | Fields | When |
|
|
139
|
+
|---------|--------|------|
|
|
140
|
+
| `registered` | `agent_id` | After successful registration |
|
|
141
|
+
| `heartbeat_ack` | --- | In response to heartbeat |
|
|
142
|
+
| `execute_prompt` | `prompt_id`, `session_id`, `text` | When user clicks Execute in the UI |
|
|
143
|
+
| `error` | `error` | On any server-side error |
|
|
144
|
+
|
|
145
|
+
## Agent States
|
|
146
|
+
|
|
147
|
+
| State | Description |
|
|
148
|
+
|-------|-------------|
|
|
149
|
+
| **idle** | Connected, waiting for work. Only state where new prompts are accepted. |
|
|
150
|
+
| **busy** | Executing a prompt. New execute requests are ignored (no queueing). |
|
|
151
|
+
| **offline** | Disconnected. Auto-reconnects with exponential backoff (1s to 30s). |
|
|
152
|
+
|
|
153
|
+
## Part of AICP
|
|
154
|
+
|
|
155
|
+
This repo is one of three that make up AICP:
|
|
156
|
+
|
|
157
|
+
| Repo | Purpose |
|
|
158
|
+
|------|---------|
|
|
159
|
+
| `aicp-app` | Web application (Fastify backend + React frontend) |
|
|
160
|
+
| `aicp-infra` | Terraform infrastructure (Cloud Run, Firestore, IAM) |
|
|
161
|
+
| **`aicp-claude-agent`** | **This repo** — CLI agent wrapping Claude Code |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SDKSessionInfo } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
export interface ExecutionMessage {
|
|
3
|
+
role: 'assistant' | 'result';
|
|
4
|
+
content: string;
|
|
5
|
+
stats?: ExecutionStats;
|
|
6
|
+
}
|
|
7
|
+
export interface ExecutionStats {
|
|
8
|
+
input_tokens: number;
|
|
9
|
+
output_tokens: number;
|
|
10
|
+
cost_usd: number;
|
|
11
|
+
num_turns: number;
|
|
12
|
+
duration_ms: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ContextInfo {
|
|
15
|
+
inputTokens: number;
|
|
16
|
+
contextWindow: number;
|
|
17
|
+
}
|
|
18
|
+
export interface ToolEvent {
|
|
19
|
+
type: 'tool_start' | 'tool_progress' | 'tool_end';
|
|
20
|
+
toolName: string;
|
|
21
|
+
toolUseId?: string;
|
|
22
|
+
elapsedSeconds?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ExecuteOptions {
|
|
25
|
+
cwd?: string;
|
|
26
|
+
resumeSessionId?: string;
|
|
27
|
+
onProgress?: (text: string) => void;
|
|
28
|
+
onContextUpdate?: (info: ContextInfo) => void;
|
|
29
|
+
onToolEvent?: (event: ToolEvent) => void;
|
|
30
|
+
}
|
|
31
|
+
export { SDKSessionInfo };
|
|
32
|
+
export declare function listRecentSessions(cwd?: string, limit?: number): Promise<SDKSessionInfo[]>;
|
|
33
|
+
export declare function executePrompt(text: string, opts?: ExecuteOptions): AsyncGenerator<ExecutionMessage>;
|
|
34
|
+
//# sourceMappingURL=sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/claude/sdk.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,gCAAgC,CAAC;AAIjF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,GAAG,eAAe,GAAG,UAAU,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC9C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC1C;AAID,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,wBAAsB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAQ5F;AAID,wBAAuB,aAAa,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,cAAmB,GACxB,cAAc,CAAC,gBAAgB,CAAC,CAalC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listRecentSessions = listRecentSessions;
|
|
4
|
+
exports.executePrompt = executePrompt;
|
|
5
|
+
const claude_agent_sdk_1 = require("@anthropic-ai/claude-agent-sdk");
|
|
6
|
+
async function listRecentSessions(cwd, limit = 20) {
|
|
7
|
+
const sessions = await (0, claude_agent_sdk_1.listSessions)({
|
|
8
|
+
dir: cwd || process.cwd(),
|
|
9
|
+
limit,
|
|
10
|
+
});
|
|
11
|
+
// Sort by most recent first
|
|
12
|
+
return sessions.sort((a, b) => b.lastModified - a.lastModified);
|
|
13
|
+
}
|
|
14
|
+
// ─── Prompt execution ────────────────────────────────────────────
|
|
15
|
+
async function* executePrompt(text, opts = {}) {
|
|
16
|
+
const q = (0, claude_agent_sdk_1.query)({
|
|
17
|
+
prompt: text,
|
|
18
|
+
options: {
|
|
19
|
+
cwd: opts.cwd || process.cwd(),
|
|
20
|
+
permissionMode: 'bypassPermissions',
|
|
21
|
+
allowDangerouslySkipPermissions: true,
|
|
22
|
+
includePartialMessages: true,
|
|
23
|
+
...(opts.resumeSessionId ? { resume: opts.resumeSessionId } : {}),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
yield* processMessages(q, opts.onProgress, opts.onContextUpdate, opts.onToolEvent);
|
|
27
|
+
}
|
|
28
|
+
// ─── Shared message processing ───────────────────────────────────
|
|
29
|
+
async function* processMessages(stream, onProgress, onContextUpdate, onToolEvent) {
|
|
30
|
+
let activeToolId;
|
|
31
|
+
for await (const message of stream) {
|
|
32
|
+
if (message.type === 'stream_event') {
|
|
33
|
+
const event = message.event;
|
|
34
|
+
if (event?.type === 'content_block_delta' && event?.delta?.type === 'text_delta') {
|
|
35
|
+
onProgress?.(event.delta.text);
|
|
36
|
+
}
|
|
37
|
+
else if (event?.type === 'content_block_start' && event?.content_block?.type === 'tool_use') {
|
|
38
|
+
const toolName = event.content_block.name || 'unknown';
|
|
39
|
+
activeToolId = event.content_block.id;
|
|
40
|
+
onToolEvent?.({ type: 'tool_start', toolName, toolUseId: activeToolId });
|
|
41
|
+
}
|
|
42
|
+
else if (event?.type === 'content_block_stop' && activeToolId) {
|
|
43
|
+
onToolEvent?.({ type: 'tool_end', toolName: '', toolUseId: activeToolId });
|
|
44
|
+
activeToolId = undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (message.type === 'tool_progress') {
|
|
48
|
+
const msg = message;
|
|
49
|
+
onToolEvent?.({
|
|
50
|
+
type: 'tool_progress',
|
|
51
|
+
toolName: msg.tool_name || '',
|
|
52
|
+
elapsedSeconds: msg.elapsed_time_seconds,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
else if (message.type === 'assistant') {
|
|
56
|
+
const msg = message;
|
|
57
|
+
const content = msg.message?.content;
|
|
58
|
+
// Extract usage for context tracking
|
|
59
|
+
if (onContextUpdate && msg.message?.usage) {
|
|
60
|
+
const usage = msg.message.usage;
|
|
61
|
+
if (usage.input_tokens) {
|
|
62
|
+
onContextUpdate({
|
|
63
|
+
inputTokens: usage.input_tokens,
|
|
64
|
+
contextWindow: 0, // Will be set from result message
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(content)) {
|
|
69
|
+
// Emit tool events from assistant content blocks (fallback for non-streaming)
|
|
70
|
+
for (const block of content) {
|
|
71
|
+
if (block.type === 'tool_use') {
|
|
72
|
+
onToolEvent?.({ type: 'tool_start', toolName: block.name, toolUseId: block.id });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const textParts = content
|
|
76
|
+
.filter((block) => block.type === 'text')
|
|
77
|
+
.map((block) => block.text);
|
|
78
|
+
if (textParts.length > 0) {
|
|
79
|
+
yield { role: 'assistant', content: textParts.join('\n') };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else if (message.type === 'result') {
|
|
84
|
+
const msg = message;
|
|
85
|
+
// Extract context window from modelUsage
|
|
86
|
+
if (onContextUpdate && msg.modelUsage) {
|
|
87
|
+
const models = Object.values(msg.modelUsage);
|
|
88
|
+
if (models.length > 0) {
|
|
89
|
+
const model = models[0];
|
|
90
|
+
onContextUpdate({
|
|
91
|
+
inputTokens: model.inputTokens || 0,
|
|
92
|
+
contextWindow: model.contextWindow || 0,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if ('result' in message) {
|
|
97
|
+
yield {
|
|
98
|
+
role: 'result',
|
|
99
|
+
content: msg.result,
|
|
100
|
+
stats: {
|
|
101
|
+
input_tokens: msg.usage?.input_tokens || 0,
|
|
102
|
+
output_tokens: msg.usage?.output_tokens || 0,
|
|
103
|
+
cost_usd: msg.total_cost_usd || 0,
|
|
104
|
+
num_turns: msg.num_turns || 0,
|
|
105
|
+
duration_ms: msg.duration_ms || 0,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/claude/sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface CommandResult {
|
|
2
|
+
handled: boolean;
|
|
3
|
+
resumeSessionId?: string;
|
|
4
|
+
}
|
|
5
|
+
interface Questionable {
|
|
6
|
+
question(prompt: string, cb: (answer: string) => void): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function dispatch(input: string, rl: Questionable): Promise<CommandResult>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAcD,UAAU,YAAY;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CAC9D;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAmBtF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dispatch = dispatch;
|
|
4
|
+
const resume_1 = require("./resume");
|
|
5
|
+
const prompt_1 = require("../terminal/prompt");
|
|
6
|
+
const COMMANDS = {
|
|
7
|
+
'/resume': 'Resume a previous Claude session',
|
|
8
|
+
'/help': 'Show available commands',
|
|
9
|
+
};
|
|
10
|
+
function helpCommand() {
|
|
11
|
+
(0, prompt_1.printInfo)('Available commands:');
|
|
12
|
+
for (const [cmd, desc] of Object.entries(COMMANDS)) {
|
|
13
|
+
(0, prompt_1.writeAbove)(` \x1b[1m\x1b[37m${cmd.padEnd(12)}\x1b[0m \x1b[2m\x1b[38;5;240m${desc}\x1b[0m`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async function dispatch(input, rl) {
|
|
17
|
+
const cmd = input.toLowerCase().trim();
|
|
18
|
+
if (cmd === '/help') {
|
|
19
|
+
helpCommand();
|
|
20
|
+
return { handled: true };
|
|
21
|
+
}
|
|
22
|
+
if (cmd === '/resume') {
|
|
23
|
+
const sessionId = await (0, resume_1.resumeCommand)(rl);
|
|
24
|
+
return { handled: true, resumeSessionId: sessionId || undefined };
|
|
25
|
+
}
|
|
26
|
+
if (cmd.startsWith('/')) {
|
|
27
|
+
(0, prompt_1.printInfo)(`Unknown command: ${cmd}. Type /help for available commands.`);
|
|
28
|
+
return { handled: true };
|
|
29
|
+
}
|
|
30
|
+
return { handled: false };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":";;AAwBA,4BAmBC;AA3CD,qCAAyC;AACzC,+CAA2D;AAO3D,MAAM,QAAQ,GAA2B;IACvC,SAAS,EAAE,kCAAkC;IAC7C,OAAO,EAAE,yBAAyB;CACnC,CAAC;AAEF,SAAS,WAAW;IAClB,IAAA,kBAAS,EAAC,qBAAqB,CAAC,CAAC;IACjC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,IAAA,mBAAU,EAAC,oBAAoB,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,gCAAgC,IAAI,SAAS,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAMM,KAAK,UAAU,QAAQ,CAAC,KAAa,EAAE,EAAgB;IAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAEvC,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,WAAW,EAAE,CAAC;QACd,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,MAAM,IAAA,sBAAa,EAAC,EAAE,CAAC,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,IAAI,SAAS,EAAE,CAAC;IACpE,CAAC;IAED,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,IAAA,kBAAS,EAAC,oBAAoB,GAAG,sCAAsC,CAAC,CAAC;QACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/commands/resume.ts"],"names":[],"mappings":"AA0BA,UAAU,YAAY;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;CAC9D;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmD5E"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resumeCommand = resumeCommand;
|
|
4
|
+
const sdk_1 = require("../claude/sdk");
|
|
5
|
+
const prompt_1 = require("../terminal/prompt");
|
|
6
|
+
const DIM = '\x1b[2m';
|
|
7
|
+
const RESET = '\x1b[0m';
|
|
8
|
+
const BOLD = '\x1b[1m';
|
|
9
|
+
const CYAN = '\x1b[36m';
|
|
10
|
+
const GRAY = '\x1b[38;5;240m';
|
|
11
|
+
const WHITE = '\x1b[37m';
|
|
12
|
+
function timeAgo(ms) {
|
|
13
|
+
const seconds = Math.floor((Date.now() - ms) / 1000);
|
|
14
|
+
if (seconds < 60)
|
|
15
|
+
return 'just now';
|
|
16
|
+
const minutes = Math.floor(seconds / 60);
|
|
17
|
+
if (minutes < 60)
|
|
18
|
+
return `${minutes}m ago`;
|
|
19
|
+
const hours = Math.floor(minutes / 60);
|
|
20
|
+
if (hours < 24)
|
|
21
|
+
return `${hours}h ago`;
|
|
22
|
+
const days = Math.floor(hours / 24);
|
|
23
|
+
return `${days}d ago`;
|
|
24
|
+
}
|
|
25
|
+
function truncate(str, max) {
|
|
26
|
+
if (str.length <= max)
|
|
27
|
+
return str;
|
|
28
|
+
return str.slice(0, max - 1) + '…';
|
|
29
|
+
}
|
|
30
|
+
async function resumeCommand(rl) {
|
|
31
|
+
(0, prompt_1.printInfo)('Loading sessions...');
|
|
32
|
+
let sessions;
|
|
33
|
+
try {
|
|
34
|
+
sessions = await (0, sdk_1.listRecentSessions)(process.cwd(), 10);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
(0, prompt_1.printError)(`Failed to list sessions: ${err.message}`);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (sessions.length === 0) {
|
|
41
|
+
(0, prompt_1.printInfo)('No sessions found for this directory.');
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
(0, prompt_1.printDivider)();
|
|
45
|
+
(0, prompt_1.printStatus)('Recent Sessions');
|
|
46
|
+
(0, prompt_1.writeAbove)('');
|
|
47
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
48
|
+
const s = sessions[i];
|
|
49
|
+
const num = `${BOLD}${WHITE} ${String(i + 1).padStart(2)}.${RESET}`;
|
|
50
|
+
const title = truncate(s.summary || s.firstPrompt || '(untitled)', 50);
|
|
51
|
+
const time = `${DIM}${GRAY}${timeAgo(s.lastModified)}${RESET}`;
|
|
52
|
+
const branch = s.gitBranch ? `${DIM}${CYAN}[${s.gitBranch}]${RESET}` : '';
|
|
53
|
+
(0, prompt_1.writeAbove)(`${num} ${title} ${time} ${branch}`);
|
|
54
|
+
}
|
|
55
|
+
(0, prompt_1.writeAbove)('');
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
rl.question(`${DIM}${GRAY} Pick session (1-${sessions.length}) or Enter to cancel: ${RESET}`, (answer) => {
|
|
58
|
+
const trimmed = answer.trim();
|
|
59
|
+
if (!trimmed) {
|
|
60
|
+
resolve(null);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const idx = parseInt(trimmed, 10) - 1;
|
|
64
|
+
if (isNaN(idx) || idx < 0 || idx >= sessions.length) {
|
|
65
|
+
(0, prompt_1.printError)('Invalid selection.');
|
|
66
|
+
resolve(null);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const selected = sessions[idx];
|
|
70
|
+
(0, prompt_1.printInfo)(`Resuming: ${selected.summary || selected.sessionId}`);
|
|
71
|
+
resolve(selected.sessionId);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../src/commands/resume.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface Config {
|
|
2
|
+
backendUrl: string;
|
|
3
|
+
machineName: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
agentId: string;
|
|
6
|
+
apiKey: string;
|
|
7
|
+
dangerouslySkipPermissions: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface GlobalConfig {
|
|
10
|
+
backend_url?: string;
|
|
11
|
+
machine_name?: string;
|
|
12
|
+
api_key?: string;
|
|
13
|
+
}
|
|
14
|
+
interface LocalConfig {
|
|
15
|
+
project_id?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function readGlobalConfig(): GlobalConfig;
|
|
18
|
+
export declare function writeGlobalConfig(data: GlobalConfig): void;
|
|
19
|
+
export declare function readLocalConfig(): LocalConfig;
|
|
20
|
+
export declare function writeLocalConfig(data: LocalConfig): void;
|
|
21
|
+
export declare function findLocalConfigPath(): string | null;
|
|
22
|
+
/** Returns the .aicp/ directory path for the current project (creates if needed) */
|
|
23
|
+
export declare function localAicpDir(): string;
|
|
24
|
+
export declare const config: Config;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,UAAU,MAAM;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B,EAAE,OAAO,CAAC;CACrC;AAED,UAAU,YAAY;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,WAAW;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA4BD,wBAAgB,gBAAgB,IAAI,YAAY,CAE/C;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAE1D;AAED,wBAAgB,eAAe,IAAI,WAAW,CAE7C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAExD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAanD;AAED,oFAAoF;AACpF,wBAAgB,YAAY,IAAI,MAAM,CAYrC;AAwCD,eAAO,MAAM,MAAM,EAAE,MAInB,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.config = void 0;
|
|
7
|
+
exports.readGlobalConfig = readGlobalConfig;
|
|
8
|
+
exports.writeGlobalConfig = writeGlobalConfig;
|
|
9
|
+
exports.readLocalConfig = readLocalConfig;
|
|
10
|
+
exports.writeLocalConfig = writeLocalConfig;
|
|
11
|
+
exports.findLocalConfigPath = findLocalConfigPath;
|
|
12
|
+
exports.localAicpDir = localAicpDir;
|
|
13
|
+
const os_1 = __importDefault(require("os"));
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const path_1 = __importDefault(require("path"));
|
|
16
|
+
const uuid_1 = require("uuid");
|
|
17
|
+
const GLOBAL_DIR = path_1.default.join(os_1.default.homedir(), '.aicp');
|
|
18
|
+
const GLOBAL_PATH = path_1.default.join(GLOBAL_DIR, 'config.json');
|
|
19
|
+
const LOCAL_DIR = '.aicp';
|
|
20
|
+
const LOCAL_FILENAME = 'aicp.json';
|
|
21
|
+
const LEGACY_LOCAL_FILENAME = '.aicp.json';
|
|
22
|
+
// ─── File I/O ───────────────────────────────────────────────────────
|
|
23
|
+
function readJson(filePath) {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(fs_1.default.readFileSync(filePath, 'utf-8'));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function writeJson(filePath, data) {
|
|
32
|
+
const dir = path_1.default.dirname(filePath);
|
|
33
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
34
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
fs_1.default.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
|
|
37
|
+
}
|
|
38
|
+
// ─── Public ─────────────────────────────────────────────────────────
|
|
39
|
+
function readGlobalConfig() {
|
|
40
|
+
return readJson(GLOBAL_PATH) || {};
|
|
41
|
+
}
|
|
42
|
+
function writeGlobalConfig(data) {
|
|
43
|
+
writeJson(GLOBAL_PATH, data);
|
|
44
|
+
}
|
|
45
|
+
function readLocalConfig() {
|
|
46
|
+
return readJson(findLocalConfigPath() || '') || {};
|
|
47
|
+
}
|
|
48
|
+
function writeLocalConfig(data) {
|
|
49
|
+
writeJson(path_1.default.join(process.cwd(), LOCAL_DIR, LOCAL_FILENAME), data);
|
|
50
|
+
}
|
|
51
|
+
function findLocalConfigPath() {
|
|
52
|
+
let dir = process.cwd();
|
|
53
|
+
while (true) {
|
|
54
|
+
// Check new path first: .aicp/aicp.json
|
|
55
|
+
const newCandidate = path_1.default.join(dir, LOCAL_DIR, LOCAL_FILENAME);
|
|
56
|
+
if (fs_1.default.existsSync(newCandidate))
|
|
57
|
+
return newCandidate;
|
|
58
|
+
// Fall back to legacy: .aicp.json
|
|
59
|
+
const legacyCandidate = path_1.default.join(dir, LEGACY_LOCAL_FILENAME);
|
|
60
|
+
if (fs_1.default.existsSync(legacyCandidate))
|
|
61
|
+
return legacyCandidate;
|
|
62
|
+
const parent = path_1.default.dirname(dir);
|
|
63
|
+
if (parent === dir)
|
|
64
|
+
return null;
|
|
65
|
+
dir = parent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Returns the .aicp/ directory path for the current project (creates if needed) */
|
|
69
|
+
function localAicpDir() {
|
|
70
|
+
const configPath = findLocalConfigPath();
|
|
71
|
+
if (configPath) {
|
|
72
|
+
// If found at legacy location, use its parent + .aicp/
|
|
73
|
+
if (configPath.endsWith(LEGACY_LOCAL_FILENAME)) {
|
|
74
|
+
return path_1.default.join(path_1.default.dirname(configPath), LOCAL_DIR);
|
|
75
|
+
}
|
|
76
|
+
// New layout: .aicp/aicp.json → .aicp/
|
|
77
|
+
return path_1.default.dirname(configPath);
|
|
78
|
+
}
|
|
79
|
+
// Default to cwd/.aicp/
|
|
80
|
+
return path_1.default.join(process.cwd(), LOCAL_DIR);
|
|
81
|
+
}
|
|
82
|
+
function loadConfig() {
|
|
83
|
+
const global = readGlobalConfig();
|
|
84
|
+
const local = readLocalConfig();
|
|
85
|
+
// Env vars override everything
|
|
86
|
+
const backendUrl = process.env.BACKEND_WS_URL || global.backend_url || '';
|
|
87
|
+
const machineName = process.env.MACHINE_NAME || global.machine_name || os_1.default.hostname();
|
|
88
|
+
const projectId = process.env.PROJECT_ID || local.project_id || '';
|
|
89
|
+
const agentId = process.env.AGENT_ID || (0, uuid_1.v4)();
|
|
90
|
+
const apiKey = process.env.AICP_API_KEY || global.api_key || '';
|
|
91
|
+
if (!backendUrl) {
|
|
92
|
+
console.error('[agent] backend_url not configured. Run: aicp-agent --setup');
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
if (!projectId) {
|
|
96
|
+
console.error('[agent] project_id not configured. Run: aicp-agent --setup');
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
if (!apiKey) {
|
|
100
|
+
console.error('[agent] api_key not configured. Run: aicp-agent --setup');
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
const dangerouslySkipPermissions = process.argv.includes('--dangerously-skip-permissions');
|
|
104
|
+
return { backendUrl, machineName, projectId, agentId, apiKey, dangerouslySkipPermissions };
|
|
105
|
+
}
|
|
106
|
+
// Lazy singleton — only validated when first accessed (not during --setup)
|
|
107
|
+
let _config = null;
|
|
108
|
+
function getConfig() {
|
|
109
|
+
if (!_config)
|
|
110
|
+
_config = loadConfig();
|
|
111
|
+
return _config;
|
|
112
|
+
}
|
|
113
|
+
exports.config = new Proxy({}, {
|
|
114
|
+
get(_, prop) {
|
|
115
|
+
return getConfig()[prop];
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Add a history entry. display is the collapsed version (only stored if different from full). */
|
|
2
|
+
export declare function addHistory(full: string, display?: string): void;
|
|
3
|
+
/** Get history entries count */
|
|
4
|
+
export declare function historyLength(): number;
|
|
5
|
+
/** Get the display text for a history entry (index 0 = oldest). Returns null if out of range. */
|
|
6
|
+
export declare function getHistoryDisplay(index: number): string | null;
|
|
7
|
+
/** Get the full text for a history entry (index 0 = oldest). Returns null if out of range. */
|
|
8
|
+
export declare function getHistoryFull(index: number): string | null;
|
|
9
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAgDA,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAkB/D;AAED,gCAAgC;AAChC,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK9D;AAED,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3D"}
|