remcodex 0.1.0-beta.1 β 0.1.0-beta.10
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 +225 -240
- package/dist/server/src/app.js +3 -1
- package/dist/server/src/cli.js +4 -3
- package/dist/server/src/controllers/session.controller.js +12 -0
- package/dist/server/src/services/codex-rollout-sync.js +5 -16
- package/dist/server/src/services/event-store.js +28 -5
- package/dist/server/src/services/session-manager.js +79 -6
- package/dist/server/src/services/session-timeline-service.js +7 -169
- package/dist/server/src/utils/output-limits.js +73 -0
- package/package.json +1 -1
- package/web/api.js +7 -0
- package/web/app.js +241 -37
- package/web/i18n/locales/en.js +3 -2
- package/web/i18n/locales/zh-CN.js +3 -2
- package/web/session-timeline-reducer.js +66 -13
- package/web/styles.css +22 -0
package/README.md
CHANGED
|
@@ -1,81 +1,104 @@
|
|
|
1
|
-
# RemCodex
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
# π RemCodex
|
|
2
|
+
|
|
3
|
+
> Remote control for Codex.
|
|
4
|
+
> From your browser and phone.
|
|
5
|
+
|
|
6
|
+
Run Codex on one machine.
|
|
7
|
+
Monitor, approve, and control the same session from another.
|
|
8
|
+
|
|
9
|
+
π https://remcodex.com
|
|
10
|
+
|
|
11
|
+
> Not a remote desktop. Not a proxy.
|
|
12
|
+
> A local-first way to control Codex away from the terminal.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## β¨ What is RemCodex?
|
|
19
|
+
|
|
20
|
+
RemCodex is **remote control for Codex**.
|
|
21
|
+
|
|
22
|
+
It lets you start Codex on one machine, then keep the same session visible,
|
|
23
|
+
interruptible, and controllable from another.
|
|
24
|
+
|
|
25
|
+
- π See what the AI is doing β in real time
|
|
26
|
+
- β
Approve or reject actions before execution
|
|
27
|
+
- βΉ Interrupt or stop at any moment
|
|
28
|
+
- π± Access your session from any device
|
|
29
|
+
- π Sessions donβt break β they resume
|
|
30
|
+
|
|
31
|
+
> One session. Any device.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## π¬ A real workflow
|
|
36
|
+
|
|
37
|
+
You start a long Codex session on your machine.
|
|
38
|
+
|
|
39
|
+
Then you leave your desk.
|
|
40
|
+
|
|
41
|
+
On your phone:
|
|
42
|
+
|
|
43
|
+
- you see progress in real time
|
|
44
|
+
- you receive an approval request
|
|
45
|
+
- you approve it
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
- Approve sensitive actions from a cleaner UI
|
|
43
|
-
- Pick up the same session again after refresh, sleep, or reconnect
|
|
47
|
+
The session continues instantly.
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
> Everything else can disconnect β your session wonβt.
|
|
46
50
|
|
|
47
|
-
|
|
51
|
+
---
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
## π₯ Why RemCodex exists
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
AI coding agents are powerful.
|
|
56
|
+
But today, they run like a black box.
|
|
52
57
|
|
|
53
|
-
|
|
58
|
+
You either:
|
|
54
59
|
|
|
55
|
-
|
|
60
|
+
- trust everything blindly
|
|
61
|
+
- or sit in front of your terminal watching it
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
RemCodex fixes that.
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
- watching a long run without babysitting a terminal window
|
|
61
|
-
- approving writes from a cleaner interface
|
|
62
|
-
- reopening a session after refresh, sleep, or reconnect
|
|
63
|
-
- reviewing imported rollout history next to native sessions
|
|
65
|
+
> AI is no longer a black box.
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
---
|
|
66
68
|
|
|
67
|
-
## What
|
|
69
|
+
## β‘ What it does
|
|
68
70
|
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
- Resume stale sessions after the page comes back from background
|
|
76
|
-
- Work well on desktop and on mobile
|
|
71
|
+
- Real-time execution timeline (messages, commands, approvals)
|
|
72
|
+
- Human-in-the-loop command approval
|
|
73
|
+
- Multi-device access to the same live session
|
|
74
|
+
- Resume after refresh, sleep, or reconnect
|
|
75
|
+
- Browser-based UI β **no extra client required**
|
|
76
|
+
- Works with Codex CLI
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
> No extra client install. Just open a browser.
|
|
79
|
+
> Your code never leaves your machine.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## π Quick start
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx remcodex
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Then open:
|
|
90
|
+
|
|
91
|
+
http://127.0.0.1:18840
|
|
92
|
+
|
|
93
|
+
Access from another device:
|
|
94
|
+
|
|
95
|
+
http://<your-ip>:18840
|
|
96
|
+
|
|
97
|
+
> Runs entirely on your local machine. No cloud, no data upload.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## π₯ Screenshots
|
|
79
102
|
|
|
80
103
|

