Skip to content

app-server resume does not preserve sandbox and approval settings #2

Description

@monkey-di

Description

When using the app-server backend, resumed threads do not inherit the current codex-full-auto, codex-sandbox-mode, or codex-approval-policy settings.

A newly started thread correctly receives:

{
  "approvalPolicy": "never",
  "sandbox": "danger-full-access"
}

However, thread/resume is sent without these fields. The resumed thread therefore uses its stored or default restricted permissions, which can disable network access and restrict filesystem and Git operations.

Configuration

(use-package codex
  :vc (:url "https://github.com/benthamite/codex")
  :custom
  (codex-terminal-backend 'app-server)
  (codex-sandbox-mode 'danger-full-access)
  (codex-full-auto t))

Steps to reproduce

  1. Start a new Codex session using the app-server backend.
  2. Confirm that the session has unrestricted permissions.
  3. Close or leave the session.
  4. Resume it using M-x codex-resume or /resume.
  5. Try an operation requiring network access or unrestricted filesystem and Git access.

Expected behavior

thread/resume should receive the same active configuration overrides as thread/start, including:

{
  "approvalPolicy": "never",
  "sandbox": "danger-full-access"
}

According to the Codex App Server documentation, thread/resume accepts the same configuration overrides supported by thread/start.

Actual behavior

codex--app-server-thread-start-params includes:

`((cwd . ,codex--buffer-directory)
  (model . ,codex-model)
  (approvalPolicy . ,(codex--app-server-approval-policy))
  (sandbox . ,(codex--app-server-sandbox-mode))
  (config . ,(codex--app-server-config)))

But codex--app-server-send-resume sends only:

`((path . ,(alist-get 'path thread))
  (threadId . ,(alist-get 'id thread))
  (cwd . ,codex--buffer-directory)
  (initialTurnsPage . ((limit . 100)
                       (sortDirection . "asc"))))

As a result, the configured sandbox and approval policy are lost during resume.

Versions tested

  • codex.el 0.4.0, commit 53c6e3fe21c1ff724b5807c6f225506ca71afff6
  • Current master, commit 36c893ec6f231f390bd1687efef2e0f8cfddd616

Proposed solution

Merge the non-empty thread/start configuration overrides into the parameters passed to thread/resume.

For example:

(defun codex--app-server-send-resume (method thread)
  "Resume or fork THREAD via METHOD and render its history."
  (let ((params
         `((path . ,(alist-get 'path thread))
           (threadId . ,(alist-get 'id thread))
           (cwd . ,codex--buffer-directory)
           (initialTurnsPage . ((limit . 100)
                                (sortDirection . "asc"))))))
    (dolist (setting (codex--app-server-thread-start-params))
      (when (cdr setting)
        (setf (alist-get (car setting) params)
              (cdr setting))))
    (codex--app-server-send-request
     method
     params
     (lambda (result error)
       (if error
           (codex--app-server-insert-status
            (format "Codex resume failed: %S" error))
         (codex--app-server-thread-started result t)
         (codex--app-server-render-resumed-history
          (alist-get 'data (alist-get 'initialTurnsPage result)))
         (codex--app-server-setup-thread-input))))))

Alternatively, a shared helper could build the common cwd, model, approval, sandbox, and config fields for thread/start, thread/resume, and possibly thread/fork.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions