dev-sessions 0.2.1 → 0.2.3
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 +124 -77
- package/dist/backends/backend.d.ts +42 -0
- package/dist/backends/backend.js +3 -0
- package/dist/backends/backend.js.map +1 -0
- package/dist/backends/claude-backend.d.ts +22 -0
- package/dist/backends/claude-backend.js +161 -0
- package/dist/backends/claude-backend.js.map +1 -0
- package/dist/backends/claude-tmux.d.ts +1 -3
- package/dist/backends/claude-tmux.js +15 -24
- package/dist/backends/claude-tmux.js.map +1 -1
- package/dist/backends/codex-appserver.d.ts +46 -6
- package/dist/backends/codex-appserver.js +299 -130
- package/dist/backends/codex-appserver.js.map +1 -1
- package/dist/backends/codex-backend.d.ts +21 -0
- package/dist/backends/codex-backend.js +224 -0
- package/dist/backends/codex-backend.js.map +1 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +31 -3
- package/dist/cli.js.map +1 -1
- package/dist/gateway/client.d.ts +3 -1
- package/dist/gateway/client.js +24 -2
- package/dist/gateway/client.js.map +1 -1
- package/dist/gateway/server.js +45 -2
- package/dist/gateway/server.js.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/session-manager.d.ts +7 -9
- package/dist/session-manager.js +122 -367
- package/dist/session-manager.js.map +1 -1
- package/dist/session-store.js +16 -4
- package/dist/session-store.js.map +1 -1
- package/dist/transcript/claude-parser.d.ts +1 -0
- package/dist/transcript/claude-parser.js +4 -0
- package/dist/transcript/claude-parser.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/package.json +1 -1
- package/skills/delegate/SKILL.md +77 -0
- package/skills/dev-sessions/SKILL.md +5 -13
package/README.md
CHANGED
|
@@ -11,33 +11,45 @@ Coding agents (Claude Code, Codex) are increasingly capable of orchestrating par
|
|
|
11
11
|
- **Send** tasks and messages to those sessions
|
|
12
12
|
- **Wait** for turns to complete (transcript-aware, not terminal scraping)
|
|
13
13
|
- **Read** structured responses (clean assistant text, not ANSI noise)
|
|
14
|
-
- **Check status** (idle
|
|
14
|
+
- **Check status** (`idle`, `working`, `waiting_for_input`)
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Installation
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- **Transcript**: `~/.claude/projects/<encoded-path>/<uuid>.jsonl`
|
|
22
|
-
- **Message delivery**: tmux send-keys (base64 encoded for safety)
|
|
23
|
-
- **Turn detection**: Watches for `system` entries in JSONL transcript (definitive turn-completion signal)
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g dev-sessions
|
|
20
|
+
```
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
Or clone and link for local development:
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/andrewting19/dev-sessions
|
|
25
|
+
cd dev-sessions
|
|
26
|
+
npm install && npm run build && npm link
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Host Setup (one-time)
|
|
30
|
+
|
|
31
|
+
Install the gateway as a system daemon so it auto-starts on login:
|
|
32
|
+
```bash
|
|
33
|
+
dev-sessions gateway install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
On macOS, grant Full Disk Access to the node binary printed by that command (System Settings → Privacy & Security → Full Disk Access). This is needed if your repos live in ~/Documents or other protected paths.
|
|
37
|
+
|
|
38
|
+
Install skills for Claude and/or Codex:
|
|
39
|
+
```bash
|
|
40
|
+
dev-sessions install-skill --global
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
32
44
|
|
|
33
45
|
## Usage
|
|
34
46
|
|
|
35
47
|
```bash
|
|
36
|
-
# Create a session (defaults: --cli claude, --mode
|
|
48
|
+
# Create a session (defaults: --cli claude, --mode native)
|
|
37
49
|
dev-sessions create --description "refactor auth module"
|
|
38
50
|
# => fizz-top
|
|
39
51
|
|
|
40
|
-
# Send a task
|
|
52
|
+
# Send a task (returns immediately — non-blocking)
|
|
41
53
|
dev-sessions send fizz-top "Implement JWT auth. See AUTH-SPEC.md for details."
|
|
42
54
|
dev-sessions send fizz-top --file BRIEFING.md
|
|
43
55
|
|
|
@@ -59,8 +71,7 @@ s1=$(dev-sessions create -q --description "frontend")
|
|
|
59
71
|
s2=$(dev-sessions create -q --description "backend")
|
|
60
72
|
dev-sessions send $s1 "build React form per SPEC.md"
|
|
61
73
|
dev-sessions send $s2 "add /api/users endpoint per SPEC.md"
|
|
62
|
-
dev-sessions wait $s1
|
|
63
|
-
dev-sessions wait $s2
|
|
74
|
+
dev-sessions wait $s1 & dev-sessions wait $s2 & wait
|
|
64
75
|
dev-sessions last-message $s1
|
|
65
76
|
dev-sessions last-message $s2
|
|
66
77
|
|
|
@@ -74,77 +85,77 @@ dev-sessions last-message $sid # "You said hello"
|
|
|
74
85
|
dev-sessions kill fizz-top
|
|
75
86
|
```
|
|
76
87
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
npm install -g dev-sessions
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Or clone and link:
|
|
84
|
-
```bash
|
|
85
|
-
git clone https://github.com/andrewting19/dev-sessions
|
|
86
|
-
cd dev-sessions
|
|
87
|
-
npm install && npm run build && npm link
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Skill Installation (Optional)
|
|
88
|
+
---
|
|
91
89
|
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
dev-sessions install-skill --global # Auto-detect available tools
|
|
95
|
-
dev-sessions install-skill --global --claude # Claude Code only
|
|
96
|
-
dev-sessions install-skill --global --codex # Codex CLI only
|
|
97
|
-
dev-sessions install-skill --local # Current directory only
|
|
98
|
-
```
|
|
90
|
+
## Architecture
|
|
99
91
|
|
|
100
|
-
|
|
92
|
+
### Claude Code Sessions
|
|
93
|
+
- **Backend**: tmux (human-attachable via `tmux attach -t dev-<id>`)
|
|
94
|
+
- **Session ID**: Pre-assigned UUID via `claude --session-id <uuid>` — transcript path is known immediately
|
|
95
|
+
- **Transcript**: `~/.claude/projects/<sanitized-cwd>/<uuid>.jsonl`
|
|
96
|
+
- Sanitized CWD: path with `/` replaced by `-`, e.g. `-Users-andrew-Documents-git-repos-myproject`
|
|
97
|
+
- **Message delivery**: `tmux send-keys` (base64 encoded for safety)
|
|
98
|
+
- **Turn detection**: Watches for `system` entries in JSONL (definitive turn-completion signal)
|
|
99
|
+
- **Status inference**: last entry is `assistant` → idle; `human/user` → working; tool call to `AskUserQuestion` → waiting_for_input
|
|
101
100
|
|
|
102
|
-
|
|
101
|
+
### Codex Sessions
|
|
102
|
+
- **Backend**: Persistent `codex app-server` daemon (JSON-RPC 2.0 over WebSocket)
|
|
103
|
+
- **Session ID**: Thread ID from `thread/start` response
|
|
104
|
+
- **Conversation continuity**: Multiple sends share the same thread — full history preserved
|
|
105
|
+
- **Message delivery**: `turn/start` JSON-RPC call (non-blocking — returns after `turn/started`)
|
|
106
|
+
- **Turn detection**: `turn/completed` notification; also `thread/status/changed` (Active → Idle)
|
|
107
|
+
- **Message history**: Fetched via `thread/read` with `includeTurns: true` — persisted across process restarts
|
|
108
|
+
- **Turn status**: Checked via `thread/resume` which returns live `Thread.status`
|
|
109
|
+
- **Session liveness**: Verified via `thread/list` — checks specific thread ID exists, not just daemon PID
|
|
110
|
+
- **Daemon lifecycle**: Auto-started on first `create --cli codex`, auto-stopped when last Codex session is killed
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|------|------|-------------|
|
|
106
|
-
| `yolo` | `--mode yolo` | Runs with permission bypass flags — `--dangerously-skip-permissions` for Claude, `approvalPolicy: never` for Codex (default) |
|
|
107
|
-
| `native` | `--mode native` | Runs normally, will prompt for permissions |
|
|
108
|
-
| `docker` | `--mode docker` | Runs via `clauded` Docker wrapper (Claude Code only — see below) |
|
|
112
|
+
### Codex App-Server Protocol
|
|
109
113
|
|
|
110
|
-
|
|
114
|
+
```
|
|
115
|
+
initialize → initialized → thread/start → turn/start → [stream notifications] → turn/started → ... → turn/completed
|
|
116
|
+
```
|
|
111
117
|
|
|
112
|
-
|
|
118
|
+
Key methods: `thread/start`, `turn/start`, `turn/interrupt`, `thread/list`, `thread/resume`, `thread/read`
|
|
119
|
+
Key notifications: `turn/started`, `item/agentMessage/delta`, `turn/completed`, `thread/status/changed`
|
|
113
120
|
|
|
114
|
-
|
|
121
|
+
**`ThreadStatus` JSON shape** — important, easy to get wrong:
|
|
122
|
+
- `"idle"`, `"notLoaded"`, `"systemError"` serialize as **plain strings**
|
|
123
|
+
- `"active"` serializes as `{ "active": { "activeFlags": [...] } }` — a tagged enum variant
|
|
124
|
+
- Do NOT look for a `.type` field — that's the wrong shape
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
1. Start the gateway on the host: `dev-sessions gateway --port 6767`
|
|
118
|
-
- Note: port 6767 may conflict with Docker's own port forwarding. Use `DEV_SESSIONS_GATEWAY_PORT=6868` if needed.
|
|
119
|
-
2. Inside Docker, set `DEV_SESSIONS_GATEWAY_URL=http://host.docker.internal:6767` (or your chosen port)
|
|
120
|
-
3. Set `HOST_PATH` to map the container workspace path to the equivalent host path
|
|
126
|
+
### Champion IDs
|
|
121
127
|
|
|
122
|
-
|
|
128
|
+
Sessions get human-readable IDs like `fizz-top`, `riven-jg` (League of Legends champion + role). These map to internal UUIDs/thread IDs but are easier to type and remember.
|
|
123
129
|
|
|
124
|
-
|
|
130
|
+
### Session Store
|
|
125
131
|
|
|
126
|
-
|
|
132
|
+
Persisted at `~/.dev-sessions/sessions.json`. No cross-process locking — avoid concurrent `create` calls (tracked in TODO.md).
|
|
127
133
|
|
|
128
|
-
|
|
129
|
-
> ```bash
|
|
130
|
-
> #!/bin/zsh
|
|
131
|
-
> source ~/.zshrc 2>/dev/null
|
|
132
|
-
> claude-docker "$@"
|
|
133
|
-
> ```
|
|
134
|
+
---
|
|
134
135
|
|
|
135
136
|
## Commands
|
|
136
137
|
|
|
137
138
|
| Command | Description |
|
|
138
139
|
|---------|-------------|
|
|
139
|
-
| `create [options]` | Spawn a new agent session (`--cli claude
|
|
140
|
-
| `send <id> <msg>` | Send a message
|
|
141
|
-
| `wait <id>` | Block until current turn completes (`--timeout`
|
|
142
|
-
| `last-message <id>` | Get last assistant
|
|
140
|
+
| `create [options]` | Spawn a new agent session (`--cli claude|codex`, `--mode native|docker`, `-q` quiet) |
|
|
141
|
+
| `send <id> <msg>` | Send a message — returns immediately after delivery (`--file` to send file contents) |
|
|
142
|
+
| `wait <id>` | Block until current turn completes (`--timeout` seconds, `--interval` poll interval) |
|
|
143
|
+
| `last-message <id>` | Get last N assistant messages (`-n` count) |
|
|
143
144
|
| `status <id>` | Get session status: `idle`, `working`, or `waiting_for_input` |
|
|
144
|
-
| `list` | List all active sessions |
|
|
145
|
+
| `list` | List all active sessions (`--json` for machine-readable output) |
|
|
145
146
|
| `kill <id>` | Terminate a session and clean up |
|
|
146
147
|
| `gateway` | Start the Docker relay gateway HTTP server (`--port`) |
|
|
147
|
-
| `install
|
|
148
|
+
| `gateway install` | Install gateway as system daemon (launchd on macOS, systemd on Linux) |
|
|
149
|
+
| `gateway uninstall` | Remove gateway daemon |
|
|
150
|
+
| `gateway status` | Check if gateway daemon is running and on which port |
|
|
151
|
+
| `install-skill` | Install all skills (`--global\|--local`, `--claude\|--codex`) |
|
|
152
|
+
|
|
153
|
+
## Modes
|
|
154
|
+
|
|
155
|
+
| Mode | Flag | Description |
|
|
156
|
+
|------|------|-------------|
|
|
157
|
+
| `native` | `--mode native` | Runs with `--dangerously-skip-permissions` — auto-approves all tool calls (default) |
|
|
158
|
+
| `docker` | `--mode docker` | Runs via `clauded` Docker wrapper (Claude Code only) |
|
|
148
159
|
|
|
149
160
|
## Session Lifecycle
|
|
150
161
|
|
|
@@ -155,23 +166,59 @@ create → send → [wait / poll status] → last-message → kill
|
|
|
155
166
|
(send follow-up)
|
|
156
167
|
```
|
|
157
168
|
|
|
169
|
+
`send` is non-blocking — it returns immediately after the message is delivered. Use `wait` to block until the turn completes.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Docker Integration
|
|
174
|
+
|
|
175
|
+
### Running FROM inside a container
|
|
176
|
+
|
|
177
|
+
When running inside a Docker container (detected via `IS_SANDBOX=1`), the CLI automatically routes all commands through an HTTP gateway relay on the host.
|
|
178
|
+
|
|
179
|
+
**Setup:**
|
|
180
|
+
1. On the host: `dev-sessions gateway install` (or manually `dev-sessions gateway --port 6767`)
|
|
181
|
+
2. Inside Docker, set `DEV_SESSIONS_GATEWAY_URL=http://host.docker.internal:6767`
|
|
182
|
+
3. Set `HOST_PATH` to map the container workspace path to the host path
|
|
183
|
+
|
|
184
|
+
The gateway binds to `127.0.0.1` only — not exposed beyond loopback.
|
|
185
|
+
|
|
186
|
+
### `--mode docker` (spawning Claude in a container)
|
|
187
|
+
|
|
188
|
+
Spawns Claude inside Docker via a `clauded` binary on the host. See [claude-ting](https://github.com/andrewting19/claude-ting) for a reference Docker wrapper.
|
|
189
|
+
|
|
190
|
+
> **Note:** If `clauded` is defined as a shell function in `.zshrc`, create a wrapper script so tmux (bash) can find it:
|
|
191
|
+
> ```bash
|
|
192
|
+
> #!/bin/zsh
|
|
193
|
+
> source ~/.zshrc 2>/dev/null
|
|
194
|
+
> claude-docker "$@"
|
|
195
|
+
> ```
|
|
196
|
+
> at `~/.local/bin/clauded`.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
158
200
|
## Known Limitations
|
|
159
201
|
|
|
160
|
-
- **
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
- **Gateway port conflict**:
|
|
202
|
+
- **Codex ignores `--mode`**: Always runs with `approvalPolicy: never` / full access regardless of mode flag.
|
|
203
|
+
- **`docker` mode is Claude-only**: Codex + Docker not implemented.
|
|
204
|
+
- **Session store has no locking**: Concurrent `create` calls can race. Avoid for now.
|
|
205
|
+
- **Gateway port conflict**: Default port 6767 can conflict with Docker. Use `DEV_SESSIONS_GATEWAY_PORT` to override.
|
|
206
|
+
- **No `respond` command**: No structured way to respond to `waiting_for_input` sessions. Only matters for non-native modes.
|
|
207
|
+
- **Claude permission prompts undetectable**: TUI-level prompts aren't written to JSONL — `status` reports `working` instead of `waiting_for_input`. Only affects `native` mode.
|
|
208
|
+
|
|
209
|
+
---
|
|
164
210
|
|
|
165
211
|
## Development
|
|
166
212
|
|
|
167
213
|
```bash
|
|
168
214
|
npm install
|
|
169
215
|
npm run build
|
|
170
|
-
npm test
|
|
171
|
-
npm
|
|
172
|
-
npm link # for local CLI testing
|
|
216
|
+
npm test # 123 unit + integration tests
|
|
217
|
+
npm link # link global dev-sessions to this repo's dist/
|
|
173
218
|
```
|
|
174
219
|
|
|
220
|
+
See `CLAUDE.md` for developer workflow standards and `TODO.md` for current project state and remaining work.
|
|
221
|
+
|
|
175
222
|
## License
|
|
176
223
|
|
|
177
224
|
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AgentTurnStatus, SessionCli, SessionMode, SessionTurn, StoredSession, WaitResult } from '../types';
|
|
2
|
+
export interface BackendCreateOptions {
|
|
3
|
+
championId: string;
|
|
4
|
+
workspacePath: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
mode?: SessionMode;
|
|
7
|
+
model?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BackendCreateResult {
|
|
10
|
+
internalId: string;
|
|
11
|
+
mode: SessionMode;
|
|
12
|
+
appServerPid?: number;
|
|
13
|
+
appServerPort?: number;
|
|
14
|
+
model?: string;
|
|
15
|
+
codexTurnInProgress?: boolean;
|
|
16
|
+
lastAssistantMessages?: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface BackendStatusResult {
|
|
19
|
+
status: AgentTurnStatus;
|
|
20
|
+
storeUpdate?: Partial<StoredSession>;
|
|
21
|
+
errorToThrow?: Error;
|
|
22
|
+
}
|
|
23
|
+
export interface BackendWaitResult extends WaitResult {
|
|
24
|
+
storeUpdate: Partial<StoredSession>;
|
|
25
|
+
errorToThrow?: Error;
|
|
26
|
+
}
|
|
27
|
+
export interface Backend {
|
|
28
|
+
readonly cli: SessionCli;
|
|
29
|
+
readonly deadSessionPolicy: 'prune' | 'deactivate';
|
|
30
|
+
isChampionIdTaken(championId: string): Promise<boolean>;
|
|
31
|
+
create(options: BackendCreateOptions): Promise<BackendCreateResult>;
|
|
32
|
+
preSendStoreFields(session: StoredSession, sendTime: string): Partial<StoredSession>;
|
|
33
|
+
send(session: StoredSession, message: string): Promise<Partial<StoredSession>>;
|
|
34
|
+
onSendError(session: StoredSession, error: Error): Partial<StoredSession>;
|
|
35
|
+
status(session: StoredSession): Promise<BackendStatusResult>;
|
|
36
|
+
wait(session: StoredSession, timeoutMs: number, intervalMs: number): Promise<BackendWaitResult>;
|
|
37
|
+
exists(session: StoredSession): Promise<'alive' | 'dead' | 'unknown'>;
|
|
38
|
+
getLastMessages(session: StoredSession, count: number): Promise<string[]>;
|
|
39
|
+
getLogs(session: StoredSession): Promise<SessionTurn[]>;
|
|
40
|
+
kill(session: StoredSession): Promise<void>;
|
|
41
|
+
afterKill(remainingActiveSessions: StoredSession[]): Promise<void>;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/backends/backend.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SessionCli, SessionTurn, StoredSession } from '../types';
|
|
2
|
+
import { Backend, BackendCreateOptions, BackendCreateResult, BackendStatusResult, BackendWaitResult } from './backend';
|
|
3
|
+
import { ClaudeTmuxBackend } from './claude-tmux';
|
|
4
|
+
export declare class ClaudeBackend implements Backend {
|
|
5
|
+
private readonly raw;
|
|
6
|
+
readonly cli: SessionCli;
|
|
7
|
+
readonly deadSessionPolicy: "prune";
|
|
8
|
+
constructor(raw: ClaudeTmuxBackend);
|
|
9
|
+
isChampionIdTaken(championId: string): Promise<boolean>;
|
|
10
|
+
create(options: BackendCreateOptions): Promise<BackendCreateResult>;
|
|
11
|
+
preSendStoreFields(_session: StoredSession, _sendTime: string): Partial<StoredSession>;
|
|
12
|
+
send(session: StoredSession, message: string): Promise<Partial<StoredSession>>;
|
|
13
|
+
onSendError(_session: StoredSession, _error: Error): Partial<StoredSession>;
|
|
14
|
+
status(session: StoredSession): Promise<BackendStatusResult>;
|
|
15
|
+
wait(session: StoredSession, timeoutMs: number, intervalMs: number): Promise<BackendWaitResult>;
|
|
16
|
+
exists(session: StoredSession): Promise<'alive' | 'dead' | 'unknown'>;
|
|
17
|
+
getLastMessages(session: StoredSession, count: number): Promise<string[]>;
|
|
18
|
+
getLogs(session: StoredSession): Promise<SessionTurn[]>;
|
|
19
|
+
kill(session: StoredSession): Promise<void>;
|
|
20
|
+
afterKill(_remainingActiveSessions: StoredSession[]): Promise<void>;
|
|
21
|
+
private sleep;
|
|
22
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClaudeBackend = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const promises_1 = require("node:fs/promises");
|
|
6
|
+
const champion_ids_1 = require("../champion-ids");
|
|
7
|
+
const claude_parser_1 = require("../transcript/claude-parser");
|
|
8
|
+
class ClaudeBackend {
|
|
9
|
+
raw;
|
|
10
|
+
cli = 'claude';
|
|
11
|
+
deadSessionPolicy = 'prune';
|
|
12
|
+
constructor(raw) {
|
|
13
|
+
this.raw = raw;
|
|
14
|
+
}
|
|
15
|
+
async isChampionIdTaken(championId) {
|
|
16
|
+
return (await this.raw.sessionExists((0, champion_ids_1.toTmuxSessionName)(championId))) === 'alive';
|
|
17
|
+
}
|
|
18
|
+
async create(options) {
|
|
19
|
+
const mode = options.mode ?? 'native';
|
|
20
|
+
const internalId = (0, node_crypto_1.randomUUID)();
|
|
21
|
+
const tmuxSessionName = (0, champion_ids_1.toTmuxSessionName)(options.championId);
|
|
22
|
+
await this.raw.createSession(tmuxSessionName, options.workspacePath, mode, internalId);
|
|
23
|
+
return { internalId, mode };
|
|
24
|
+
}
|
|
25
|
+
preSendStoreFields(_session, _sendTime) {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
async send(session, message) {
|
|
29
|
+
const tmuxSessionName = (0, champion_ids_1.toTmuxSessionName)(session.championId);
|
|
30
|
+
const sendTime = new Date().toISOString();
|
|
31
|
+
await this.raw.sendMessage(tmuxSessionName, message);
|
|
32
|
+
return {
|
|
33
|
+
lastUsed: sendTime,
|
|
34
|
+
status: 'active',
|
|
35
|
+
lastTurnStatus: undefined,
|
|
36
|
+
lastTurnError: undefined
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
onSendError(_session, _error) {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
async status(session) {
|
|
43
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
44
|
+
const transcriptEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
45
|
+
const status = (0, claude_parser_1.inferTranscriptStatus)(transcriptEntries);
|
|
46
|
+
return { status };
|
|
47
|
+
}
|
|
48
|
+
async wait(session, timeoutMs, intervalMs) {
|
|
49
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
50
|
+
const startTime = Date.now();
|
|
51
|
+
const deadline = startTime + timeoutMs;
|
|
52
|
+
const initialEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
53
|
+
const baselineAssistantCount = (0, claude_parser_1.countAssistantMessages)(initialEntries);
|
|
54
|
+
const baselineSystemCount = (0, claude_parser_1.countSystemEntries)(initialEntries);
|
|
55
|
+
const baselineFileHistoryCount = (0, claude_parser_1.countFileHistorySnapshots)(initialEntries);
|
|
56
|
+
let lastMtimeMs = -1;
|
|
57
|
+
let shouldReadTranscript = false;
|
|
58
|
+
let cachedEntries = initialEntries;
|
|
59
|
+
while (Date.now() <= deadline) {
|
|
60
|
+
try {
|
|
61
|
+
const fileStat = await (0, promises_1.stat)(transcriptPath);
|
|
62
|
+
if (fileStat.mtimeMs !== lastMtimeMs) {
|
|
63
|
+
lastMtimeMs = fileStat.mtimeMs;
|
|
64
|
+
shouldReadTranscript = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error.code !== 'ENOENT') {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
shouldReadTranscript = true;
|
|
72
|
+
cachedEntries = [];
|
|
73
|
+
}
|
|
74
|
+
if (shouldReadTranscript) {
|
|
75
|
+
cachedEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
76
|
+
shouldReadTranscript = false;
|
|
77
|
+
}
|
|
78
|
+
const hasNewAssistant = (0, claude_parser_1.countAssistantMessages)(cachedEntries) > baselineAssistantCount;
|
|
79
|
+
const hasNewSystemEntry = (0, claude_parser_1.countSystemEntries)(cachedEntries) > baselineSystemCount;
|
|
80
|
+
const hasNewFileHistorySnapshot = (0, claude_parser_1.countFileHistorySnapshots)(cachedEntries) > baselineFileHistoryCount;
|
|
81
|
+
// A system entry followed by a new assistant message is the primary completion signal.
|
|
82
|
+
if (hasNewSystemEntry && hasNewAssistant) {
|
|
83
|
+
return {
|
|
84
|
+
completed: true,
|
|
85
|
+
timedOut: false,
|
|
86
|
+
elapsedMs: Date.now() - startTime,
|
|
87
|
+
storeUpdate: { lastUsed: new Date().toISOString() }
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// For turns that end without a system entry (e.g. long tool runs), Claude writes a
|
|
91
|
+
// file-history-snapshot at turn completion. Use that as the fallback signal.
|
|
92
|
+
if (hasNewFileHistorySnapshot && hasNewAssistant) {
|
|
93
|
+
return {
|
|
94
|
+
completed: true,
|
|
95
|
+
timedOut: false,
|
|
96
|
+
elapsedMs: Date.now() - startTime,
|
|
97
|
+
storeUpdate: { lastUsed: new Date().toISOString() }
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
await this.sleep(intervalMs);
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
completed: false,
|
|
104
|
+
timedOut: true,
|
|
105
|
+
elapsedMs: Date.now() - startTime,
|
|
106
|
+
storeUpdate: {}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async exists(session) {
|
|
110
|
+
return this.raw.sessionExists((0, champion_ids_1.toTmuxSessionName)(session.championId));
|
|
111
|
+
}
|
|
112
|
+
async getLastMessages(session, count) {
|
|
113
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
114
|
+
const transcriptEntries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
115
|
+
const blocks = (0, claude_parser_1.getAssistantTextBlocks)(transcriptEntries);
|
|
116
|
+
return blocks.slice(-Math.max(1, count));
|
|
117
|
+
}
|
|
118
|
+
async getLogs(session) {
|
|
119
|
+
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(session.path, session.internalId);
|
|
120
|
+
const entries = await (0, claude_parser_1.readClaudeTranscript)(transcriptPath);
|
|
121
|
+
const turns = [];
|
|
122
|
+
for (const entry of entries) {
|
|
123
|
+
const type = entry.type?.toLowerCase();
|
|
124
|
+
if (type === 'human' || type === 'user') {
|
|
125
|
+
const text = (0, claude_parser_1.extractTextBlocks)(entry.message?.content).join('\n\n');
|
|
126
|
+
if (text) {
|
|
127
|
+
turns.push({ role: 'human', text });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (type === 'assistant') {
|
|
131
|
+
const text = (0, claude_parser_1.extractTextBlocks)(entry.message?.content).join('\n\n');
|
|
132
|
+
if (text) {
|
|
133
|
+
turns.push({ role: 'assistant', text });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return turns;
|
|
138
|
+
}
|
|
139
|
+
async kill(session) {
|
|
140
|
+
const tmuxSessionName = (0, champion_ids_1.toTmuxSessionName)(session.championId);
|
|
141
|
+
try {
|
|
142
|
+
await this.raw.killSession(tmuxSessionName);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (!(error instanceof Error) ||
|
|
146
|
+
!/failed to connect server|no server running|can't find session/i.test(error.message)) {
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async afterKill(_remainingActiveSessions) {
|
|
152
|
+
// No post-kill cleanup needed for Claude
|
|
153
|
+
}
|
|
154
|
+
async sleep(ms) {
|
|
155
|
+
await new Promise((resolve) => {
|
|
156
|
+
setTimeout(resolve, ms);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
exports.ClaudeBackend = ClaudeBackend;
|
|
161
|
+
//# sourceMappingURL=claude-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-backend.js","sourceRoot":"","sources":["../../src/backends/claude-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,10 +4,8 @@ export declare class ClaudeTmuxBackend {
|
|
|
4
4
|
constructor(timeoutMs?: number);
|
|
5
5
|
createSession(tmuxSessionName: string, workspacePath: string, mode: SessionMode, sessionUuid: string): Promise<void>;
|
|
6
6
|
sendMessage(tmuxSessionName: string, message: string): Promise<void>;
|
|
7
|
-
submitInput(tmuxSessionName: string): Promise<void>;
|
|
8
7
|
killSession(tmuxSessionName: string): Promise<void>;
|
|
9
|
-
|
|
10
|
-
sessionExists(tmuxSessionName: string): Promise<boolean>;
|
|
8
|
+
sessionExists(tmuxSessionName: string): Promise<'alive' | 'dead' | 'unknown'>;
|
|
11
9
|
isClaudeRunning(tmuxSessionName: string): Promise<boolean>;
|
|
12
10
|
isCliRunning(tmuxSessionName: string, commandPatterns?: RegExp[]): Promise<boolean>;
|
|
13
11
|
private getPaneCommands;
|
|
@@ -69,34 +69,20 @@ class ClaudeTmuxBackend {
|
|
|
69
69
|
await this.sleep(150);
|
|
70
70
|
await this.execTmux(['send-keys', '-t', tmuxSessionName, 'C-m']);
|
|
71
71
|
}
|
|
72
|
-
async submitInput(tmuxSessionName) {
|
|
73
|
-
if (!(await this.isClaudeRunning(tmuxSessionName))) {
|
|
74
|
-
throw new Error('Claude is not running in this tmux session - refusing to submit input');
|
|
75
|
-
}
|
|
76
|
-
await this.execTmux(['send-keys', '-t', tmuxSessionName, 'C-m']);
|
|
77
|
-
}
|
|
78
72
|
async killSession(tmuxSessionName) {
|
|
79
73
|
await this.execTmux(['kill-session', '-t', tmuxSessionName]);
|
|
80
74
|
}
|
|
81
|
-
async listSessions() {
|
|
82
|
-
try {
|
|
83
|
-
const output = await this.execTmux(['list-sessions', '-F', '#{session_name}']);
|
|
84
|
-
return output
|
|
85
|
-
.split('\n')
|
|
86
|
-
.map((line) => line.trim())
|
|
87
|
-
.filter((line) => line.length > 0);
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return [];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
75
|
async sessionExists(tmuxSessionName) {
|
|
94
76
|
try {
|
|
95
77
|
await this.execTmux(['has-session', '-t', tmuxSessionName]);
|
|
96
|
-
return
|
|
78
|
+
return 'alive';
|
|
97
79
|
}
|
|
98
|
-
catch {
|
|
99
|
-
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error instanceof Error &&
|
|
82
|
+
/can't find session|session not found/i.test(error.message)) {
|
|
83
|
+
return 'dead';
|
|
84
|
+
}
|
|
85
|
+
return 'unknown';
|
|
100
86
|
}
|
|
101
87
|
}
|
|
102
88
|
async isClaudeRunning(tmuxSessionName) {
|
|
@@ -150,20 +136,25 @@ class ClaudeTmuxBackend {
|
|
|
150
136
|
buildStartupCommand(workspacePath, mode, sessionUuid) {
|
|
151
137
|
const binary = mode === 'docker' ? 'clauded' : 'claude';
|
|
152
138
|
const commandParts = [`${binary} --session-id ${shellEscape(sessionUuid)}`];
|
|
153
|
-
if (mode === '
|
|
139
|
+
if (mode === 'native') {
|
|
154
140
|
commandParts.push('--dangerously-skip-permissions');
|
|
155
141
|
}
|
|
156
142
|
return `cd ${shellEscape(workspacePath)} && ${commandParts.join(' ')}`;
|
|
157
143
|
}
|
|
158
144
|
async waitForTranscriptReady(workspacePath, sessionUuid, pollIntervalMs = 200) {
|
|
159
145
|
const transcriptPath = (0, claude_parser_1.getClaudeTranscriptPath)(workspacePath, sessionUuid);
|
|
160
|
-
const
|
|
146
|
+
const timeoutOverride = parseInt(process.env['DEV_SESSIONS_TRANSCRIPT_TIMEOUT_MS'] ?? '');
|
|
147
|
+
const timeoutMs = Number.isFinite(timeoutOverride) && timeoutOverride >= 0 ? timeoutOverride : this.timeoutMs;
|
|
148
|
+
const deadline = Date.now() + timeoutMs;
|
|
161
149
|
while (Date.now() < deadline) {
|
|
162
150
|
try {
|
|
163
151
|
await (0, promises_1.access)(transcriptPath);
|
|
164
152
|
return;
|
|
165
153
|
}
|
|
166
|
-
catch {
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (error.code !== 'ENOENT') {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
167
158
|
// File not yet created; keep polling.
|
|
168
159
|
}
|
|
169
160
|
await this.sleep(pollIntervalMs);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-tmux.js","sourceRoot":"","sources":["../../src/backends/claude-tmux.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"claude-tmux.js","sourceRoot":"","sources":["../../src/backends/claude-tmux.ts"],"names":[],"mappings":"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"}
|