|
|
81
104
|
|
|
@@ -91,241 +114,203 @@ RemCodex turns Codex's event stream into a browser-based workspace that is easie
|
|
|
91
114
|
|
|
92
115
|

|
|
93
116
|
|
|
94
|
-
> Bring imported Codex rollouts into the same workspace
|
|
117
|
+
> Bring imported Codex rollouts into the same workspace.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## π§ What it actually is
|
|
122
|
+
|
|
123
|
+
RemCodex is a **browser-based workspace for Codex sessions**.
|
|
95
124
|
|
|
96
|
-
|
|
125
|
+
It is built for real workflows:
|
|
97
126
|
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
127
|
+
- long-running sessions
|
|
128
|
+
- mobile check-ins
|
|
129
|
+
- approval prompts
|
|
130
|
+
- imported rollout history
|
|
131
|
+
- timeline-style execution flow
|
|
102
132
|
|
|
103
|
-
|
|
133
|
+
Instead of raw terminal logs, you get a structured, visual timeline you can follow and control.
|
|
104
134
|
|
|
105
|
-
|
|
106
|
-
- ad-hoc mobile remote desktop checks
|
|
107
|
-
- raw log scrolling for approvals and command progress
|
|
108
|
-
- fragmented session history between local and imported rollouts
|
|
135
|
+
---
|
|
109
136
|
|
|
110
|
-
## Current
|
|
137
|
+
## π§© Current product shape
|
|
111
138
|
|
|
112
139
|
- Single-page workspace UI
|
|
113
140
|
- Left sidebar for session navigation
|
|
114
|
-
- Right-side
|
|
115
|
-
- Fixed composer
|
|
141
|
+
- Right-side execution timeline
|
|
142
|
+
- Fixed input composer
|
|
116
143
|
- Semantic timeline rendering for:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
144
|
+
- user messages
|
|
145
|
+
- assistant output
|
|
146
|
+
- thinking
|
|
147
|
+
- commands
|
|
148
|
+
- patches
|
|
149
|
+
- approvals
|
|
150
|
+
- system events
|
|
124
151
|
|
|
125
|
-
|
|
152
|
+
---
|
|
126
153
|
|
|
127
|
-
|
|
128
|
-
- Database: SQLite via `better-sqlite3`
|
|
129
|
-
- Terminal/runtime integration: `node-pty` + Codex app-server
|
|
130
|
-
- Frontend: zero-build static web app (`web/`)
|
|
131
|
-
- Markdown rendering: `markdown-it`
|
|
154
|
+
## βοΈ Key behaviors
|
|
132
155
|
|
|
133
|
-
|
|
156
|
+
### Approvals
|
|
134
157
|
|
|
135
|
-
|
|
158
|
+
- Writes inside working area β auto allowed
|
|
159
|
+
- Writes outside β require approval
|
|
160
|
+
- `Allow once` / `Allow for this turn` supported
|
|
161
|
+
- Approval history stays visible in timeline
|
|
136
162
|
|
|
137
|
-
|
|
138
|
-
- Codex CLI installed and already working locally
|
|
139
|
-
- A machine where this app can access your local Codex data and working directories
|
|
163
|
+
---
|
|
140
164
|
|
|
141
|
-
|
|
165
|
+
### Timeline
|
|
142
166
|
|
|
143
|
-
|
|
167
|
+
- Semantic rendering (not raw logs)
|
|
168
|
+
- Commands grouped into readable activity blocks
|
|
169
|
+
- Running / failed states clearly visible
|
|
170
|
+
- Smooth streaming + recovery after refresh
|
|
144
171
|
|
|
145
|
-
|
|
172
|
+
---
|
|
146
173
|
|
|
147
|
-
|
|
148
|
-
npm install
|
|
149
|
-
npm run build
|
|
150
|
-
npm link
|
|
151
|
-
remcodex start
|
|
152
|
-
```
|
|
174
|
+
### Imported sessions
|
|
153
175
|
|
|
154
|
-
|
|
176
|
+
- Import from `~/.codex/sessions/...`
|
|
177
|
+
- Keep syncing if still active
|
|
178
|
+
- Unified view with native sessions
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## π§ Architecture
|
|
155
183
|
|
|
156
|
-
```
|
|
157
|
-
|
|
184
|
+
```
|
|
185
|
+
Codex CLI β Event stream β Semantic layer β Timeline β Web UI
|
|
158
186
|
```
|
|
159
187
|
|
|
160
|
-
|
|
188
|
+
---
|
|
161
189
|
|
|
162
|
-
##
|
|
190
|
+
## βοΈ Requirements
|
|
163
191
|
|
|
164
|
-
|
|
192
|
+
- Node.js
|
|
193
|
+
- Codex CLI (already working locally)
|
|
165
194
|
|
|
166
|
-
|
|
195
|
+
---
|
|
167
196
|
|
|
168
|
-
|
|
169
|
-
node dist/server/src/cli.js start --no-open
|
|
170
|
-
```
|
|
197
|
+
## βοΈ Configuration
|
|
171
198
|
|
|
172
|
-
|
|
199
|
+
Default port: **18840**
|
|
173
200
|
|
|
174
201
|
```bash
|
|
175
|
-
|
|
176
|
-
node dist/server/src/cli.js start --no-open
|
|
177
|
-
node dist/server/src/cli.js version
|
|
202
|
+
PORT=18841 npx remcodex
|
|
178
203
|
```
|
|
179
204
|
|
|
180
|
-
|
|
205
|
+
---
|
|
181
206
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
207
|
+
## π¦ Install FAQ
|
|
208
|
+
|
|
209
|
+
### Why does `npx remcodex` hang on Linux?
|
|
210
|
+
|
|
211
|
+
First install may compile native deps:
|
|
212
|
+
|
|
213
|
+
- `better-sqlite3`
|
|
214
|
+
- `node-pty`
|
|
215
|
+
|
|
216
|
+
Make sure you have:
|
|
217
|
+
|
|
218
|
+
- `python3`
|
|
219
|
+
- `make`
|
|
220
|
+
- `g++`
|
|
186
221
|
|
|
187
|
-
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### Debug install issues
|
|
188
225
|
|
|
189
226
|
```bash
|
|
190
|
-
|
|
227
|
+
npm install -g remcodex
|
|
228
|
+
remcodex doctor
|
|
229
|
+
remcodex start
|
|
191
230
|
```
|
|
192
231
|
|
|
193
|
-
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### Headless mode
|
|
194
235
|
|
|
195
236
|
```bash
|
|
196
|
-
|
|
197
|
-
npm run dev
|
|
237
|
+
npx remcodex --no-open
|
|
198
238
|
```
|
|
199
239
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
The app uses `codex app-server` as the primary runtime path.
|
|
240
|
+
---
|
|
203
241
|
|
|
204
|
-
|
|
242
|
+
## π§ How it works
|
|
205
243
|
|
|
206
|
-
1. Codex emits
|
|
207
|
-
2.
|
|
208
|
-
3.
|
|
209
|
-
4. Live updates
|
|
244
|
+
1. Codex emits events
|
|
245
|
+
2. Backend stores them (SQLite)
|
|
246
|
+
3. Frontend loads timeline snapshot
|
|
247
|
+
4. Live updates stream via WebSocket
|
|
210
248
|
|
|
211
|
-
|
|
249
|
+
Result:
|
|
212
250
|
|
|
213
|
-
- smooth streaming
|
|
214
251
|
- recoverable sessions
|
|
215
|
-
-
|
|
216
|
-
-
|
|
252
|
+
- real-time UI
|
|
253
|
+
- consistent execution flow
|
|
217
254
|
|
|
218
|
-
|
|
255
|
+
---
|
|
219
256
|
|
|
220
|
-
|
|
257
|
+
## π Status
|
|
221
258
|
|
|
222
|
-
-
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
- `Allow for this turn` expands writable roots for the active turn
|
|
226
|
-
- Historical approval records stay visible in the timeline
|
|
227
|
-
- Only live approvals stay actionable in the bottom approval bar
|
|
228
|
-
|
|
229
|
-
### Imported Codex Sessions
|
|
230
|
-
|
|
231
|
-
- Existing Codex rollouts can be imported from local session history
|
|
232
|
-
- Imported sessions keep their own source metadata
|
|
233
|
-
- Imported sessions can continue syncing after you open them
|
|
234
|
-
- Native sessions are excluded from the import picker
|
|
235
|
-
|
|
236
|
-
### Timeline and Execution Flow
|
|
237
|
-
|
|
238
|
-
- The UI renders semantic timeline items, not raw logs
|
|
239
|
-
- Commands and patches can be grouped into lighter activity summaries
|
|
240
|
-
- Running and failed commands remain visually important
|
|
241
|
-
- The final thinking placeholder appears only at the end of the active flow
|
|
242
|
-
|
|
243
|
-
## Configuration
|
|
244
|
-
|
|
245
|
-
Supported environment variables:
|
|
246
|
-
|
|
247
|
-
- `PORT`
|
|
248
|
-
- `DATABASE_PATH`
|
|
249
|
-
- `PROJECT_ROOTS`
|
|
250
|
-
- `CODEX_COMMAND`
|
|
251
|
-
- `CODEX_MODE`
|
|
252
|
-
- `REMOTE_HOSTS`
|
|
253
|
-
- `ACTIVE_REMOTE_HOST`
|
|
254
|
-
|
|
255
|
-
Notes:
|
|
256
|
-
|
|
257
|
-
- The default runtime mode is `app-server`
|
|
258
|
-
- `exec-json` is kept only as a fallback compatibility path
|
|
259
|
-
- If `PROJECT_ROOTS` is not set, the app falls back to a broad local browsing root
|
|
260
|
-
|
|
261
|
-
## Project Structure
|
|
262
|
-
|
|
263
|
-
```text
|
|
264
|
-
server/
|
|
265
|
-
src/
|
|
266
|
-
app.ts
|
|
267
|
-
controllers/
|
|
268
|
-
db/
|
|
269
|
-
gateways/
|
|
270
|
-
services/
|
|
271
|
-
types/
|
|
272
|
-
utils/
|
|
273
|
-
web/
|
|
274
|
-
index.html
|
|
275
|
-
styles.css
|
|
276
|
-
api.js
|
|
277
|
-
session-ws.js
|
|
278
|
-
app.js
|
|
279
|
-
scripts/
|
|
280
|
-
fix-node-pty-helper.js
|
|
281
|
-
```
|
|
259
|
+
- Beta / developer preview
|
|
260
|
+
- Local-first architecture
|
|
261
|
+
- No cloud dependency
|
|
282
262
|
|
|
283
|
-
|
|
263
|
+
---
|
|
284
264
|
|
|
285
|
-
|
|
286
|
-
- `GET /api/codex/mode`
|
|
287
|
-
- `GET /api/codex/status`
|
|
288
|
-
- `GET /api/codex/quota`
|
|
289
|
-
- `GET /api/sessions`
|
|
290
|
-
- `GET /api/sessions/:sessionId`
|
|
291
|
-
- `GET /api/sessions/:sessionId/timeline`
|
|
292
|
-
- `GET /api/sessions/:sessionId/events`
|
|
293
|
-
- `POST /api/sessions`
|
|
294
|
-
- `POST /api/sessions/:sessionId/messages`
|
|
295
|
-
- `POST /api/sessions/:sessionId/stop`
|
|
296
|
-
- `POST /api/sessions/:sessionId/approvals/:requestId`
|
|
297
|
-
- `WS /ws/sessions/:sessionId`
|
|
265
|
+
## πΊ Roadmap
|
|
298
266
|
|
|
299
|
-
|
|
267
|
+
**Visibility**
|
|
300
268
|
|
|
301
|
-
|
|
269
|
+
- fully observable execution
|
|
270
|
+
- clear action timeline
|
|
302
271
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
-
|
|
306
|
-
-
|
|
307
|
-
- no release pipeline yet
|
|
272
|
+
**Control**
|
|
273
|
+
|
|
274
|
+
- fine-grained approvals
|
|
275
|
+
- safer execution
|
|
308
276
|
|
|
309
|
-
|
|
277
|
+
**Continuity**
|
|
310
278
|
|
|
311
|
-
|
|
279
|
+
- survive refresh / sleep
|
|
280
|
+
- stable long runs
|
|
312
281
|
|
|
313
|
-
|
|
282
|
+
**Access**
|
|
314
283
|
|
|
315
|
-
-
|
|
316
|
-
- ship a cleaner public README and screenshots
|
|
317
|
-
- add stronger regression coverage
|
|
318
|
-
- harden long-running session recovery
|
|
319
|
-
- continue refining the execution timeline UI
|
|
284
|
+
- control from any device
|
|
320
285
|
|
|
321
|
-
|
|
286
|
+
**Integration**
|
|
287
|
+
|
|
288
|
+
- IDE integrations
|
|
289
|
+
- optional sharing
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## π₯ Who itβs for
|
|
294
|
+
|
|
295
|
+
- developers already using Codex
|
|
296
|
+
- people tired of terminal-only workflows
|
|
297
|
+
- anyone who wants **control, not just output**
|
|
298
|
+
- multi-device workflows
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## β οΈ Whatβs not finished yet
|
|
303
|
+
|
|
304
|
+
- no polished installer yet
|
|
305
|
+
- no desktop packaging
|
|
306
|
+
- no production-grade auth
|
|
307
|
+
- no release pipeline
|
|
322
308
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
- stronger sharing, auditing, and team workflows
|
|
309
|
+
If you're comfortable running a local Node app β
|
|
310
|
+
you can use it today.
|
|
326
311
|
|
|
327
|
-
|
|
312
|
+
---
|
|
328
313
|
|
|
329
|
-
|
|
314
|
+
## π License
|
|
330
315
|
|
|
331
|
-
|
|
316
|
+
MIT License
|
package/dist/server/src/app.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DEFAULT_PORT = void 0;
|
|
6
7
|
exports.resolvePackageRoot = resolvePackageRoot;
|
|
7
8
|
exports.resolveDefaultDatabasePath = resolveDefaultDatabasePath;
|
|
8
9
|
exports.startRemCodexServer = startRemCodexServer;
|
|
@@ -46,9 +47,10 @@ function resolvePackageRoot(startDir = __dirname) {
|
|
|
46
47
|
function resolveDefaultDatabasePath() {
|
|
47
48
|
return node_path_1.default.join((0, node_os_1.homedir)(), ".remcodex", "remcodex.db");
|
|
48
49
|
}
|
|
50
|
+
exports.DEFAULT_PORT = 18840;
|
|
49
51
|
function buildRemCodexServer(options = {}) {
|
|
50
52
|
const repoRoot = options.repoRoot ? node_path_1.default.resolve(options.repoRoot) : resolvePackageRoot();
|
|
51
|
-
const port = options.port ?? Number.parseInt(process.env.PORT ??
|
|
53
|
+
const port = options.port ?? Number.parseInt(process.env.PORT ?? String(exports.DEFAULT_PORT), 10);
|
|
52
54
|
const databasePath = options.databasePath ??
|
|
53
55
|
process.env.DATABASE_PATH ??
|
|
54
56
|
resolveDefaultDatabasePath();
|
package/dist/server/src/cli.js
CHANGED
|
@@ -169,7 +169,7 @@ async function runStart(flags) {
|
|
|
169
169
|
printError("Install Codex first, or set CODEX_COMMAND to the correct executable.");
|
|
170
170
|
return 1;
|
|
171
171
|
}
|
|
172
|
-
const preferredPort = flags.port ?? Number.parseInt(process.env.PORT ??
|
|
172
|
+
const preferredPort = flags.port ?? Number.parseInt(process.env.PORT ?? String(app_1.DEFAULT_PORT), 10);
|
|
173
173
|
const codexMode = process.env.CODEX_MODE === "exec-json" ? "exec-json" : "app-server";
|
|
174
174
|
let started = null;
|
|
175
175
|
let activePort = preferredPort;
|
|
@@ -242,8 +242,9 @@ async function main() {
|
|
|
242
242
|
usage();
|
|
243
243
|
return;
|
|
244
244
|
}
|
|
245
|
-
const
|
|
246
|
-
const
|
|
245
|
+
const hasExplicitCommand = Boolean(argv[0] && !argv[0].startsWith("-"));
|
|
246
|
+
const command = hasExplicitCommand ? argv[0] : "start";
|
|
247
|
+
const flagArgs = hasExplicitCommand ? argv.slice(1) : argv;
|
|
247
248
|
const flags = parseFlags(flagArgs);
|
|
248
249
|
switch (command) {
|
|
249
250
|
case "start":
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createSessionRouter = createSessionRouter;
|
|
4
4
|
const express_1 = require("express");
|
|
5
|
+
const codex_launch_1 = require("../utils/codex-launch");
|
|
5
6
|
function createSessionRouter(sessionManager, eventStore, projectManager, codexRolloutSync, sessionTimeline) {
|
|
6
7
|
const router = (0, express_1.Router)();
|
|
7
8
|
router.get("/", (_request, response) => {
|
|
@@ -171,5 +172,16 @@ function createSessionRouter(sessionManager, eventStore, projectManager, codexRo
|
|
|
171
172
|
next(error);
|
|
172
173
|
}
|
|
173
174
|
});
|
|
175
|
+
router.post("/:sessionId/approvals/:requestId/retry", (request, response, next) => {
|
|
176
|
+
try {
|
|
177
|
+
const body = request.body;
|
|
178
|
+
const launch = (0, codex_launch_1.normalizeCodexExecLaunchInput)(body.codex);
|
|
179
|
+
const result = sessionManager.retryApprovalRequest(request.params.sessionId, request.params.requestId, launch);
|
|
180
|
+
response.json(result);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
next(error);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
174
186
|
return router;
|
|
175
187
|
}
|
|
@@ -9,6 +9,7 @@ const node_os_1 = __importDefault(require("node:os"));
|
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const errors_1 = require("../utils/errors");
|
|
11
11
|
const ids_1 = require("../utils/ids");
|
|
12
|
+
const output_limits_1 = require("../utils/output-limits");
|
|
12
13
|
function computeSourceRolloutHasOpenTurnFromRecords(records) {
|
|
13
14
|
const openTurnIds = new Set();
|
|
14
15
|
for (const record of records) {
|
|
@@ -571,22 +572,7 @@ function translateRolloutRecords(records, emitFromRecordIndex = 0) {
|
|
|
571
572
|
: `call_${index}`;
|
|
572
573
|
const started = commandStarts.get(callId) || null;
|
|
573
574
|
const parsed = parseExecOutput(payload.output);
|
|
574
|
-
|
|
575
|
-
appendSemantic(index, {
|
|
576
|
-
type: "command.output.delta",
|
|
577
|
-
turnId: currentTurnId,
|
|
578
|
-
messageId: null,
|
|
579
|
-
callId,
|
|
580
|
-
requestId: null,
|
|
581
|
-
phase: null,
|
|
582
|
-
stream: "stdout",
|
|
583
|
-
payload: {
|
|
584
|
-
stream: "stdout",
|
|
585
|
-
textDelta: parsed.outputText,
|
|
586
|
-
},
|
|
587
|
-
timestamp,
|
|
588
|
-
});
|
|
589
|
-
}
|
|
575
|
+
const cappedOutput = parsed.outputText ? (0, output_limits_1.capTextValue)(parsed.outputText) : null;
|
|
590
576
|
appendSemantic(index, {
|
|
591
577
|
type: "command.end",
|
|
592
578
|
turnId: currentTurnId,
|
|
@@ -598,6 +584,9 @@ function translateRolloutRecords(records, emitFromRecordIndex = 0) {
|
|
|
598
584
|
payload: {
|
|
599
585
|
command: parsed.commandLine || started?.commandPayload.command || null,
|
|
600
586
|
cwd: started?.commandPayload.cwd || null,
|
|
587
|
+
stdout: cappedOutput?.text || null,
|
|
588
|
+
aggregatedOutput: cappedOutput?.text || null,
|
|
589
|
+
stdoutTruncated: cappedOutput?.truncated || undefined,
|
|
601
590
|
status: parsed.exitCode == null
|
|
602
591
|
? "completed"
|
|
603
592
|
: parsed.exitCode === 0
|