@accomplish_ai/agent-core-cli 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 (47) hide show
  1. package/README.md +163 -0
  2. package/dist/commands/interactive.d.ts +4 -0
  3. package/dist/commands/interactive.js +93 -0
  4. package/dist/commands/interactive.js.map +1 -0
  5. package/dist/commands/run.d.ts +5 -0
  6. package/dist/commands/run.js +38 -0
  7. package/dist/commands/run.js.map +1 -0
  8. package/dist/commands/serve.d.ts +5 -0
  9. package/dist/commands/serve.js +43 -0
  10. package/dist/commands/serve.js.map +1 -0
  11. package/dist/core/init.d.ts +13 -0
  12. package/dist/core/init.js +90 -0
  13. package/dist/core/init.js.map +1 -0
  14. package/dist/core/job-runner.d.ts +14 -0
  15. package/dist/core/job-runner.js +60 -0
  16. package/dist/core/job-runner.js.map +1 -0
  17. package/dist/core/message-mapper.d.ts +3 -0
  18. package/dist/core/message-mapper.js +31 -0
  19. package/dist/core/message-mapper.js.map +1 -0
  20. package/dist/core/permission-servers.d.ts +3 -0
  21. package/dist/core/permission-servers.js +73 -0
  22. package/dist/core/permission-servers.js.map +1 -0
  23. package/dist/core/sync.d.ts +1 -0
  24. package/dist/core/sync.js +10 -0
  25. package/dist/core/sync.js.map +1 -0
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +78 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/server/app.d.ts +5 -0
  30. package/dist/server/app.js +10 -0
  31. package/dist/server/app.js.map +1 -0
  32. package/dist/server/event-bus.d.ts +9 -0
  33. package/dist/server/event-bus.js +22 -0
  34. package/dist/server/event-bus.js.map +1 -0
  35. package/dist/server/routes/health.d.ts +2 -0
  36. package/dist/server/routes/health.js +6 -0
  37. package/dist/server/routes/health.js.map +1 -0
  38. package/dist/server/routes/jobs.d.ts +5 -0
  39. package/dist/server/routes/jobs.js +76 -0
  40. package/dist/server/routes/jobs.js.map +1 -0
  41. package/dist/server/routes/websocket.d.ts +7 -0
  42. package/dist/server/routes/websocket.js +47 -0
  43. package/dist/server/routes/websocket.js.map +1 -0
  44. package/dist/types.d.ts +17 -0
  45. package/dist/types.js +2 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # agent-core-cli
