remcodex 0.1.0-beta.6 → 0.1.0-beta.8

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.
@@ -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
  }
@@ -288,6 +288,30 @@ class SessionManager {
288
288
  runtime.runner.stop();
289
289
  return { accepted: true };
290
290
  }
291
+ retryApprovalRequest(sessionId, requestId, codexLaunch) {
292
+ const session = this.getSessionOrThrow(sessionId);
293
+ const project = this.options.projectManager.getProject(session.project_id);
294
+ if (!project) {
295
+ throw new errors_1.AppError(404, "Project not found for session.");
296
+ }
297
+ const currentRunner = this.runners.get(sessionId);
298
+ const busyStatuses = ["starting", "running", "stopping"];
299
+ if (currentRunner?.runner.isAlive() && busyStatuses.includes(session.status)) {
300
+ throw new errors_1.AppError(409, "Session already has an active task.");
301
+ }
302
+ const pending = this.pendingApprovals.get(sessionId)?.get(requestId) ??
303
+ this.restorePendingApprovalFromEvents(sessionId, requestId);
304
+ if (!pending) {
305
+ throw new errors_1.AppError(404, "Approval request not found.");
306
+ }
307
+ const turnId = (0, ids_1.createId)("turn");
308
+ const runtimePrompt = normalizeDemoPrompt(project.path, this.buildApprovalRetryRuntimePrompt(pending));
309
+ this.startRunner(sessionId, project.path, runtimePrompt, turnId, this.resolveResumeThreadId(session), codexLaunch);
310
+ return {
311
+ accepted: true,
312
+ turnId,
313
+ };
314
+ }
291
315
  resolveApproval(sessionId, requestId, decision) {
292
316
  const runtime = this.runners.get(sessionId);
293
317
  if (!runtime?.runner.isAlive()) {
@@ -1368,6 +1392,35 @@ class SessionManager {
1368
1392
  }
1369
1393
  return null;
1370
1394
  }
1395
+ buildApprovalRetryRuntimePrompt(approval) {
1396
+ const commandText = this.extractApprovalCommand(approval.method, approval.params);
1397
+ const reason = typeof approval.params.reason === "string" && approval.params.reason.trim()
1398
+ ? approval.params.reason.trim()
1399
+ : "";
1400
+ if (commandText) {
1401
+ return [
1402
+ "Re-run the exact operation that previously requested approval.",
1403
+ "Do not do extra exploration.",
1404
+ "As soon as the approval prompt appears again, stop and wait for the user decision.",
1405
+ "",
1406
+ commandText,
1407
+ ].join("\n");
1408
+ }
1409
+ if (reason) {
1410
+ return [
1411
+ "Re-run the exact step that previously requested approval.",
1412
+ "Do not do extra exploration.",
1413
+ "As soon as the approval prompt appears again, stop and wait for the user decision.",
1414
+ "",
1415
+ `Original approval reason: ${reason}`,
1416
+ ].join("\n");
1417
+ }
1418
+ return [
1419
+ "Re-run the exact step that previously requested approval.",
1420
+ "Do not do extra exploration.",
1421
+ "As soon as the approval prompt appears again, stop and wait for the user decision.",
1422
+ ].join("\n");
1423
+ }
1371
1424
  describeApprovalTitle(method) {
1372
1425
  if (method === "item/commandExecution/requestApproval" || method === "execCommandApproval") {
1373
1426
  return "Command execution requires approval";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remcodex",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.8",
4
4
  "description": "Control Codex from anywhere. Even on your phone.",
5
5
  "license": "MIT",
6
6
  "bin": {
package/web/styles.css CHANGED
@@ -1394,13 +1394,16 @@ button:hover {
1394
1394
 
1395
1395
  .approval-banner {
1396
1396
  display: grid;
1397
+ grid-template-rows: minmax(0, 1fr) auto;
1397
1398
  gap: 0.6rem;
1398
1399
  margin-bottom: 0.7rem;
1399
1400
  padding: 0.72rem 0.82rem;
1401
+ max-height: min(46dvh, 24rem);
1400
1402
  border-radius: 14px;
1401
1403
  border: 1px solid rgba(188, 90, 48, 0.16);
1402
1404
  background: rgba(255, 248, 238, 0.96);
1403
1405
  box-shadow: 0 6px 16px rgba(169, 77, 38, 0.06);
1406
+ overflow: hidden;
1404
1407
  }
1405
1408
 
1406
1409
  .approval-banner[aria-busy="true"] {
@@ -1411,6 +1414,14 @@ button:hover {
1411
1414
  .approval-banner-copy {
1412
1415
  display: grid;
1413
1416
  gap: 0.28rem;
1417
+ min-height: 0;
1418
+ overflow-y: auto;
1419
+ overflow-x: hidden;
1420
+ overscroll-behavior: contain;
1421
+ scrollbar-gutter: stable;
1422
+ -webkit-overflow-scrolling: touch;
1423
+ touch-action: pan-y;
1424
+ padding-right: 0.18rem;
1414
1425
  }
1415
1426
 
1416
1427
  .approval-banner-head {
@@ -1496,6 +1507,9 @@ button:hover {
1496
1507
  display: flex;
1497
1508
  gap: 0.55rem;
1498
1509
  flex-wrap: wrap;
1510
+ flex-shrink: 0;
1511
+ padding-top: 0.15rem;
1512
+ border-top: 1px solid rgba(188, 90, 48, 0.12);
1499
1513
  }
1500
1514
 
1501
1515
  .approval-banner-actions .primary-button,
@@ -5104,6 +5118,13 @@ button:hover {
5104
5118
  padding-right: env(safe-area-inset-right, 0px);
5105
5119
  }
5106
5120
 
5121
+ .composer-panel:has(#session-approval-slot .approval-banner) {
5122
+ max-height: calc(100dvh - env(safe-area-inset-top, 0px) - 3rem);
5123
+ overflow-y: auto;
5124
+ overscroll-behavior: contain;
5125
+ -webkit-overflow-scrolling: touch;
5126
+ }
5127
+
5107
5128
  .composer-dock {
5108
5129
  max-width: 100%;
5109
5130
  }
@@ -5112,6 +5133,7 @@ button:hover {
5112
5133
  gap: 0.45rem;
5113
5134
  margin-bottom: 0.45rem;
5114
5135
  padding: 0.56rem 0.62rem;
5136
+ max-height: min(40dvh, 18rem);
5115
5137
  }
5116
5138
  }
5117
5139