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.
Files changed (54) hide show
  1. package/README.md +161 -0
  2. package/dist/claude/sdk.d.ts +34 -0
  3. package/dist/claude/sdk.d.ts.map +1 -0
  4. package/dist/claude/sdk.js +112 -0
  5. package/dist/claude/sdk.js.map +1 -0
  6. package/dist/commands/index.d.ts +10 -0
  7. package/dist/commands/index.d.ts.map +1 -0
  8. package/dist/commands/index.js +32 -0
  9. package/dist/commands/index.js.map +1 -0
  10. package/dist/commands/resume.d.ts +6 -0
  11. package/dist/commands/resume.d.ts.map +1 -0
  12. package/dist/commands/resume.js +75 -0
  13. package/dist/commands/resume.js.map +1 -0
  14. package/dist/config.d.ts +26 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +118 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/history.d.ts +9 -0
  19. package/dist/history.d.ts.map +1 -0
  20. package/dist/history.js +87 -0
  21. package/dist/history.js.map +1 -0
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +53 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/main.d.ts +2 -0
  27. package/dist/main.d.ts.map +1 -0
  28. package/dist/main.js +344 -0
  29. package/dist/main.js.map +1 -0
  30. package/dist/setup.d.ts +2 -0
  31. package/dist/setup.d.ts.map +1 -0
  32. package/dist/setup.js +129 -0
  33. package/dist/setup.js.map +1 -0
  34. package/dist/terminal/prompt.d.ts +29 -0
  35. package/dist/terminal/prompt.d.ts.map +1 -0
  36. package/dist/terminal/prompt.js +764 -0
  37. package/dist/terminal/prompt.js.map +1 -0
  38. package/dist/terminal/spinner.d.ts +7 -0
  39. package/dist/terminal/spinner.d.ts.map +1 -0
  40. package/dist/terminal/spinner.js +114 -0
  41. package/dist/terminal/spinner.js.map +1 -0
  42. package/dist/types/protocol.d.ts +59 -0
  43. package/dist/types/protocol.d.ts.map +1 -0
  44. package/dist/types/protocol.js +4 -0
  45. package/dist/types/protocol.js.map +1 -0
  46. package/dist/update.d.ts +2 -0
  47. package/dist/update.d.ts.map +1 -0
  48. package/dist/update.js +65 -0
  49. package/dist/update.js.map +1 -0
  50. package/dist/websocket/client.d.ts +8 -0
  51. package/dist/websocket/client.d.ts.map +1 -0
  52. package/dist/websocket/client.js +120 -0
  53. package/dist/websocket/client.js.map +1 -0
  54. 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,6 @@
1
+ interface Questionable {
2
+ question(prompt: string, cb: (answer: string) => void): void;
3
+ }
4
+ export declare function resumeCommand(rl: Questionable): Promise<string | null>;
5
+ export {};
6
+ //# sourceMappingURL=resume.d.ts.map
@@ -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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"}
@@ -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"}