2
+
3
+ Headless CLI and HTTP server wrapping [`@accomplish_ai/agent-core`](https://github.com/accomplish-ai/accomplish/tree/main/packages/agent-core). A drop-in replacement for the sandbox mock agent that runs AI tasks autonomously — no Electron, no GUI.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ Client ──POST /jobs──> Hono HTTP Server
9
+ |
10
+ JobRunner
11
+ |
12
+ TaskManager (agent-core)
13
+ |
14
+ OpenCode CLI
15
+ |
16
+ ┌─────────┴─────────┐
17
+ v v
18
+ EventBus StorageAPI
19
+ | |
20
+ ┌───────┼───────┐ SQLite DB
21
+ v v v
22
+ SSE WS stdout
23
+ ```
24
+
25
+ ## Prerequisites
26
+
27
+ - Node.js >= 20
28
+ - `ANTHROPIC_API_KEY` environment variable
29
+ - [`@accomplish_ai/agent-core`](https://github.com/accomplish-ai/accomplish/tree/main/packages/agent-core) built locally
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm install @accomplish_ai/agent-core-cli
35
+ ```
36
+
37
+ ### From source
38
+
39
+ ```bash
40
+ npm install
41
+ npm run build
42
+ ```
43
+
44
+ ## Commands
45
+
46
+ ### `run` — One-shot execution
47
+
48
+ Run a single prompt and stream output to stdout, then exit.
49
+
50
+ ```bash
51
+ agent-core-cli run --prompt "Write a hello world in Python" \
52
+ --model claude-sonnet-4-20250514 \
53
+ --workdir ./my-project \
54
+ --data-dir /app/data
55
+ ```
56
+
57
+ | Option | Default | Description |
58
+ |--------|---------|-------------|
59
+ | `--prompt` (required) | — | Task prompt |
60
+ | `--model` | `claude-sonnet-4-20250514` | Model ID |
61
+ | `--workdir` | Current directory | Working directory for the agent |
62
+ | `--data-dir` | `/app/data` | SQLite database directory |
63
+
64
+ ### `serve` — HTTP server
65
+
66
+ Start the HTTP API server with SSE and WebSocket support.
67
+
68
+ ```bash
69
+ agent-core-cli serve --port 8080 \
70
+ --model claude-sonnet-4-20250514 \
71
+ --workdir /workspace \
72
+ --data-dir /app/data
73
+ ```
74
+
75
+ | Option | Default | Description |
76
+ |--------|---------|-------------|
77
+ | `--port` | `8080` | HTTP port |
78
+ | `--model` | `claude-sonnet-4-20250514` | Model ID |
79
+ | `--workdir` | `/workspace` | Working directory for the agent |
80
+ | `--data-dir` | `/app/data` | SQLite database directory |
81
+
82
+ ### `interactive` — REPL mode
83
+
84
+ Start a multi-turn conversation with session continuity.
85
+
86
+ ```bash
87
+ agent-core-cli interactive \
88
+ --model claude-sonnet-4-20250514 \
89
+ --workdir ./my-project
90
+ ```
91
+
92
+ | Option | Default | Description |
93
+ |--------|---------|-------------|
94
+ | `--model` | `claude-sonnet-4-20250514` | Model ID |
95
+ | `--workdir` | Current directory | Working directory for the agent |
96
+ | `--data-dir` | `/app/data` | SQLite database directory |
97
+
98
+ ## HTTP API
99
+
100
+ ### `GET /health`
101
+
102
+ ```json
103
+ { "status": "ok" }
104
+ ```
105
+
106
+ ### `POST /jobs`
107
+
108
+ Create and start a new agent job. Returns immediately; the job runs in the background.
109
+
110
+ **Request:**
111
+ ```json
112
+ { "id": "optional-custom-id", "prompt": "Build a REST API" }
113
+ ```
114
+
115
+ **Response (201):**
116
+ ```json
117
+ { "id": "job_1707400000_abc1234", "status": "pending" }
118
+ ```
119
+
120
+ ### `GET /jobs/:id`
121
+
122
+ Poll job status.
123
+
124
+ ```json
125
+ {
126
+ "id": "job_123",
127
+ "prompt": "Build a REST API",
128
+ "status": "running",
129
+ "result": null,
130
+ "created_at": "2026-02-08T12:00:00.000Z",
131
+ "started_at": "2026-02-08T12:00:01.000Z",
132
+ "completed_at": null
133
+ }
134
+ ```
135
+
136
+ Status values: `pending`, `running`, `completed`, `failed`.
137
+
138
+ ### `GET /jobs/:id/stream`
139
+
140
+ Server-Sent Events stream. Replays historical messages on connect, then streams live updates.
141
+
142
+ ```
143
+ data: {"type":"assistant","content":"I'll create the API..."}
144
+ data: {"type":"tool_use","content":"{\"tool\":\"bash\",\"input\":{...}}"}
145
+ data: {"type":"tool_result","content":"server.py created"}
146
+ data: {"type":"done","content":"Task completed"}
147
+ ```
148
+
149
+ ### `WS /jobs/:id/ws`
150
+
151
+ WebSocket endpoint. Same message format as SSE. Replays history on connect, streams live updates, closes automatically when the job completes.
152
+
153
+ ## Development
154
+
155
+ ```bash
156
+ npm run dev # Watch mode
157
+ npm run build # Compile TypeScript
158
+ npm test # Run tests
159
+ ```
160
+
161
+ ## License
162
+
163
+ MIT
@@ -0,0 +1,4 @@
1
+ import { type InitOptions } from '../core/init.js';
2
+ export interface InteractiveOptions extends InitOptions {
3
+ }
4
+ export declare function interactive(options: InteractiveOptions): Promise<void>;
@@ -0,0 +1,93 @@
1
+ import readline from 'node:readline';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { initialize } from '../core/init.js';
4
+ import { mapMessage } from '../core/message-mapper.js';
5
+ export async function interactive(options) {
6
+ const { model, workdir, dataDir } = options;
7
+ // Initialize core services
8
+ const { taskManager, cleanup } = await initialize({ model, workdir, dataDir });
9
+ // Generate persistent session ID for multi-turn continuity
10
+ const sessionId = randomUUID();
11
+ // Create readline interface
12
+ const rl = readline.createInterface({
13
+ input: process.stdin,
14
+ output: process.stdout,
15
+ });
16
+ console.log('Interactive mode. Type your prompts. Ctrl+C to exit.\n');
17
+ // Handle Ctrl+C gracefully
18
+ rl.on('close', async () => {
19
+ console.log('\nExiting...');
20
+ await cleanup();
21
+ process.exit(0);
22
+ });
23
+ // Main REPL loop
24
+ const promptUser = () => {
25
+ rl.question('> ', async (input) => {
26
+ const trimmedInput = input.trim();
27
+ // Skip empty lines
28
+ if (!trimmedInput) {
29
+ promptUser();
30
+ return;
31
+ }
32
+ const taskId = randomUUID();
33
+ await new Promise((resolve) => {
34
+ taskManager.startTask(taskId, {
35
+ prompt: trimmedInput,
36
+ sessionId,
37
+ workingDirectory: workdir,
38
+ }, {
39
+ onMessage: (message) => {
40
+ const mapped = mapMessage(message);
41
+ if (mapped) {
42
+ if (mapped.type === 'assistant') {
43
+ process.stdout.write(mapped.content);
44
+ }
45
+ else if (mapped.type === 'tool_use') {
46
+ try {
47
+ const toolData = JSON.parse(mapped.content);
48
+ console.log(`\x1b[2m[TOOL] ${toolData.tool}\x1b[0m`);
49
+ }
50
+ catch {
51
+ console.log(`\x1b[2m[TOOL USE]\x1b[0m`);
52
+ }
53
+ }
54
+ else if (mapped.type === 'tool_result') {
55
+ console.log(`\x1b[2m[RESULT]\x1b[0m`);
56
+ }
57
+ else if (mapped.type === 'error') {
58
+ console.error(`Error: ${mapped.content}`);
59
+ }
60
+ }
61
+ },
62
+ onProgress: (progress) => {
63
+ if (progress.message) {
64
+ console.log(`\x1b[2m${progress.message}\x1b[0m`);
65
+ }
66
+ },
67
+ onPermissionRequest: (request) => {
68
+ console.log(`\x1b[2m[Permission requested: ${request.type}]\x1b[0m`);
69
+ },
70
+ onComplete: (result) => {
71
+ if (result.status === 'error' && result.error) {
72
+ console.error(`\nTask error: ${result.error}`);
73
+ }
74
+ console.log();
75
+ resolve();
76
+ },
77
+ onError: (error) => {
78
+ console.error(`\nError: ${error.message}`);
79
+ resolve();
80
+ },
81
+ }).catch((err) => {
82
+ console.error(`\nFailed to start task: ${err.message}`);
83
+ resolve();
84
+ });
85
+ });
86
+ // Continue REPL loop
87
+ promptUser();
88
+ });
89
+ };
90
+ // Start the REPL
91
+ promptUser();
92
+ }
93
+ //# sourceMappingURL=interactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/commands/interactive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type InitOptions } from '../core/init.js';
2
+ export interface RunOptions extends InitOptions {
3
+ prompt: string;
4
+ }
5
+ export declare function run(options: RunOptions): Promise<void>;
@@ -0,0 +1,38 @@
1
+ import { initialize } from '../core/init.js';
2
+ import { mapMessage } from '../core/message-mapper.js';
3
+ export async function run(options) {
4
+ const { prompt, model, workdir, dataDir = '/app/data' } = options;
5
+ const { taskManager, cleanup } = await initialize({ model, workdir, dataDir });
6
+ const taskId = `run_${Date.now()}`;
7
+ return new Promise((resolve, reject) => {
8
+ taskManager.startTask(taskId, { prompt, workingDirectory: workdir }, {
9
+ onMessage: (message) => {
10
+ const mapped = mapMessage(message);
11
+ if (mapped) {
12
+ process.stdout.write(`data: ${JSON.stringify(mapped)}\n`);
13
+ }
14
+ },
15
+ onProgress: () => { },
16
+ onPermissionRequest: () => { },
17
+ onComplete: async (result) => {
18
+ if (result.status === 'success') {
19
+ process.stdout.write(`data: ${JSON.stringify({ type: 'done', content: 'Task completed' })}\n`);
20
+ }
21
+ else {
22
+ process.stdout.write(`data: ${JSON.stringify({ type: 'error', content: result.error || 'Task failed' })}\n`);
23
+ }
24
+ await cleanup();
25
+ resolve();
26
+ },
27
+ onError: async (error) => {
28
+ process.stderr.write(`Error: ${error.message}\n`);
29
+ await cleanup();
30
+ reject(error);
31
+ },
32
+ }).catch(async (err) => {
33
+ await cleanup();
34
+ reject(err);
35
+ });
36
+ });
37
+ }
38
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAOvD,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAAmB;IAC3C,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAElE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAEnC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,WAAW,CAAC,SAAS,CACnB,MAAM,EACN,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,EACrC;YACE,SAAS,EAAE,CAAC,OAAwB,EAAE,EAAE;gBACtC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;gBACnC,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;YACD,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;YACpB,mBAAmB,EAAE,GAAG,EAAE,GAAE,CAAC;YAC7B,UAAU,EAAE,KAAK,EAAE,MAAkB,EAAE,EAAE;gBACvC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,IAAI,CAAC,CAAC;gBACjG,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC/G,CAAC;gBACD,MAAM,OAAO,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,KAAY,EAAE,EAAE;gBAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;gBAClD,MAAM,OAAO,EAAE,CAAC;gBAChB,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;SACF,CACF,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACpB,MAAM,OAAO,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type InitOptions } from '../core/init.js';
2
+ export interface ServeOptions extends InitOptions {
3
+ port?: number;
4
+ }
5
+ export declare function serve(options: ServeOptions): Promise<void>;
@@ -0,0 +1,43 @@
1
+ import { serve as honoServe } from '@hono/node-server';
2
+ import { createNodeWebSocket } from '@hono/node-ws';
3
+ import { initialize } from '../core/init.js';
4
+ import { EventBus } from '../server/event-bus.js';
5
+ import { JobRunner } from '../core/job-runner.js';
6
+ import { createApp } from '../server/app.js';
7
+ import { registerWebSocketRoute } from '../server/routes/websocket.js';
8
+ export async function serve(options) {
9
+ const { port = 8080, model, workdir = '/workspace', dataDir = '/app/data', } = options;
10
+ const backupDir = '/data/backup';
11
+ const { storage, taskManager, cleanup } = await initialize({ model, workdir, dataDir });
12
+ const eventBus = new EventBus();
13
+ const jobRunner = new JobRunner({
14
+ storage,
15
+ taskManager,
16
+ eventBus,
17
+ dataDir,
18
+ backupDir,
19
+ });
20
+ const app = createApp(storage, eventBus, jobRunner, workdir);
21
+ // Set up WebSocket support
22
+ const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: app });
23
+ registerWebSocketRoute(app, upgradeWebSocket, storage, eventBus);
24
+ const server = honoServe({
25
+ fetch: app.fetch,
26
+ port,
27
+ }, (info) => {
28
+ console.log(`agent-core-cli server listening on http://0.0.0.0:${info.port}`);
29
+ });
30
+ injectWebSocket(server);
31
+ // Graceful shutdown
32
+ const shutdown = async () => {
33
+ console.log('\nShutting down...');
34
+ await new Promise((resolve) => {
35
+ server.close(() => resolve());
36
+ });
37
+ await cleanup();
38
+ process.exit(0);
39
+ };
40
+ process.on('SIGTERM', shutdown);
41
+ process.on('SIGINT', shutdown);
42
+ }
43
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAMvE,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,OAAqB;IAC/C,MAAM,EACJ,IAAI,GAAG,IAAI,EACX,KAAK,EACL,OAAO,GAAG,YAAY,EACtB,OAAO,GAAG,WAAW,GACtB,GAAG,OAAO,CAAC;IAEZ,MAAM,SAAS,GAAG,cAAc,CAAC;IAEjC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAExF,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;QAC9B,OAAO;QACP,WAAW;QACX,QAAQ;QACR,OAAO;QACP,SAAS;KACV,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAE7D,2BAA2B;IAC3B,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,mBAAmB,CAAC,EAAE,GAAG,EAAE,GAAU,EAAE,CAAC,CAAC;IACvF,sBAAsB,CAAC,GAAG,EAAE,gBAAuB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAExE,MAAM,MAAM,GAAG,SAAS,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI;KACL,EAAE,CAAC,IAAI,EAAE,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,qDAAqD,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,eAAe,CAAC,MAAM,CAAC,CAAC;IAExB,oBAAoB;IACpB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type StorageAPI, type TaskManagerAPI } from '@accomplish_ai/agent-core';
2
+ export interface InitOptions {
3
+ model?: string;
4
+ workdir?: string;
5
+ dataDir?: string;
6
+ }
7
+ export interface InitResult {
8
+ storage: StorageAPI;
9
+ taskManager: TaskManagerAPI;
10
+ configPath: string;
11
+ cleanup: () => Promise<void>;
12
+ }
13
+ export declare function initialize(options?: InitOptions): Promise<InitResult>;
@@ -0,0 +1,90 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import { createStorage, createTaskManager, generateConfig, buildCliArgs as coreBuildCliArgs, buildOpenCodeEnvironment, PERMISSION_API_PORT, QUESTION_API_PORT, } from '@accomplish_ai/agent-core';
4
+ import { startPermissionServers, stopPermissionServers } from './permission-servers.js';
5
+ export async function initialize(options = {}) {
6
+ const { model = 'claude-sonnet-4-20250514', workdir = process.cwd(), dataDir = '/app/data', } = options;
7
+ // 1. Validate ANTHROPIC_API_KEY
8
+ if (!process.env.ANTHROPIC_API_KEY) {
9
+ throw new Error('ANTHROPIC_API_KEY environment variable is required');
10
+ }
11
+ // 2. Initialize storage
12
+ const storage = createStorage({
13
+ databasePath: path.join(dataDir, 'agent-core.db'),
14
+ runMigrations: true,
15
+ userDataPath: dataDir,
16
+ });
17
+ storage.initialize();
18
+ // 3. Start permission servers
19
+ await startPermissionServers();
20
+ // 4. Resolve MCP tools path
21
+ const mcpToolsPath = resolveMcpToolsPath();
22
+ // 5. Generate OpenCode config
23
+ const configResult = generateConfig({
24
+ platform: process.platform,
25
+ mcpToolsPath,
26
+ userDataPath: dataDir,
27
+ isPackaged: true,
28
+ permissionApiPort: PERMISSION_API_PORT,
29
+ questionApiPort: QUESTION_API_PORT,
30
+ enabledProviders: ['anthropic'],
31
+ model,
32
+ });
33
+ process.env.OPENCODE_CONFIG = configResult.configPath;
34
+ process.env.OPENCODE_CONFIG_DIR = path.dirname(configResult.configPath);
35
+ // 6. Create TaskManager
36
+ const adapterOptions = {
37
+ platform: process.platform,
38
+ isPackaged: true,
39
+ tempPath: '/tmp',
40
+ getCliCommand: () => ({ command: 'opencode', args: [] }),
41
+ buildEnvironment: async (taskId) => {
42
+ return buildOpenCodeEnvironment({ ...process.env }, {
43
+ apiKeys: {
44
+ anthropic: process.env.ANTHROPIC_API_KEY || '',
45
+ },
46
+ taskId,
47
+ });
48
+ },
49
+ buildCliArgs: async (config, _taskId) => {
50
+ return coreBuildCliArgs({
51
+ prompt: config.prompt,
52
+ sessionId: config.sessionId,
53
+ selectedModel: { provider: 'anthropic', model },
54
+ });
55
+ },
56
+ };
57
+ const taskManagerOptions = {
58
+ adapterOptions,
59
+ defaultWorkingDirectory: workdir,
60
+ maxConcurrentTasks: 1,
61
+ isCliAvailable: async () => true,
62
+ };
63
+ const taskManager = createTaskManager(taskManagerOptions);
64
+ const cleanup = async () => {
65
+ taskManager.dispose();
66
+ storage.close();
67
+ await stopPermissionServers();
68
+ };
69
+ return { storage, taskManager, configPath: configResult.configPath, cleanup };
70
+ }
71
+ function resolveMcpToolsPath() {
72
+ // Try common locations synchronously
73
+ const candidates = [
74
+ path.join(process.cwd(), 'node_modules', '@accomplish_ai', 'agent-core', 'mcp-tools'),
75
+ path.resolve(import.meta.dirname, '..', '..', 'node_modules', '@accomplish_ai', 'agent-core', 'mcp-tools'),
76
+ ];
77
+ for (const candidate of candidates) {
78
+ if (fs.existsSync(candidate))
79
+ return candidate;
80
+ }
81
+ // Fallback: use import.meta.resolve
82
+ try {
83
+ const agentCorePath = path.dirname(new URL(import.meta.resolve('@accomplish_ai/agent-core')).pathname);
84
+ return path.join(agentCorePath, 'mcp-tools');
85
+ }
86
+ catch {
87
+ return path.join(process.cwd(), 'mcp-tools');
88
+ }
89
+ }
90
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { StorageAPI, TaskManagerAPI } from '@accomplish_ai/agent-core';
2
+ import { EventBus } from '../server/event-bus.js';
3
+ export interface JobRunnerOptions {
4
+ storage: StorageAPI;
5
+ taskManager: TaskManagerAPI;
6
+ eventBus: EventBus;
7
+ dataDir: string;
8
+ backupDir: string;
9
+ }
10
+ export declare class JobRunner {
11
+ private opts;
12
+ constructor(opts: JobRunnerOptions);
13
+ startJob(jobId: string, prompt: string, workdir?: string): Promise<void>;
14
+ }
@@ -0,0 +1,60 @@
1
+ import { mapMessage } from './message-mapper.js';
2
+ import { syncDatabase } from './sync.js';
3
+ export class JobRunner {
4
+ opts;
5
+ constructor(opts) {
6
+ this.opts = opts;
7
+ }
8
+ async startJob(jobId, prompt, workdir) {
9
+ const { storage, taskManager, eventBus, dataDir, backupDir } = this.opts;
10
+ // Save initial task
11
+ const initialTask = {
12
+ id: jobId,
13
+ prompt,
14
+ status: 'pending',
15
+ messages: [],
16
+ createdAt: new Date().toISOString(),
17
+ };
18
+ storage.saveTask(initialTask);
19
+ // Update to running
20
+ storage.updateTaskStatus(jobId, 'running', undefined);
21
+ // Start via TaskManager
22
+ await taskManager.startTask(jobId, { prompt, workingDirectory: workdir }, {
23
+ onMessage: (message) => {
24
+ const mapped = mapMessage(message);
25
+ if (mapped) {
26
+ storage.addTaskMessage(jobId, {
27
+ id: `msg_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
28
+ type: mapped.type === 'assistant' ? 'assistant' : 'tool',
29
+ content: mapped.content,
30
+ timestamp: new Date().toISOString(),
31
+ });
32
+ eventBus.emit(jobId, mapped);
33
+ syncDatabase(dataDir, backupDir);
34
+ }
35
+ },
36
+ onProgress: (progress) => {
37
+ console.log(`[Job ${jobId}] Progress: ${progress.stage} - ${progress.message || ''}`);
38
+ },
39
+ onPermissionRequest: (_request) => {
40
+ console.log(`[Job ${jobId}] Permission request (auto-handled by servers)`);
41
+ },
42
+ onComplete: (result) => {
43
+ const summary = result.status === 'success' ? 'Task completed' : `Task ${result.status}`;
44
+ storage.updateTaskSummary(jobId, summary);
45
+ storage.updateTaskStatus(jobId, result.status === 'success' ? 'completed' : 'failed', new Date().toISOString());
46
+ eventBus.emitComplete(jobId, summary);
47
+ syncDatabase(dataDir, backupDir);
48
+ console.log(`[Job ${jobId}] Complete: ${result.status}`);
49
+ },
50
+ onError: (error) => {
51
+ console.error(`[Job ${jobId}] Error:`, error.message);
52
+ storage.updateTaskStatus(jobId, 'failed', new Date().toISOString());
53
+ eventBus.emit(jobId, { type: 'error', content: error.message });
54
+ eventBus.emitComplete(jobId, `Error: ${error.message}`);
55
+ syncDatabase(dataDir, backupDir);
56
+ },
57
+ });
58
+ }
59
+ }
60
+ //# sourceMappingURL=job-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-runner.js","sourceRoot":"","sources":["../../src/core/job-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { OpenCodeMessage } from '@accomplish_ai/agent-core';
2
+ import type { SandboxMessage } from '../types.js';
3
+ export declare function mapMessage(message: OpenCodeMessage): SandboxMessage | null;
@@ -0,0 +1,31 @@
1
+ export function mapMessage(message) {
2
+ switch (message.type) {
3
+ case 'text':
4
+ return { type: 'assistant', content: message.part.text };
5
+ case 'tool_call':
6
+ return {
7
+ type: 'tool_use',
8
+ content: JSON.stringify({ tool: message.part.tool, input: message.part.input }),
9
+ };
10
+ case 'tool_use': {
11
+ const state = message.part.state;
12
+ if (state.status === 'completed' || state.status === 'error') {
13
+ return { type: 'tool_result', content: state.output || '' };
14
+ }
15
+ return {
16
+ type: 'tool_use',
17
+ content: JSON.stringify({ tool: message.part.tool, input: state.input }),
18
+ };
19
+ }
20
+ case 'tool_result':
21
+ return { type: 'tool_result', content: message.part.output || '' };
22
+ case 'error':
23
+ return { type: 'error', content: message.error };
24
+ case 'step_start':
25
+ case 'step_finish':
26
+ return null;
27
+ default:
28
+ return null;
29
+ }
30
+ }
31
+ //# sourceMappingURL=message-mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-mapper.js","sourceRoot":"","sources":["../../src/core/message-mapper.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,UAAU,CAAC,OAAwB;IACjD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAE3D,KAAK,WAAW;YACd,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;aAChF,CAAC;QAEJ,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YACjC,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC7D,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YAC9D,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;aACzE,CAAC;QACJ,CAAC;QAED,KAAK,aAAa;YAChB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAErE,KAAK,OAAO;YACV,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;QAEnD,KAAK,YAAY,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,IAAI,CAAC;QAEd;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import http from 'node:http';
2
+ export declare function startPermissionServers(): Promise<http.Server[]>;
3
+ export declare function stopPermissionServers(): Promise<void>;
@@ -0,0 +1,73 @@
1
+ import http from 'node:http';
2
+ import { PERMISSION_API_PORT, QUESTION_API_PORT, THOUGHT_STREAM_PORT, } from '@accomplish_ai/agent-core';
3
+ let servers = [];
4
+ function parseBody(req) {
5
+ return new Promise((resolve, reject) => {
6
+ let body = '';
7
+ req.on('data', (chunk) => { body += chunk; });
8
+ req.on('end', () => {
9
+ try {
10
+ resolve(JSON.parse(body));
11
+ }
12
+ catch {
13
+ reject(new Error('Invalid JSON'));
14
+ }
15
+ });
16
+ });
17
+ }
18
+ function createJsonServer(port, handler) {
19
+ return new Promise((resolve, reject) => {
20
+ const server = http.createServer(async (req, res) => {
21
+ res.setHeader('Access-Control-Allow-Origin', '*');
22
+ res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
23
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
24
+ if (req.method === 'OPTIONS') {
25
+ res.writeHead(200);
26
+ res.end();
27
+ return;
28
+ }
29
+ if (req.method !== 'POST') {
30
+ res.writeHead(404, { 'Content-Type': 'application/json' });
31
+ res.end(JSON.stringify({ error: 'Not found' }));
32
+ return;
33
+ }
34
+ try {
35
+ const body = await parseBody(req);
36
+ const result = handler(req.url || '/', body);
37
+ res.writeHead(200, { 'Content-Type': 'application/json' });
38
+ res.end(JSON.stringify(result));
39
+ }
40
+ catch {
41
+ res.writeHead(400, { 'Content-Type': 'application/json' });
42
+ res.end(JSON.stringify({ error: 'Bad request' }));
43
+ }
44
+ });
45
+ server.listen(port, '127.0.0.1', () => {
46
+ console.log(`[Permission] Listening on port ${port}`);
47
+ resolve(server);
48
+ });
49
+ server.on('error', reject);
50
+ });
51
+ }
52
+ export async function startPermissionServers() {
53
+ const permissionServer = await createJsonServer(PERMISSION_API_PORT, () => ({
54
+ allowed: true,
55
+ }));
56
+ const questionServer = await createJsonServer(QUESTION_API_PORT, (_url, body) => {
57
+ const options = body.options;
58
+ const firstLabel = options?.[0]?.label ?? '';
59
+ return {
60
+ selectedOptions: firstLabel ? [firstLabel] : [],
61
+ customText: '',
62
+ denied: false,
63
+ };
64
+ });
65
+ const thoughtServer = await createJsonServer(THOUGHT_STREAM_PORT, () => ({}));
66
+ servers = [permissionServer, questionServer, thoughtServer];
67
+ return servers;
68
+ }
69
+ export async function stopPermissionServers() {
70
+ await Promise.all(servers.map((s) => new Promise((resolve) => s.close(() => resolve()))));
71
+ servers = [];
72
+ }
73
+ //# sourceMappingURL=permission-servers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-servers.js","sourceRoot":"","sources":["../../src/core/permission-servers.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AAEnC,IAAI,OAAO,GAAkB,EAAE,CAAC;AAEhC,SAAS,SAAS,CAAC,GAAyB;IAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;YAAC,CAAC;YAClC,MAAM,CAAC;gBAAC,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;YAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CACvB,IAAY,EACZ,OAAgF;IAEhF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YAClD,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;YAClD,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,eAAe,CAAC,CAAC;YAC/D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;YAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;gBAChD,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC7C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;YACpC,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1E,OAAO,EAAE,IAAI;KACd,CAAC,CAAC,CAAC;IAEJ,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QAC9E,MAAM,OAAO,GAAG,IAAI,CAAC,OAA+C,CAAC;QACrE,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;QAC7C,OAAO;YACL,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;YAC/C,UAAU,EAAE,EAAE;YACd,MAAM,EAAE,KAAK;SACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE9E,OAAO,GAAG,CAAC,gBAAgB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CACT,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAChE,CACF,CAAC;IACF,OAAO,GAAG,EAAE,CAAC;AACf,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function syncDatabase(dataDir: string, backupDir: string): void;
@@ -0,0 +1,10 @@
1
+ import { execSync } from 'node:child_process';
2
+ export function syncDatabase(dataDir, backupDir) {
3
+ try {
4
+ execSync(`rsync -a "${dataDir}/agent-core.db" "${dataDir}/agent-core.db-wal" "${dataDir}/agent-core.db-shm" "${backupDir}/" 2>/dev/null; date -Iseconds > "${backupDir}/.last-sync"`, { timeout: 10000, stdio: 'pipe' });
5
+ }
6
+ catch (err) {
7
+ console.error('[Sync] rsync failed:', err.message);
8
+ }
9
+ }
10
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,SAAiB;IAC7D,IAAI,CAAC;QACH,QAAQ,CACN,aAAa,OAAO,oBAAoB,OAAO,wBAAwB,OAAO,wBAAwB,SAAS,qCAAqC,SAAS,cAAc,EAC3K,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAClC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;IAChE,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { run } from './commands/run.js';
4
+ import { serve } from './commands/serve.js';
5
+ import { interactive } from './commands/interactive.js';
6
+ const program = new Command();
7
+ program
8
+ .name('agent-core-cli')
9
+ .description('Headless CLI wrapping @accomplish_ai/agent-core')
10
+ .version('0.1.0');
11
+ program
12
+ .command('run')
13
+ .description('Run a single prompt and stream output to stdout')
14
+ .requiredOption('--prompt <text>', 'Task prompt')
15
+ .option('--model <id>', 'Model ID', 'claude-sonnet-4-20250514')
16
+ .option('--workdir <path>', 'Working directory', process.cwd())
17
+ .option('--data-dir <path>', 'SQLite data directory', '/app/data')
18
+ .action(async (opts) => {
19
+ try {
20
+ await run({
21
+ prompt: opts.prompt,
22
+ model: opts.model,
23
+ workdir: opts.workdir,
24
+ dataDir: opts.dataDir,
25
+ });
26
+ }
27
+ catch (err) {
28
+ console.error('Fatal:', err.message);
29
+ process.exit(1);
30
+ }
31
+ });
32
+ program
33
+ .command('serve')
34
+ .description('Start the HTTP server')
35
+ .option('--port <number>', 'HTTP port', '8080')
36
+ .option('--model <id>', 'Model ID', 'claude-sonnet-4-20250514')
37
+ .option('--workdir <path>', 'Working directory', '/workspace')
38
+ .option('--data-dir <path>', 'SQLite data directory', '/app/data')
39
+ .action(async (opts) => {
40
+ try {
41
+ const port = parseInt(opts.port, 10);
42
+ if (isNaN(port) || port < 1 || port > 65535) {
43
+ console.error('Error: --port must be a number between 1 and 65535');
44
+ process.exit(1);
45
+ }
46
+ await serve({
47
+ port,
48
+ model: opts.model,
49
+ workdir: opts.workdir,
50
+ dataDir: opts.dataDir,
51
+ });
52
+ }
53
+ catch (err) {
54
+ console.error('Fatal:', err.message);
55
+ process.exit(1);
56
+ }
57
+ });
58
+ program
59
+ .command('interactive')
60
+ .description('Start an interactive REPL session')
61
+ .option('--model <id>', 'Model ID', 'claude-sonnet-4-20250514')
62
+ .option('--workdir <path>', 'Working directory', process.cwd())
63
+ .option('--data-dir <path>', 'SQLite data directory', '/app/data')
64
+ .action(async (opts) => {
65
+ try {
66
+ await interactive({
67
+ model: opts.model,
68
+ workdir: opts.workdir,
69
+ dataDir: opts.dataDir,
70
+ });
71
+ }
72
+ catch (err) {
73
+ console.error('Fatal:', err.message);
74
+ process.exit(1);
75
+ }
76
+ });
77
+ program.parse();
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Hono } from 'hono';
2
+ import type { StorageAPI } from '@accomplish_ai/agent-core';
3
+ import type { EventBus } from './event-bus.js';
4
+ import type { JobRunner } from '../core/job-runner.js';
5
+ export declare function createApp(storage: StorageAPI, eventBus: EventBus, jobRunner: JobRunner, workdir: string): Hono;
@@ -0,0 +1,10 @@
1
+ import { Hono } from 'hono';
2
+ import { healthRoutes } from './routes/health.js';
3
+ import { createJobRoutes } from './routes/jobs.js';
4
+ export function createApp(storage, eventBus, jobRunner, workdir) {
5
+ const app = new Hono();
6
+ app.route('/', healthRoutes);
7
+ app.route('/', createJobRoutes(storage, eventBus, jobRunner, workdir));
8
+ return app;
9
+ }
10
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/server/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAKnD,MAAM,UAAU,SAAS,CACvB,OAAmB,EACnB,QAAkB,EAClB,SAAoB,EACpB,OAAe;IAEf,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC7B,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { SandboxMessage } from '../types.js';
2
+ type Callback = (message: SandboxMessage) => void;
3
+ export declare class EventBus {
4
+ private subscribers;
5
+ subscribe(jobId: string, callback: Callback): () => void;
6
+ emit(jobId: string, message: SandboxMessage): void;
7
+ emitComplete(jobId: string, result: string): void;
8
+ }
9
+ export {};
@@ -0,0 +1,22 @@
1
+ export class EventBus {
2
+ subscribers = new Map();
3
+ subscribe(jobId, callback) {
4
+ if (!this.subscribers.has(jobId)) {
5
+ this.subscribers.set(jobId, new Set());
6
+ }
7
+ this.subscribers.get(jobId).add(callback);
8
+ return () => {
9
+ this.subscribers.get(jobId)?.delete(callback);
10
+ if (this.subscribers.get(jobId)?.size === 0) {
11
+ this.subscribers.delete(jobId);
12
+ }
13
+ };
14
+ }
15
+ emit(jobId, message) {
16
+ this.subscribers.get(jobId)?.forEach((cb) => cb(message));
17
+ }
18
+ emitComplete(jobId, result) {
19
+ this.emit(jobId, { type: 'done', content: result });
20
+ }
21
+ }
22
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/server/event-bus.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,QAAQ;IACX,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEvD,SAAS,CAAC,KAAa,EAAE,QAAkB;QACzC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE3C,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,OAAuB;QACzC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,YAAY,CAAC,KAAa,EAAE,MAAc;QACxC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ import { Hono } from 'hono';
2
+ export declare const healthRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
@@ -0,0 +1,6 @@
1
+ import { Hono } from 'hono';
2
+ export const healthRoutes = new Hono();
3
+ healthRoutes.get('/health', (c) => {
4
+ return c.json({ status: 'ok' });
5
+ });
6
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/server/routes/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;AAEvC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;IAChC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Hono } from 'hono';
2
+ import type { StorageAPI } from '@accomplish_ai/agent-core';
3
+ import type { EventBus } from '../event-bus.js';
4
+ import type { JobRunner } from '../../core/job-runner.js';
5
+ export declare function createJobRoutes(storage: StorageAPI, eventBus: EventBus, jobRunner: JobRunner, workdir: string): Hono;
@@ -0,0 +1,76 @@
1
+ import { Hono } from 'hono';
2
+ import { streamSSE } from 'hono/streaming';
3
+ export function createJobRoutes(storage, eventBus, jobRunner, workdir) {
4
+ const app = new Hono();
5
+ // POST /jobs — create and start a new job
6
+ app.post('/jobs', async (c) => {
7
+ const body = await c.req.json();
8
+ if (!body.prompt) {
9
+ return c.json({ error: 'prompt is required' }, 400);
10
+ }
11
+ const id = body.id || `job_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
12
+ jobRunner.startJob(id, body.prompt, workdir).catch((err) => {
13
+ console.error(`[Jobs] Failed to start job ${id}:`, err);
14
+ });
15
+ return c.json({ id, status: 'pending' }, 201);
16
+ });
17
+ // GET /jobs/:id — get job status
18
+ app.get('/jobs/:id', (c) => {
19
+ const id = c.req.param('id');
20
+ const task = storage.getTask(id);
21
+ if (!task) {
22
+ return c.json({ error: 'Job not found' }, 404);
23
+ }
24
+ const job = {
25
+ id: task.id,
26
+ prompt: task.prompt,
27
+ status: task.status === 'running' ? 'running' :
28
+ task.status === 'completed' ? 'completed' :
29
+ task.status === 'failed' ? 'failed' : 'pending',
30
+ result: task.summary,
31
+ created_at: task.createdAt,
32
+ started_at: task.startedAt,
33
+ completed_at: task.completedAt,
34
+ };
35
+ return c.json(job);
36
+ });
37
+ // GET /jobs/:id/stream — SSE stream
38
+ app.get('/jobs/:id/stream', (c) => {
39
+ const id = c.req.param('id');
40
+ const task = storage.getTask(id);
41
+ if (!task) {
42
+ return c.json({ error: 'Job not found' }, 404);
43
+ }
44
+ return streamSSE(c, async (stream) => {
45
+ // Send historical messages
46
+ for (const msg of task.messages) {
47
+ await stream.writeSSE({
48
+ data: JSON.stringify({
49
+ type: msg.type === 'assistant' ? 'assistant' : 'tool_result',
50
+ content: msg.content,
51
+ }),
52
+ });
53
+ }
54
+ // Subscribe to live events BEFORE checking status to avoid race condition
55
+ const unsub = eventBus.subscribe(id, async (message) => {
56
+ await stream.writeSSE({ data: JSON.stringify(message) });
57
+ if (message.type === 'done') {
58
+ unsub();
59
+ stream.close();
60
+ }
61
+ });
62
+ stream.onAbort(() => unsub());
63
+ // Re-check task status after subscribing (task may have completed)
64
+ const latestTask = storage.getTask(id);
65
+ if (latestTask && (latestTask.status === 'completed' || latestTask.status === 'failed')) {
66
+ await stream.writeSSE({
67
+ data: JSON.stringify({ type: 'done', content: latestTask.summary || '' }),
68
+ });
69
+ unsub();
70
+ return;
71
+ }
72
+ });
73
+ });
74
+ return app;
75
+ }
76
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../../src/server/routes/jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Hono } from 'hono';
2
+ import type { WSContext } from 'hono/ws';
3
+ import type { StorageAPI } from '@accomplish_ai/agent-core';
4
+ import type { EventBus } from '../event-bus.js';
5
+ export declare function registerWebSocketRoute(app: Hono, upgradeWebSocket: (handler: (c: unknown) => {
6
+ onOpen: (evt: unknown, ws: WSContext) => void;
7
+ }) => unknown, storage: StorageAPI, eventBus: EventBus): void;
@@ -0,0 +1,47 @@
1
+ export function registerWebSocketRoute(app, upgradeWebSocket, storage, eventBus) {
2
+ app.get('/jobs/:id/ws', upgradeWebSocket((c) => {
3
+ let unsub;
4
+ return {
5
+ onOpen(_evt, ws) {
6
+ const id = c.req.param('id');
7
+ const task = storage.getTask(id);
8
+ if (!task) {
9
+ ws.close(4004, 'Job not found');
10
+ return;
11
+ }
12
+ // Replay stored messages
13
+ for (const msg of task.messages) {
14
+ ws.send(JSON.stringify({
15
+ type: msg.type === 'assistant' ? 'assistant' : 'tool_result',
16
+ content: msg.content,
17
+ }));
18
+ }
19
+ // Subscribe BEFORE checking status to avoid race condition
20
+ unsub = eventBus.subscribe(id, (message) => {
21
+ try {
22
+ ws.send(JSON.stringify(message));
23
+ if (message.type === 'done') {
24
+ unsub?.();
25
+ ws.close();
26
+ }
27
+ }
28
+ catch {
29
+ unsub?.();
30
+ }
31
+ });
32
+ // Re-check status after subscribing
33
+ const latestTask = storage.getTask(id);
34
+ if (latestTask && (latestTask.status === 'completed' || latestTask.status === 'failed')) {
35
+ ws.send(JSON.stringify({ type: 'done', content: latestTask.summary || '' }));
36
+ unsub();
37
+ ws.close();
38
+ return;
39
+ }
40
+ },
41
+ onClose() {
42
+ unsub?.();
43
+ },
44
+ };
45
+ }));
46
+ }
47
+ //# sourceMappingURL=websocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../../src/server/routes/websocket.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,sBAAsB,CACpC,GAAS,EACT,gBAAyG,EACzG,OAAmB,EACnB,QAAkB;IAElB,GAAG,CAAC,GAAG,CACL,cAAc,EACd,gBAAgB,CAAC,CAAC,CAAM,EAAE,EAAE;QAC1B,IAAI,KAA+B,CAAC;QACpC,OAAO;YACL,MAAM,CAAC,IAAa,EAAE,EAAa;gBACjC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAEjC,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;oBAChC,OAAO;gBACT,CAAC;gBAED,yBAAyB;gBACzB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAChC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;wBACrB,IAAI,EAAE,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa;wBAC5D,OAAO,EAAE,GAAG,CAAC,OAAO;qBACrB,CAAC,CAAC,CAAC;gBACN,CAAC;gBAED,2DAA2D;gBAC3D,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,OAAuB,EAAE,EAAE;oBACzD,IAAI,CAAC;wBACH,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;wBACjC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;4BAC5B,KAAK,EAAE,EAAE,CAAC;4BACV,EAAE,CAAC,KAAK,EAAE,CAAC;wBACb,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,KAAK,EAAE,EAAE,CAAC;oBACZ,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,oCAAoC;gBACpC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACvC,IAAI,UAAU,IAAI,CAAC,UAAU,CAAC,MAAM,KAAK,WAAW,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;oBACxF,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;oBAC7E,KAAK,EAAE,CAAC;oBACR,EAAE,CAAC,KAAK,EAAE,CAAC;oBACX,OAAO;gBACT,CAAC;YACH,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,EAAE,CAAC;YACZ,CAAC;SACF,CAAC;IACJ,CAAC,CAAQ,CACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ /** Message format sent to sandbox clients via SSE/WS */
2
+ export interface SandboxMessage {
3
+ type: 'assistant' | 'tool_use' | 'tool_result' | 'error' | 'done';
4
+ content: string;
5
+ }
6
+ /** Job status as exposed by the HTTP API */
7
+ export type JobStatus = 'pending' | 'running' | 'completed' | 'failed';
8
+ /** Job as returned by GET /jobs/:id */
9
+ export interface Job {
10
+ id: string;
11
+ prompt: string;
12
+ status: JobStatus;
13
+ result?: string;
14
+ created_at: string;
15
+ started_at?: string;
16
+ completed_at?: string;
17
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@accomplish_ai/agent-core-cli",
3
+ "version": "0.1.0",
4
+ "description": "Headless CLI wrapping @accomplish_ai/agent-core",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/accomplish-ai/agent-core-cli.git"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "bin": {
18
+ "agent-core-cli": "./dist/index.js"
19
+ },
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "start": "node dist/index.js",
26
+ "test": "vitest run"
27
+ },
28
+ "dependencies": {
29
+ "@accomplish_ai/agent-core": "^0.2.1",
30
+ "@hono/node-server": "^1.14.0",
31
+ "@hono/node-ws": "^1.1.0",
32
+ "commander": "^13.0.0",
33
+ "hono": "^4.7.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^22.0.0",
37
+ "typescript": "^5.7.0",
38
+ "vitest": "^3.0.0"
39
+ },
40
+ "engines": {
41
+ "node": ">=20"
42
+ }
43
+ }