codedeck 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 +211 -0
- package/dist/cli/commands/diff.js +43 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/doctor.js +90 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/logs.js +139 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/ps.js +59 -0
- package/dist/cli/commands/ps.js.map +1 -0
- package/dist/cli/commands/run.js +145 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/send.js +29 -0
- package/dist/cli/commands/send.js.map +1 -0
- package/dist/cli/commands/show.js +99 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/stop.js +27 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/index.js +63 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/config.js +26 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/paths.js +43 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/core/capabilities.js +14 -0
- package/dist/core/capabilities.js.map +1 -0
- package/dist/core/driver.js +2 -0
- package/dist/core/driver.js.map +1 -0
- package/dist/core/errors.js +61 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/events.js +10 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/session.js +33 -0
- package/dist/core/session.js.map +1 -0
- package/dist/daemon/daemon.js +534 -0
- package/dist/daemon/daemon.js.map +1 -0
- package/dist/daemon/ipc.js +292 -0
- package/dist/daemon/ipc.js.map +1 -0
- package/dist/daemon/process-manager.js +55 -0
- package/dist/daemon/process-manager.js.map +1 -0
- package/dist/daemon/protocol.js +2 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/drivers/claude/driver.js +247 -0
- package/dist/drivers/claude/driver.js.map +1 -0
- package/dist/drivers/claude/parser.js +184 -0
- package/dist/drivers/claude/parser.js.map +1 -0
- package/dist/drivers/codex/driver.js +241 -0
- package/dist/drivers/codex/driver.js.map +1 -0
- package/dist/drivers/codex/parser.js +184 -0
- package/dist/drivers/codex/parser.js.map +1 -0
- package/dist/drivers/helpers.js +85 -0
- package/dist/drivers/helpers.js.map +1 -0
- package/dist/drivers/omp/driver.js +372 -0
- package/dist/drivers/omp/driver.js.map +1 -0
- package/dist/drivers/opencode/driver.js +307 -0
- package/dist/drivers/opencode/driver.js.map +1 -0
- package/dist/drivers/registry.js +48 -0
- package/dist/drivers/registry.js.map +1 -0
- package/dist/git/diff.js +100 -0
- package/dist/git/diff.js.map +1 -0
- package/dist/git/repository.js +68 -0
- package/dist/git/repository.js.map +1 -0
- package/dist/git/worktree.js +89 -0
- package/dist/git/worktree.js.map +1 -0
- package/dist/store/database.js +85 -0
- package/dist/store/database.js.map +1 -0
- package/dist/store/events.js +39 -0
- package/dist/store/events.js.map +1 -0
- package/dist/store/sessions.js +128 -0
- package/dist/store/sessions.js.map +1 -0
- package/dist/utils/process.js +35 -0
- package/dist/utils/process.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# CodeDeck
|
|
2
|
+
|
|
3
|
+
Local runtime for coding agents — session management, process supervision, event normalization, and git isolation.
|
|
4
|
+
|
|
5
|
+
> **Process manager for coding agents**: PM2 + tmux + git worktrees + normalized events
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
CodeDeck is not an agent. It manages the lifecycle of existing harnesses:
|
|
10
|
+
|
|
11
|
+
- **Claude Code** (`claude -p --output-format stream-json`)
|
|
12
|
+
- **Codex** (`codex exec --json` / app-server)
|
|
13
|
+
- **OpenCode** (`opencode run --format json`)
|
|
14
|
+
- **OMP** (`omp --mode rpc`)
|
|
15
|
+
|
|
16
|
+
The `codedeck` CLI provides a single unified interface for all of them:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npx codedeck run "implement authentication" --agent claude
|
|
20
|
+
npx codedeck run "fix the tests" --agent codex
|
|
21
|
+
npx codedeck run "investigate this bug" --agent opencode
|
|
22
|
+
npx codedeck run "refactor this module" --agent omp
|
|
23
|
+
|
|
24
|
+
npx codedeck ps
|
|
25
|
+
npx codedeck logs a83f --follow
|
|
26
|
+
npx codedeck show a83f
|
|
27
|
+
npx codedeck send a83f "add tests"
|
|
28
|
+
npx codedeck stop a83f
|
|
29
|
+
npx codedeck diff a83f
|
|
30
|
+
npx codedeck doctor
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Stack
|
|
34
|
+
|
|
35
|
+
- TypeScript / Node.js
|
|
36
|
+
- SQLite (`node:sqlite` — `DatabaseSync`)
|
|
37
|
+
- Unix Domain Socket for IPC
|
|
38
|
+
- Git worktrees for isolation
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install -g codedeck
|
|
44
|
+
# or
|
|
45
|
+
npx codedeck
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Binary: `codedeck`
|
|
49
|
+
|
|
50
|
+
For local development:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install
|
|
54
|
+
npm run build
|
|
55
|
+
node dist/cli/index.js doctor
|
|
56
|
+
# or create a local alias
|
|
57
|
+
npm link
|
|
58
|
+
npx codedeck doctor
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Architecture
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
codedeck CLI
|
|
65
|
+
│ IPC (Unix Socket, NDJSON)
|
|
66
|
+
▼
|
|
67
|
+
CodeDeck Daemon
|
|
68
|
+
├── Session Store (SQLite)
|
|
69
|
+
├── Event Store (SQLite)
|
|
70
|
+
├── Process Manager
|
|
71
|
+
└── Driver Registry
|
|
72
|
+
├── ClaudeDriver (stream-json)
|
|
73
|
+
├── CodexDriver (exec --json)
|
|
74
|
+
├── OpencodeDriver (run --format json)
|
|
75
|
+
└── OmpDriver (rpc)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The daemon owns the sessions. The CLI only follows events — closing the terminal does not kill the agent.
|
|
79
|
+
|
|
80
|
+
## Commands
|
|
81
|
+
|
|
82
|
+
| Command | Description |
|
|
83
|
+
|---------|-------------|
|
|
84
|
+
| `npx codedeck doctor` | Check Node, Git, harnesses, daemon, and database |
|
|
85
|
+
| `npx codedeck run "<prompt>" --agent <id> [--model <m>] [--name <n>] [--worktree] [--detach]` | Start a session |
|
|
86
|
+
| `npx codedeck ps [--all] [--json]` | List recent sessions |
|
|
87
|
+
| `npx codedeck show <id> [--json]` | Show session details |
|
|
88
|
+
| `npx codedeck logs <id> [--follow] [--json] [--raw]` | Show normalized events |
|
|
89
|
+
| `npx codedeck send <id> "<msg>"` | Continue a session (new turn) |
|
|
90
|
+
| `npx codedeck stop <id>` | Graceful interrupt → SIGTERM → SIGKILL |
|
|
91
|
+
| `npx codedeck diff <id> [--stat] [--json]` | Git diff against base commit |
|
|
92
|
+
|
|
93
|
+
## Session
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
Session {
|
|
97
|
+
id: string // e.g. a83f (CodeDeck)
|
|
98
|
+
nativeSessionId? // internal harness id
|
|
99
|
+
agent: "claude" | "codex" | "opencode" | "omp"
|
|
100
|
+
status: "starting" | "working" | "needs_input" | "idle" | "completed" | "failed" | "stopped" | "orphaned"
|
|
101
|
+
cwd, worktree, branch, repository, baseCommit
|
|
102
|
+
pid, usage, createdAt, updatedAt
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`nativeSessionId` is an internal detail. Users only see the CodeDeck ID.
|
|
107
|
+
|
|
108
|
+
## Normalized Events
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
AgentEvent =
|
|
112
|
+
| session.started | turn.started | text.delta | message
|
|
113
|
+
| tool.started | tool.completed | file.changed
|
|
114
|
+
| permission.requested | permission.resolved
|
|
115
|
+
| usage.updated | turn.completed
|
|
116
|
+
| session.completed | session.failed | error
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Every event is persisted with its original `raw` payload intact for debugging and future compatibility.
|
|
120
|
+
|
|
121
|
+
Tables:
|
|
122
|
+
|
|
123
|
+
- `sessions` — per-session state
|
|
124
|
+
- `events` — monotonic log `(session_id, sequence)`
|
|
125
|
+
|
|
126
|
+
## Worktrees
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx codedeck run "implement oauth" --worktree
|
|
130
|
+
# creates ~/.run-agent/worktrees/<repo-hash>/<session-id>
|
|
131
|
+
# branch: ra/<slug>-<session-id>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The driver receives the worktree as `cwd`. Isolation is the responsibility of CodeDeck, not the harness.
|
|
135
|
+
|
|
136
|
+
Global config: `~/.config/run-agent/config.json` or `~/.run-agent/` (fallback)
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"defaultAgent": "claude",
|
|
141
|
+
"worktree": true
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Spikes
|
|
146
|
+
|
|
147
|
+
Validates each harness in isolation before abstractions:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
spikes/claude.ts
|
|
151
|
+
spikes/codex.ts
|
|
152
|
+
spikes/opencode.ts
|
|
153
|
+
spikes/omp.ts
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Run with:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx tsx spikes/claude.ts
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Each spike proves: detect, start, prompt, events, nativeSessionId, completion, interrupt, resume, stderr, and cleanup.
|
|
163
|
+
|
|
164
|
+
## Development
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
src/
|
|
168
|
+
cli/ → commander, commands (run/ps/show/logs/send/stop/diff/doctor)
|
|
169
|
+
core/ → driver interface, session, events, capabilities, errors
|
|
170
|
+
drivers/ → claude / codex / opencode / omp
|
|
171
|
+
daemon/ → daemon, ipc (Unix socket), process-manager, protocol
|
|
172
|
+
store/ → SQLite (sessions, events)
|
|
173
|
+
git/ → repository, worktree, diff
|
|
174
|
+
config/ → paths, config
|
|
175
|
+
utils/
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Build:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
npm run build
|
|
182
|
+
npm test
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Definition of Done (first release)
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
cd example-project
|
|
189
|
+
npx codedeck doctor
|
|
190
|
+
npx codedeck run "find one improvement and implement it" --agent claude --worktree --detach
|
|
191
|
+
npx codedeck run "find one improvement and implement it" --agent codex --worktree --detach
|
|
192
|
+
npx codedeck ps
|
|
193
|
+
npx codedeck logs <claude-session> --follow
|
|
194
|
+
npx codedeck show <codex-session>
|
|
195
|
+
npx codedeck diff <claude-session>
|
|
196
|
+
npx codedeck diff <codex-session>
|
|
197
|
+
npx codedeck send <claude-session> "run the tests before finishing"
|
|
198
|
+
npx codedeck stop <codex-session>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The same experience across all four harnesses.
|
|
202
|
+
|
|
203
|
+
## Security
|
|
204
|
+
|
|
205
|
+
- Does not store API keys/tokens — uses harness authentication.
|
|
206
|
+
- Raw events may contain sensitive data (documented).
|
|
207
|
+
- Does not silently modify user configuration.
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { IpcClient } from "../../daemon/ipc.js";
|
|
2
|
+
export function registerDiffCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("diff")
|
|
5
|
+
.description("Show git diff for a session against its base commit (harness-independent)")
|
|
6
|
+
.argument("<id>", "session id (prefix allowed, e.g. a83f)")
|
|
7
|
+
.option("--stat", "show diff --stat and file list only")
|
|
8
|
+
.option("--json", "output JSON { base, diff, stat, files }")
|
|
9
|
+
.action(async (id, opts) => {
|
|
10
|
+
const client = new IpcClient();
|
|
11
|
+
try {
|
|
12
|
+
await client.ensureDaemonStarted();
|
|
13
|
+
}
|
|
14
|
+
catch { }
|
|
15
|
+
let result;
|
|
16
|
+
try {
|
|
17
|
+
result = await client.request("session.diff", { id });
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
if (opts.json) {
|
|
24
|
+
console.log(JSON.stringify(result, null, 2));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (opts.stat) {
|
|
28
|
+
console.log(result.stat || "(no stat)");
|
|
29
|
+
if (result.files?.length) {
|
|
30
|
+
console.log(`\nFiles: ${result.files.join(", ")}`);
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!result.diff || !result.diff.trim()) {
|
|
35
|
+
console.log("(no changes)");
|
|
36
|
+
if (result.files?.length)
|
|
37
|
+
console.log(`Files: ${result.files.join(", ")}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(result.diff);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/cli/commands/diff.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,2EAA2E,CAAC;SACxF,QAAQ,CAAC,MAAM,EAAE,wCAAwC,CAAC;SAC1D,MAAM,CAAC,QAAQ,EAAE,qCAAqC,CAAC;SACvD,MAAM,CAAC,QAAQ,EAAE,yCAAyC,CAAC;SAC3D,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAS,EAAE,EAAE;QACtC,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC;YAAC,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACpD,IAAI,MAAW,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC;YACxC,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC5B,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3E,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { IpcClient, isDaemonRunning } from "../../daemon/ipc.js";
|
|
2
|
+
import { getPaths } from "../../config/paths.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
function check(label, ok, detail) {
|
|
5
|
+
const icon = ok ? "✓" : "✗";
|
|
6
|
+
const msg = detail ? `${label.padEnd(20)} ${icon} ${detail}` : `${label.padEnd(20)} ${icon}`;
|
|
7
|
+
return ok ? msg : `\x1b[31m${msg}\x1b[0m`;
|
|
8
|
+
}
|
|
9
|
+
export function registerDoctorCommand(program) {
|
|
10
|
+
program
|
|
11
|
+
.command("doctor")
|
|
12
|
+
.description("Check Node, Git, harnesses, daemon, database and paths")
|
|
13
|
+
.option("--json", "output JSON with full health report")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
const client = new IpcClient();
|
|
16
|
+
let daemonRunning = await isDaemonRunning();
|
|
17
|
+
if (!daemonRunning) {
|
|
18
|
+
try {
|
|
19
|
+
await client.ensureDaemonStarted();
|
|
20
|
+
daemonRunning = true;
|
|
21
|
+
}
|
|
22
|
+
catch { }
|
|
23
|
+
}
|
|
24
|
+
let result;
|
|
25
|
+
try {
|
|
26
|
+
result = await client.request("doctor", {});
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
console.error(`Doctor failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
if (opts.json) {
|
|
33
|
+
console.log(JSON.stringify(result, null, 2));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
console.log("CodeDeck\n");
|
|
37
|
+
console.log("System");
|
|
38
|
+
console.log(` Node ${result.node.version}`);
|
|
39
|
+
console.log(` ${check("Git", result.git.installed, result.git.version || "not found")}`);
|
|
40
|
+
console.log("");
|
|
41
|
+
for (const [agent, info] of Object.entries(result.agents)) {
|
|
42
|
+
const label = agent.charAt(0).toUpperCase() + agent.slice(1);
|
|
43
|
+
// normalize name
|
|
44
|
+
const display = label === "Claude" ? "Claude Code" : label.charAt(0).toUpperCase() + label.slice(1);
|
|
45
|
+
console.log(display);
|
|
46
|
+
console.log(` ${check("installed", !!info.installed, info.version || info.path || (info.installed ? "yes" : "no"))}`);
|
|
47
|
+
if (info.installed) {
|
|
48
|
+
const auth = info.authenticated;
|
|
49
|
+
if (auth === true)
|
|
50
|
+
console.log(` ${check("authenticated", true, "yes")}`);
|
|
51
|
+
else if (auth === false)
|
|
52
|
+
console.log(` ${check("authenticated", false, "no")}`);
|
|
53
|
+
else
|
|
54
|
+
console.log(` ${check("authenticated", true, "unknown")}`);
|
|
55
|
+
const caps = info.capabilities || {};
|
|
56
|
+
for (const [k, v] of Object.entries(caps)) {
|
|
57
|
+
const ok = !!v;
|
|
58
|
+
const mark = ok ? "✓" : "✗";
|
|
59
|
+
// Use check helper but without color for capabilities maybe
|
|
60
|
+
console.log(` ${k.padEnd(20)} ${ok ? "✓" : "✗"} ${ok ? "yes" : "no"}`);
|
|
61
|
+
}
|
|
62
|
+
if (info.details)
|
|
63
|
+
console.log(` details ${info.details}`);
|
|
64
|
+
}
|
|
65
|
+
else if (info.error) {
|
|
66
|
+
console.log(` error ${info.error}`);
|
|
67
|
+
}
|
|
68
|
+
console.log("");
|
|
69
|
+
}
|
|
70
|
+
console.log("Daemon");
|
|
71
|
+
console.log(` ${check("running", !!result.daemon.running, result.daemon.running ? `pid ${result.daemon.pid}` : "not running")}`);
|
|
72
|
+
if (result.daemon.running) {
|
|
73
|
+
const up = result.daemon.uptime;
|
|
74
|
+
const upStr = up ? `${Math.floor(up / 1000)}s` : "unknown";
|
|
75
|
+
console.log(` uptime ${upStr}`);
|
|
76
|
+
}
|
|
77
|
+
console.log("");
|
|
78
|
+
console.log("Database");
|
|
79
|
+
console.log(` path ${result.database.path}`);
|
|
80
|
+
console.log(` ${check("exists", !!result.database.exists, result.database.exists ? "yes" : "no")}`);
|
|
81
|
+
console.log("");
|
|
82
|
+
const paths = getPaths();
|
|
83
|
+
console.log("Paths");
|
|
84
|
+
console.log(` base ${paths.base}`);
|
|
85
|
+
console.log(` socket ${paths.daemonSock} ${fs.existsSync(paths.daemonSock) ? "✓" : "✗"}`);
|
|
86
|
+
console.log(` worktrees ${paths.worktreesDir}`);
|
|
87
|
+
console.log("");
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { IpcClient } from "../../daemon/ipc.js";
|
|
2
|
+
function formatEvent(ev) {
|
|
3
|
+
const t = new Date(ev.timestamp).toLocaleTimeString();
|
|
4
|
+
switch (ev.type) {
|
|
5
|
+
case "session.started":
|
|
6
|
+
return `[${t}] ● Session started ${ev.nativeSessionId ? `(native ${String(ev.nativeSessionId).slice(0, 8)})` : ""}`;
|
|
7
|
+
case "turn.started":
|
|
8
|
+
return `[${t}] ▶ Turn started${ev.prompt ? `: ${String(ev.prompt).slice(0, 100)}` : ""}`;
|
|
9
|
+
case "message":
|
|
10
|
+
return `[${t}] ${ev.role === "user" ? "▶" : "●"} ${ev.role}: ${String(ev.content).slice(0, 500)}`;
|
|
11
|
+
case "text.delta":
|
|
12
|
+
return ev.delta;
|
|
13
|
+
case "tool.started":
|
|
14
|
+
return `[${t}] → ${ev.tool.name} ${ev.tool.input ? JSON.stringify(ev.tool.input).slice(0, 120) : ""}`;
|
|
15
|
+
case "tool.completed":
|
|
16
|
+
return `[${t}] ✓ ${ev.tool.name} ${ev.tool.success === false ? "failed" : "done"}${ev.tool.output ? `: ${String(ev.tool.output).slice(0, 200)}` : ""}`;
|
|
17
|
+
case "file.changed":
|
|
18
|
+
return `[${t}] ✎ ${ev.change} ${ev.path}`;
|
|
19
|
+
case "usage.updated":
|
|
20
|
+
return `[${t}] ◐ usage: ${JSON.stringify(ev.usage)}`;
|
|
21
|
+
case "turn.completed":
|
|
22
|
+
return `[${t}] ◑ turn completed (${ev.reason || ""})`;
|
|
23
|
+
case "session.completed":
|
|
24
|
+
return `[${t}] ● Session completed ${ev.reason || ""}`;
|
|
25
|
+
case "session.failed":
|
|
26
|
+
return `[${t}] ✗ Session failed: ${ev.error}`;
|
|
27
|
+
case "error":
|
|
28
|
+
return `[${t}] ✗ Error: ${ev.error}`;
|
|
29
|
+
case "permission.requested":
|
|
30
|
+
return `[${t}] ? Permission requested: ${ev.tool || ev.description || ""}`;
|
|
31
|
+
default:
|
|
32
|
+
return `[${t}] ${ev.type} ${JSON.stringify(ev).slice(0, 200)}`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function registerLogsCommand(program) {
|
|
36
|
+
program
|
|
37
|
+
.command("logs")
|
|
38
|
+
.description("Show normalized session logs (human, JSON, or raw)")
|
|
39
|
+
.argument("<id>", "session id (prefix allowed, e.g. a83f)")
|
|
40
|
+
.option("--follow", "follow logs in real time (Ctrl+C to detach, session keeps running)")
|
|
41
|
+
.option("--json", "output JSON array of normalized events")
|
|
42
|
+
.option("--raw", "output raw harness payloads (debug)")
|
|
43
|
+
.action(async (id, opts) => {
|
|
44
|
+
const client = new IpcClient();
|
|
45
|
+
try {
|
|
46
|
+
await client.ensureDaemonStarted();
|
|
47
|
+
}
|
|
48
|
+
catch { }
|
|
49
|
+
let result;
|
|
50
|
+
try {
|
|
51
|
+
result = await client.request("session.logs", { id, follow: !!opts.follow, json: !!opts.json, raw: !!opts.raw });
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
console.error(e instanceof Error ? e.message : String(e));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const events = result.events || [];
|
|
58
|
+
if (opts.json) {
|
|
59
|
+
console.log(JSON.stringify(events, null, 2));
|
|
60
|
+
if (!opts.follow)
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
else if (opts.raw) {
|
|
64
|
+
for (const ev of events) {
|
|
65
|
+
console.log(JSON.stringify(ev.raw || ev, null, 2));
|
|
66
|
+
}
|
|
67
|
+
if (!opts.follow)
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
for (const ev of events) {
|
|
72
|
+
if (ev.type === "text.delta") {
|
|
73
|
+
// For logs non-follow, show deltas as they are but maybe skip to avoid spam?
|
|
74
|
+
// We'll show them
|
|
75
|
+
process.stdout.write(ev.delta);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
console.log(formatEvent(ev));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!opts.follow) {
|
|
82
|
+
// If terminal not reached and follow not requested, just exit
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!opts.follow)
|
|
87
|
+
return;
|
|
88
|
+
// Follow mode: subscribe
|
|
89
|
+
console.log(`\n— following ${id} (Ctrl+C to exit) —\n`);
|
|
90
|
+
const onEvent = (ev) => {
|
|
91
|
+
if (opts.json) {
|
|
92
|
+
console.log(JSON.stringify(ev));
|
|
93
|
+
}
|
|
94
|
+
else if (opts.raw) {
|
|
95
|
+
console.log(JSON.stringify(ev.raw || ev, null, 2));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
if (ev.type === "text.delta")
|
|
99
|
+
process.stdout.write(ev.delta);
|
|
100
|
+
else
|
|
101
|
+
console.log(formatEvent(ev));
|
|
102
|
+
}
|
|
103
|
+
if (ev.type === "session.completed" || ev.type === "session.failed") {
|
|
104
|
+
console.log(`\n— session ${ev.type === "session.completed" ? "completed" : "failed"} —`);
|
|
105
|
+
process.exit(ev.type === "session.failed" ? 1 : 0);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const off = client.subscribe(id, onEvent, () => {
|
|
109
|
+
console.log("\n— stream ended —");
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}, (err) => {
|
|
112
|
+
console.error(`Subscribe error: ${err.message}`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|
|
115
|
+
process.on("SIGINT", () => {
|
|
116
|
+
console.log("\nDetached.");
|
|
117
|
+
off();
|
|
118
|
+
process.exit(0);
|
|
119
|
+
});
|
|
120
|
+
// Also poll status as fallback
|
|
121
|
+
const poll = async () => {
|
|
122
|
+
while (true) {
|
|
123
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
124
|
+
try {
|
|
125
|
+
const info = await client.request("session.get", { id });
|
|
126
|
+
const status = info.session.status;
|
|
127
|
+
if (["completed", "failed", "stopped"].includes(status)) {
|
|
128
|
+
console.log(`\nSession ${status}`);
|
|
129
|
+
off();
|
|
130
|
+
process.exit(status === "failed" ? 1 : 0);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch { }
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
poll();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { IpcClient } from "../../daemon/ipc.js";
|
|
2
|
+
function formatAge(date) {
|
|
3
|
+
const d = new Date(date);
|
|
4
|
+
const diffMs = Date.now() - d.getTime();
|
|
5
|
+
const mins = Math.floor(diffMs / 60000);
|
|
6
|
+
if (mins < 1)
|
|
7
|
+
return "now";
|
|
8
|
+
if (mins < 60)
|
|
9
|
+
return `${mins}m`;
|
|
10
|
+
const hours = Math.floor(mins / 60);
|
|
11
|
+
if (hours < 24)
|
|
12
|
+
return `${hours}h`;
|
|
13
|
+
const days = Math.floor(hours / 24);
|
|
14
|
+
return `${days}d`;
|
|
15
|
+
}
|
|
16
|
+
export function registerPsCommand(program) {
|
|
17
|
+
program
|
|
18
|
+
.command("ps")
|
|
19
|
+
.description("List recent sessions (daemon-owned, not harness IDs)")
|
|
20
|
+
.option("--all", "include all sessions including completed/failed (default: recent)")
|
|
21
|
+
.option("--json", "output JSON instead of table")
|
|
22
|
+
.action(async (opts) => {
|
|
23
|
+
const client = new IpcClient();
|
|
24
|
+
try {
|
|
25
|
+
await client.ensureDaemonStarted();
|
|
26
|
+
}
|
|
27
|
+
catch { }
|
|
28
|
+
let result;
|
|
29
|
+
try {
|
|
30
|
+
result = await client.request("session.list", { all: !!opts.all });
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
console.error(`Failed to list sessions: ${e instanceof Error ? e.message : String(e)}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const sessions = result.sessions || [];
|
|
37
|
+
if (opts.json) {
|
|
38
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (sessions.length === 0) {
|
|
42
|
+
console.log("No sessions");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Header
|
|
46
|
+
console.log("ID NAME AGENT STATUS AGE CWD");
|
|
47
|
+
console.log("─".repeat(80));
|
|
48
|
+
for (const s of sessions) {
|
|
49
|
+
const id = (s.id || "").padEnd(4);
|
|
50
|
+
const name = (s.name || s.branch?.replace("ra/", "") || "-").slice(0, 16).padEnd(16);
|
|
51
|
+
const agent = (s.agent || "").padEnd(9);
|
|
52
|
+
const status = (s.status || "").padEnd(12);
|
|
53
|
+
const age = formatAge(s.createdAt).padEnd(5);
|
|
54
|
+
const cwd = (s.worktree || s.cwd || "").replace(process.env.HOME || "", "~");
|
|
55
|
+
console.log(`${id} ${name} ${agent} ${status} ${age} ${cwd}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=ps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ps.js","sourceRoot":"","sources":["../../../src/cli/commands/ps.ts"],"names":[],"mappings":"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"}
|