Commit Graph

9 Commits

  • Removed experimental "command risk assessment" feature (#7799)
    This experimental feature received lukewarm reception during internal
    testing. Removing from the code base.
  • updating app server types to support execpoilcy amendment (#7747)
    also includes minor refactor merging `ApprovalDecision` with
    `CommandExecutionRequestAcceptSettings`
  • fix: remove serde(flatten) annotation for TurnError (#7499)
    The problem with using `serde(flatten)` on Turn status is that it
    conditionally serializes the `error` field, which is not the pattern we
    want in API v2 where all fields on an object should always be returned.
    
    ```
    #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
    #[serde(rename_all = "camelCase")]
    #[ts(export_to = "v2/")]
    pub struct Turn {
        pub id: String,
        /// Only populated on a `thread/resume` response.
        /// For all other responses and notifications returning a Turn,
        /// the items field will be an empty list.
        pub items: Vec<ThreadItem>,
        #[serde(flatten)]
        pub status: TurnStatus,
    }
    
    #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
    #[serde(tag = "status", rename_all = "camelCase")]
    #[ts(tag = "status", export_to = "v2/")]
    pub enum TurnStatus {
        Completed,
        Interrupted,
        Failed { error: TurnError },
        InProgress,
    }
    ```
    
    serializes to:
    ```
    {
      "id": "turn-123",
      "items": [],
      "status": "completed"
    }
    
    {
      "id": "turn-123",
      "items": [],
      "status": "failed",
      "error": {
        "message": "Tool timeout",
        "codexErrorInfo": null
      }
    }
    ```
    
    Instead we want:
    ```
    {
      "id": "turn-123",
      "items": [],
      "status": "completed",
      "error": null
    }
    
    {
      "id": "turn-123",
      "items": [],
      "status": "failed",
      "error": {
        "message": "Tool timeout",
        "codexErrorInfo": null
      }
    }
    ```
  • [app-server-test-client] add send-followup-v2 (#7271)
    Add a new endpoint that allows us to test multi-turn behavior.
    
    Tested with running:
    ```
    RUST_LOG=codex_app_server=debug CODEX_BIN=target/debug/codex \
          cargo run -p codex-app-server-test-client -- \
          send-follow-up-v2 "hello" "and now a follow-up question"
    ```
  • [app-server] feat: v2 apply_patch approval flow (#6760)
    This PR adds the API V2 version of the apply_patch approval flow, which
    centers around `ThreadItem::FileChange`.
    
    This PR wires the new RPC (`item/fileChange/requestApproval`, V2 only)
    and related events (`item/started`, `item/completed` for
    `ThreadItem::FileChange`, which are emitted in both V1 and V2) through
    the app-server
    protocol. The new approval RPC is only sent when the user initiates a
    turn with the new `turn/start` API so we don't break backwards
    compatibility with VSCE.
    
    Similar to https://github.com/openai/codex/pull/6758, the approach I
    took was to make as few changes to the Codex core as possible,
    leveraging existing `EventMsg` core events, and translating those in
    app-server. I did have to add a few additional fields to
    `EventMsg::PatchApplyBegin` and `EventMsg::PatchApplyEnd`, but those
    were fairly lightweight.
    
    However, the `EventMsg`s emitted by core are the following:
    ```
    1) Auto-approved (no request for approval)

    - EventMsg::PatchApplyBegin
    - EventMsg::PatchApplyEnd
    
    2) Approved by user
    - EventMsg::ApplyPatchApprovalRequest
    - EventMsg::PatchApplyBegin
    - EventMsg::PatchApplyEnd
    
    3) Declined by user
    - EventMsg::ApplyPatchApprovalRequest
    - EventMsg::PatchApplyBegin
    - EventMsg::PatchApplyEnd
    ```
    
    For a request triggering an approval, this would result in:
    ```
    item/fileChange/requestApproval
    item/started
    item/completed
    ```
    
    which is different from the `ThreadItem::CommandExecution` flow
    introduced in https://github.com/openai/codex/pull/6758, which does the
    below and is preferable:
    ```
    item/started
    item/commandExecution/requestApproval
    item/completed
    ```
    
    To fix this, we leverage `TurnSummaryStore` on codex_message_processor
    to store a little bit of state, allowing us to fire `item/started` and
    `item/fileChange/requestApproval` whenever we receive the underlying
    `EventMsg::ApplyPatchApprovalRequest`, and no-oping when we receive the
    `EventMsg::PatchApplyBegin` later.
    
    This is much less invasive than modifying the order of EventMsg within
    core (I tried).
    
    The resulting payloads:
    ```
    {
      "method": "item/started",
      "params": {
        "item": {
          "changes": [
            {
              "diff": "Hello from Codex!\n",
              "kind": "add",
              "path": "/Users/owen/repos/codex/codex-rs/APPROVAL_DEMO.txt"
            }
          ],
          "id": "call_Nxnwj7B3YXigfV6Mwh03d686",
          "status": "inProgress",
          "type": "fileChange"
        }
      }
    }
    ```
    
    ```
    {
      "id": 0,
      "method": "item/fileChange/requestApproval",
      "params": {
        "grantRoot": null,
        "itemId": "call_Nxnwj7B3YXigfV6Mwh03d686",
        "reason": null,
        "threadId": "019a9e11-8295-7883-a283-779e06502c6f",
        "turnId": "1"
      }
    }
    ```
    
    ```
    {
      "id": 0,
      "result": {
        "decision": "accept"
      }
    }
    ```
    
    ```
    {
      "method": "item/completed",
      "params": {
        "item": {
          "changes": [
            {
              "diff": "Hello from Codex!\n",
              "kind": "add",
              "path": "/Users/owen/repos/codex/codex-rs/APPROVAL_DEMO.txt"
            }
          ],
          "id": "call_Nxnwj7B3YXigfV6Mwh03d686",
          "status": "completed",
          "type": "fileChange"
        }
      }
    }
    ```
  • [app-server] introduce turn/completed v2 event (#6800)
    similar to logic in
    `codex/codex-rs/exec/src/event_processor_with_jsonl_output.rs`.
    translation of v1 -> v2 events:
    `codex/event/task_complete` -> `turn/completed`
    `codex/event/turn_aborted` -> `turn/completed` with `interrupted` status
    `codex/event/error` -> `turn/completed` with `error` status
    
    this PR also makes `items` field in `Turn` optional. For now, we only
    populate it when we resume a thread, and leave it as None for all other
    places until we properly rewrite core to keep track of items.
    
    tested using the codex app server client. example new event:
    ```
    < {
    <   "method": "turn/completed",
    <   "params": {
    <     "turn": {
    <       "id": "0",
    <       "items": [],
    <       "status": "interrupted"
    <     }
    <   }
    < }
    ```
  • feat: add app-server-test-client crate for internal use (#5391)
    For app-server development it's been helpful to be able to trigger some
    test flows end-to-end and print the JSON-RPC messages sent between
    client and server.