From 29acc22b43acedc2b288967c3844423b33b3cd2a Mon Sep 17 00:00:00 2001 From: Andrei Hasna Date: Tue, 7 Jul 2026 20:52:15 +0300 Subject: [PATCH] feat(app-server-protocol): add v2 pullRequest protocol module Add the v2 pullRequest protocol surface and register its three read methods so downstream consumers can query pull-request data. - Add protocol/v2/pull_request.rs with PullRequest{,Overview,List,Read} params/response types plus a PullRequestQueryState enum so empty, loading, and degraded outcomes are represented in-band on each response instead of as JSON-RPC errors. - Export the module from v2/mod.rs. - Register pullRequest/overview, pullRequest/list, and pullRequest/read in protocol/common.rs using global_shared_read("pull-request"), mirroring the sibling read methods. - Add ClientRequest handler arms in app-server message_processor.rs that return in-band Unavailable query states until the backing PullRequestRequestProcessor is implemented (todos task 1ca04ab4); the ClientRequest match is exhaustive with no wildcard arm. - Regenerate vendored app-server schema fixtures (typescript + json). Co-Authored-By: Claude Opus 4.8 --- .../schema/json/ClientRequest.json | 145 +++++++ .../codex_app_server_protocol.schemas.json | 392 ++++++++++++++++++ .../codex_app_server_protocol.v2.schemas.json | 392 ++++++++++++++++++ .../schema/json/v2/PullRequestListParams.json | 48 +++ .../json/v2/PullRequestListResponse.json | 155 +++++++ .../json/v2/PullRequestOverviewParams.json | 13 + .../json/v2/PullRequestOverviewResponse.json | 191 +++++++++ .../schema/json/v2/PullRequestReadParams.json | 20 + .../json/v2/PullRequestReadResponse.json | 152 +++++++ .../schema/typescript/ClientRequest.ts | 5 +- .../schema/typescript/v2/PullRequest.ts | 7 + .../typescript/v2/PullRequestListParams.ts | 6 + .../typescript/v2/PullRequestListResponse.ts | 7 + .../typescript/v2/PullRequestOverview.ts | 9 + .../v2/PullRequestOverviewParams.ts | 5 + .../v2/PullRequestOverviewResponse.ts | 7 + .../typescript/v2/PullRequestQueryState.ts | 14 + .../typescript/v2/PullRequestReadParams.ts | 5 + .../typescript/v2/PullRequestReadResponse.ts | 7 + .../v2/PullRequestReviewDecision.ts | 5 + .../schema/typescript/v2/PullRequestState.ts | 5 + .../schema/typescript/v2/index.ts | 11 + .../src/protocol/common.rs | 15 + .../src/protocol/v2/mod.rs | 2 + .../src/protocol/v2/pull_request.rs | 144 +++++++ codex-rs/app-server/src/message_processor.rs | 38 ++ 26 files changed, 1799 insertions(+), 1 deletion(-) create mode 100644 codex-rs/app-server-protocol/schema/json/v2/PullRequestListParams.json create mode 100644 codex-rs/app-server-protocol/schema/json/v2/PullRequestListResponse.json create mode 100644 codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewParams.json create mode 100644 codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewResponse.json create mode 100644 codex-rs/app-server-protocol/schema/json/v2/PullRequestReadParams.json create mode 100644 codex-rs/app-server-protocol/schema/json/v2/PullRequestReadResponse.json create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequest.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListParams.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListResponse.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverview.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewParams.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewResponse.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestQueryState.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadParams.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadResponse.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReviewDecision.ts create mode 100644 codex-rs/app-server-protocol/schema/typescript/v2/PullRequestState.ts create mode 100644 codex-rs/app-server-protocol/src/protocol/v2/pull_request.rs diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index 06bc32a56e..f036f5b137 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -2941,6 +2941,79 @@ ], "type": "object" }, + "PullRequestListParams": { + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestState" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "PullRequestOverviewParams": { + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "PullRequestReadParams": { + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "number": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "number" + ], + "type": "object" + }, + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + }, "RealtimeOutputModality": { "enum": [ "text", @@ -7779,6 +7852,78 @@ "title": "Worktree/mergeCandidate/dismissRequest", "type": "object" }, + { + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "method": { + "enum": [ + "pullRequest/overview" + ], + "title": "PullRequest/overviewRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/PullRequestOverviewParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/overviewRequest", + "type": "object" + }, + { + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "method": { + "enum": [ + "pullRequest/list" + ], + "title": "PullRequest/listRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/PullRequestListParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/listRequest", + "type": "object" + }, + { + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "method": { + "enum": [ + "pullRequest/read" + ], + "title": "PullRequest/readRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/PullRequestReadParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/readRequest", + "type": "object" + }, { "properties": { "id": { diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 792d58a860..55fc8f1c34 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -1332,6 +1332,78 @@ "title": "Worktree/mergeCandidate/dismissRequest", "type": "object" }, + { + "properties": { + "id": { + "$ref": "#/definitions/v2/RequestId" + }, + "method": { + "enum": [ + "pullRequest/overview" + ], + "title": "PullRequest/overviewRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/v2/PullRequestOverviewParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/overviewRequest", + "type": "object" + }, + { + "properties": { + "id": { + "$ref": "#/definitions/v2/RequestId" + }, + "method": { + "enum": [ + "pullRequest/list" + ], + "title": "PullRequest/listRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/v2/PullRequestListParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/listRequest", + "type": "object" + }, + { + "properties": { + "id": { + "$ref": "#/definitions/v2/RequestId" + }, + "method": { + "enum": [ + "pullRequest/read" + ], + "title": "PullRequest/readRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/v2/PullRequestReadParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/readRequest", + "type": "object" + }, { "properties": { "id": { @@ -16718,6 +16790,326 @@ ], "type": "object" }, + "PullRequest": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "baseRef": { + "type": [ + "string", + "null" + ] + }, + "createdAt": { + "format": "int64", + "type": "integer" + }, + "headRef": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "isDraft": { + "type": "boolean" + }, + "number": { + "format": "int64", + "type": "integer" + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "reviewDecision": { + "anyOf": [ + { + "$ref": "#/definitions/v2/PullRequestReviewDecision" + }, + { + "type": "null" + } + ] + }, + "state": { + "$ref": "#/definitions/v2/PullRequestState" + }, + "title": { + "type": "string" + }, + "updatedAt": { + "format": "int64", + "type": "integer" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "createdAt", + "id", + "isDraft", + "number", + "state", + "title", + "updatedAt" + ], + "type": "object" + }, + "PullRequestListParams": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/definitions/v2/PullRequestState" + }, + { + "type": "null" + } + ] + } + }, + "title": "PullRequestListParams", + "type": "object" + }, + "PullRequestListResponse": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "data": { + "items": { + "$ref": "#/definitions/v2/PullRequest" + }, + "type": "array" + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "nextCursor": { + "type": [ + "string", + "null" + ] + }, + "queryState": { + "$ref": "#/definitions/v2/PullRequestQueryState" + } + }, + "required": [ + "data", + "queryState" + ], + "title": "PullRequestListResponse", + "type": "object" + }, + "PullRequestOverview": { + "description": "Aggregate view of the pull requests relevant to the current repository.", + "properties": { + "authoredByViewer": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "awaitingViewerReview": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "recentlyUpdated": { + "items": { + "$ref": "#/definitions/v2/PullRequest" + }, + "type": "array" + }, + "totalDraft": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "totalOpen": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + } + }, + "required": [ + "authoredByViewer", + "awaitingViewerReview", + "recentlyUpdated", + "totalDraft", + "totalOpen" + ], + "type": "object" + }, + "PullRequestOverviewParams": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + } + }, + "title": "PullRequestOverviewParams", + "type": "object" + }, + "PullRequestOverviewResponse": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "overview": { + "anyOf": [ + { + "$ref": "#/definitions/v2/PullRequestOverview" + }, + { + "type": "null" + } + ] + }, + "queryState": { + "$ref": "#/definitions/v2/PullRequestQueryState" + } + }, + "required": [ + "queryState" + ], + "title": "PullRequestOverviewResponse", + "type": "object" + }, + "PullRequestQueryState": { + "description": "In-band outcome of a pull-request query.\n\nPull-request data is sourced asynchronously and may be unavailable (for example when no GitHub remote is configured or the backing processor has not been implemented yet). Rather than surfacing these outcomes as JSON-RPC errors, every pull-request response carries a [`PullRequestQueryState`] so clients can render empty/loading/degraded states in-band.", + "oneOf": [ + { + "description": "The response data reflects the current, fully-loaded state.", + "enum": [ + "ready" + ], + "type": "string" + }, + { + "description": "The response data is a partial snapshot while a refresh is in flight.", + "enum": [ + "loading" + ], + "type": "string" + }, + { + "description": "Pull-request data could not be produced; see the accompanying message.", + "enum": [ + "unavailable" + ], + "type": "string" + } + ] + }, + "PullRequestReadParams": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "number": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "number" + ], + "title": "PullRequestReadParams", + "type": "object" + }, + "PullRequestReadResponse": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "pullRequest": { + "anyOf": [ + { + "$ref": "#/definitions/v2/PullRequest" + }, + { + "type": "null" + } + ] + }, + "queryState": { + "$ref": "#/definitions/v2/PullRequestQueryState" + } + }, + "required": [ + "queryState" + ], + "title": "PullRequestReadResponse", + "type": "object" + }, + "PullRequestReviewDecision": { + "enum": [ + "approved", + "changesRequested", + "reviewRequired" + ], + "type": "string" + }, + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + }, "RateLimitReachedType": { "enum": [ "rate_limit_reached", diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index d5505cf6d3..aec3e0d916 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -3298,6 +3298,78 @@ "title": "Worktree/mergeCandidate/dismissRequest", "type": "object" }, + { + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "method": { + "enum": [ + "pullRequest/overview" + ], + "title": "PullRequest/overviewRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/PullRequestOverviewParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/overviewRequest", + "type": "object" + }, + { + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "method": { + "enum": [ + "pullRequest/list" + ], + "title": "PullRequest/listRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/PullRequestListParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/listRequest", + "type": "object" + }, + { + "properties": { + "id": { + "$ref": "#/definitions/RequestId" + }, + "method": { + "enum": [ + "pullRequest/read" + ], + "title": "PullRequest/readRequestMethod", + "type": "string" + }, + "params": { + "$ref": "#/definitions/PullRequestReadParams" + } + }, + "required": [ + "id", + "method", + "params" + ], + "title": "PullRequest/readRequest", + "type": "object" + }, { "properties": { "id": { @@ -13248,6 +13320,326 @@ ], "type": "object" }, + "PullRequest": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "baseRef": { + "type": [ + "string", + "null" + ] + }, + "createdAt": { + "format": "int64", + "type": "integer" + }, + "headRef": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "isDraft": { + "type": "boolean" + }, + "number": { + "format": "int64", + "type": "integer" + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "reviewDecision": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestReviewDecision" + }, + { + "type": "null" + } + ] + }, + "state": { + "$ref": "#/definitions/PullRequestState" + }, + "title": { + "type": "string" + }, + "updatedAt": { + "format": "int64", + "type": "integer" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "createdAt", + "id", + "isDraft", + "number", + "state", + "title", + "updatedAt" + ], + "type": "object" + }, + "PullRequestListParams": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestState" + }, + { + "type": "null" + } + ] + } + }, + "title": "PullRequestListParams", + "type": "object" + }, + "PullRequestListResponse": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "data": { + "items": { + "$ref": "#/definitions/PullRequest" + }, + "type": "array" + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "nextCursor": { + "type": [ + "string", + "null" + ] + }, + "queryState": { + "$ref": "#/definitions/PullRequestQueryState" + } + }, + "required": [ + "data", + "queryState" + ], + "title": "PullRequestListResponse", + "type": "object" + }, + "PullRequestOverview": { + "description": "Aggregate view of the pull requests relevant to the current repository.", + "properties": { + "authoredByViewer": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "awaitingViewerReview": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "recentlyUpdated": { + "items": { + "$ref": "#/definitions/PullRequest" + }, + "type": "array" + }, + "totalDraft": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "totalOpen": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + } + }, + "required": [ + "authoredByViewer", + "awaitingViewerReview", + "recentlyUpdated", + "totalDraft", + "totalOpen" + ], + "type": "object" + }, + "PullRequestOverviewParams": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + } + }, + "title": "PullRequestOverviewParams", + "type": "object" + }, + "PullRequestOverviewResponse": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "overview": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestOverview" + }, + { + "type": "null" + } + ] + }, + "queryState": { + "$ref": "#/definitions/PullRequestQueryState" + } + }, + "required": [ + "queryState" + ], + "title": "PullRequestOverviewResponse", + "type": "object" + }, + "PullRequestQueryState": { + "description": "In-band outcome of a pull-request query.\n\nPull-request data is sourced asynchronously and may be unavailable (for example when no GitHub remote is configured or the backing processor has not been implemented yet). Rather than surfacing these outcomes as JSON-RPC errors, every pull-request response carries a [`PullRequestQueryState`] so clients can render empty/loading/degraded states in-band.", + "oneOf": [ + { + "description": "The response data reflects the current, fully-loaded state.", + "enum": [ + "ready" + ], + "type": "string" + }, + { + "description": "The response data is a partial snapshot while a refresh is in flight.", + "enum": [ + "loading" + ], + "type": "string" + }, + { + "description": "Pull-request data could not be produced; see the accompanying message.", + "enum": [ + "unavailable" + ], + "type": "string" + } + ] + }, + "PullRequestReadParams": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "number": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "number" + ], + "title": "PullRequestReadParams", + "type": "object" + }, + "PullRequestReadResponse": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "pullRequest": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequest" + }, + { + "type": "null" + } + ] + }, + "queryState": { + "$ref": "#/definitions/PullRequestQueryState" + } + }, + "required": [ + "queryState" + ], + "title": "PullRequestReadResponse", + "type": "object" + }, + "PullRequestReviewDecision": { + "enum": [ + "approved", + "changesRequested", + "reviewRequired" + ], + "type": "string" + }, + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + }, "RateLimitReachedType": { "enum": [ "rate_limit_reached", diff --git a/codex-rs/app-server-protocol/schema/json/v2/PullRequestListParams.json b/codex-rs/app-server-protocol/schema/json/v2/PullRequestListParams.json new file mode 100644 index 0000000000..699716c6dd --- /dev/null +++ b/codex-rs/app-server-protocol/schema/json/v2/PullRequestListParams.json @@ -0,0 +1,48 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + } + }, + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint32", + "minimum": 0.0, + "type": [ + "integer", + "null" + ] + }, + "state": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestState" + }, + { + "type": "null" + } + ] + } + }, + "title": "PullRequestListParams", + "type": "object" +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/PullRequestListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PullRequestListResponse.json new file mode 100644 index 0000000000..422c45288e --- /dev/null +++ b/codex-rs/app-server-protocol/schema/json/v2/PullRequestListResponse.json @@ -0,0 +1,155 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "PullRequest": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "baseRef": { + "type": [ + "string", + "null" + ] + }, + "createdAt": { + "format": "int64", + "type": "integer" + }, + "headRef": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "isDraft": { + "type": "boolean" + }, + "number": { + "format": "int64", + "type": "integer" + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "reviewDecision": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestReviewDecision" + }, + { + "type": "null" + } + ] + }, + "state": { + "$ref": "#/definitions/PullRequestState" + }, + "title": { + "type": "string" + }, + "updatedAt": { + "format": "int64", + "type": "integer" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "createdAt", + "id", + "isDraft", + "number", + "state", + "title", + "updatedAt" + ], + "type": "object" + }, + "PullRequestQueryState": { + "description": "In-band outcome of a pull-request query.\n\nPull-request data is sourced asynchronously and may be unavailable (for example when no GitHub remote is configured or the backing processor has not been implemented yet). Rather than surfacing these outcomes as JSON-RPC errors, every pull-request response carries a [`PullRequestQueryState`] so clients can render empty/loading/degraded states in-band.", + "oneOf": [ + { + "description": "The response data reflects the current, fully-loaded state.", + "enum": [ + "ready" + ], + "type": "string" + }, + { + "description": "The response data is a partial snapshot while a refresh is in flight.", + "enum": [ + "loading" + ], + "type": "string" + }, + { + "description": "Pull-request data could not be produced; see the accompanying message.", + "enum": [ + "unavailable" + ], + "type": "string" + } + ] + }, + "PullRequestReviewDecision": { + "enum": [ + "approved", + "changesRequested", + "reviewRequired" + ], + "type": "string" + }, + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + } + }, + "properties": { + "data": { + "items": { + "$ref": "#/definitions/PullRequest" + }, + "type": "array" + }, + "message": { + "type": [ + "string", + "null" + ] + }, + "nextCursor": { + "type": [ + "string", + "null" + ] + }, + "queryState": { + "$ref": "#/definitions/PullRequestQueryState" + } + }, + "required": [ + "data", + "queryState" + ], + "title": "PullRequestListResponse", + "type": "object" +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewParams.json b/codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewParams.json new file mode 100644 index 0000000000..4b0ff63865 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewParams.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + } + }, + "title": "PullRequestOverviewParams", + "type": "object" +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewResponse.json new file mode 100644 index 0000000000..f86f4c42cd --- /dev/null +++ b/codex-rs/app-server-protocol/schema/json/v2/PullRequestOverviewResponse.json @@ -0,0 +1,191 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "PullRequest": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "baseRef": { + "type": [ + "string", + "null" + ] + }, + "createdAt": { + "format": "int64", + "type": "integer" + }, + "headRef": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "isDraft": { + "type": "boolean" + }, + "number": { + "format": "int64", + "type": "integer" + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "reviewDecision": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestReviewDecision" + }, + { + "type": "null" + } + ] + }, + "state": { + "$ref": "#/definitions/PullRequestState" + }, + "title": { + "type": "string" + }, + "updatedAt": { + "format": "int64", + "type": "integer" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "createdAt", + "id", + "isDraft", + "number", + "state", + "title", + "updatedAt" + ], + "type": "object" + }, + "PullRequestOverview": { + "description": "Aggregate view of the pull requests relevant to the current repository.", + "properties": { + "authoredByViewer": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "awaitingViewerReview": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "recentlyUpdated": { + "items": { + "$ref": "#/definitions/PullRequest" + }, + "type": "array" + }, + "totalDraft": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + }, + "totalOpen": { + "format": "uint32", + "minimum": 0.0, + "type": "integer" + } + }, + "required": [ + "authoredByViewer", + "awaitingViewerReview", + "recentlyUpdated", + "totalDraft", + "totalOpen" + ], + "type": "object" + }, + "PullRequestQueryState": { + "description": "In-band outcome of a pull-request query.\n\nPull-request data is sourced asynchronously and may be unavailable (for example when no GitHub remote is configured or the backing processor has not been implemented yet). Rather than surfacing these outcomes as JSON-RPC errors, every pull-request response carries a [`PullRequestQueryState`] so clients can render empty/loading/degraded states in-band.", + "oneOf": [ + { + "description": "The response data reflects the current, fully-loaded state.", + "enum": [ + "ready" + ], + "type": "string" + }, + { + "description": "The response data is a partial snapshot while a refresh is in flight.", + "enum": [ + "loading" + ], + "type": "string" + }, + { + "description": "Pull-request data could not be produced; see the accompanying message.", + "enum": [ + "unavailable" + ], + "type": "string" + } + ] + }, + "PullRequestReviewDecision": { + "enum": [ + "approved", + "changesRequested", + "reviewRequired" + ], + "type": "string" + }, + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + } + }, + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "overview": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestOverview" + }, + { + "type": "null" + } + ] + }, + "queryState": { + "$ref": "#/definitions/PullRequestQueryState" + } + }, + "required": [ + "queryState" + ], + "title": "PullRequestOverviewResponse", + "type": "object" +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/PullRequestReadParams.json b/codex-rs/app-server-protocol/schema/json/v2/PullRequestReadParams.json new file mode 100644 index 0000000000..641508d7ea --- /dev/null +++ b/codex-rs/app-server-protocol/schema/json/v2/PullRequestReadParams.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "baseRepoPath": { + "type": [ + "string", + "null" + ] + }, + "number": { + "format": "int64", + "type": "integer" + } + }, + "required": [ + "number" + ], + "title": "PullRequestReadParams", + "type": "object" +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/PullRequestReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PullRequestReadResponse.json new file mode 100644 index 0000000000..978232c0ed --- /dev/null +++ b/codex-rs/app-server-protocol/schema/json/v2/PullRequestReadResponse.json @@ -0,0 +1,152 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "PullRequest": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "baseRef": { + "type": [ + "string", + "null" + ] + }, + "createdAt": { + "format": "int64", + "type": "integer" + }, + "headRef": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "isDraft": { + "type": "boolean" + }, + "number": { + "format": "int64", + "type": "integer" + }, + "repository": { + "type": [ + "string", + "null" + ] + }, + "reviewDecision": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequestReviewDecision" + }, + { + "type": "null" + } + ] + }, + "state": { + "$ref": "#/definitions/PullRequestState" + }, + "title": { + "type": "string" + }, + "updatedAt": { + "format": "int64", + "type": "integer" + }, + "url": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "createdAt", + "id", + "isDraft", + "number", + "state", + "title", + "updatedAt" + ], + "type": "object" + }, + "PullRequestQueryState": { + "description": "In-band outcome of a pull-request query.\n\nPull-request data is sourced asynchronously and may be unavailable (for example when no GitHub remote is configured or the backing processor has not been implemented yet). Rather than surfacing these outcomes as JSON-RPC errors, every pull-request response carries a [`PullRequestQueryState`] so clients can render empty/loading/degraded states in-band.", + "oneOf": [ + { + "description": "The response data reflects the current, fully-loaded state.", + "enum": [ + "ready" + ], + "type": "string" + }, + { + "description": "The response data is a partial snapshot while a refresh is in flight.", + "enum": [ + "loading" + ], + "type": "string" + }, + { + "description": "Pull-request data could not be produced; see the accompanying message.", + "enum": [ + "unavailable" + ], + "type": "string" + } + ] + }, + "PullRequestReviewDecision": { + "enum": [ + "approved", + "changesRequested", + "reviewRequired" + ], + "type": "string" + }, + "PullRequestState": { + "enum": [ + "open", + "closed", + "merged", + "draft" + ], + "type": "string" + } + }, + "properties": { + "message": { + "type": [ + "string", + "null" + ] + }, + "pullRequest": { + "anyOf": [ + { + "$ref": "#/definitions/PullRequest" + }, + { + "type": "null" + } + ] + }, + "queryState": { + "$ref": "#/definitions/PullRequestQueryState" + } + }, + "required": [ + "queryState" + ], + "title": "PullRequestReadResponse", + "type": "object" +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/typescript/ClientRequest.ts b/codex-rs/app-server-protocol/schema/typescript/ClientRequest.ts index b0695a1a7e..ddb4f949d4 100644 --- a/codex-rs/app-server-protocol/schema/typescript/ClientRequest.ts +++ b/codex-rs/app-server-protocol/schema/typescript/ClientRequest.ts @@ -66,6 +66,9 @@ import type { PluginShareSaveParams } from "./v2/PluginShareSaveParams"; import type { PluginShareUpdateTargetsParams } from "./v2/PluginShareUpdateTargetsParams"; import type { PluginSkillReadParams } from "./v2/PluginSkillReadParams"; import type { PluginUninstallParams } from "./v2/PluginUninstallParams"; +import type { PullRequestListParams } from "./v2/PullRequestListParams"; +import type { PullRequestOverviewParams } from "./v2/PullRequestOverviewParams"; +import type { PullRequestReadParams } from "./v2/PullRequestReadParams"; import type { ReviewStartParams } from "./v2/ReviewStartParams"; import type { SendAddCreditsNudgeEmailParams } from "./v2/SendAddCreditsNudgeEmailParams"; import type { SkillsConfigWriteParams } from "./v2/SkillsConfigWriteParams"; @@ -135,4 +138,4 @@ import type { WorktreeReleaseParams } from "./v2/WorktreeReleaseParams"; /** * Request from the client to the server. */ -export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/goal/set", id: RequestId, params: ThreadGoalSetParams, } | { "method": "thread/goal/get", id: RequestId, params: ThreadGoalGetParams, } | { "method": "thread/goal/list", id: RequestId, params: ThreadGoalListParams, } | { "method": "thread/goalPlan/activateNode", id: RequestId, params: ThreadGoalPlanActivateNodeParams, } | { "method": "thread/goalPlan/addGoal", id: RequestId, params: ThreadGoalPlanAddGoalParams, } | { "method": "thread/goal/clear", id: RequestId, params: ThreadGoalClearParams, } | { "method": "thread/schedule/create", id: RequestId, params: ThreadScheduleCreateParams, } | { "method": "thread/schedule/list", id: RequestId, params: ThreadScheduleListParams, } | { "method": "thread/schedule/get", id: RequestId, params: ThreadScheduleGetParams, } | { "method": "thread/schedule/update", id: RequestId, params: ThreadScheduleUpdateParams, } | { "method": "thread/schedule/pause", id: RequestId, params: ThreadSchedulePauseParams, } | { "method": "thread/schedule/resume", id: RequestId, params: ThreadScheduleResumeParams, } | { "method": "thread/schedule/delete", id: RequestId, params: ThreadScheduleDeleteParams, } | { "method": "thread/schedule/runNow", id: RequestId, params: ThreadScheduleRunNowParams, } | { "method": "thread/monitor/create", id: RequestId, params: ThreadMonitorCreateParams, } | { "method": "thread/monitor/list", id: RequestId, params: ThreadMonitorListParams, } | { "method": "thread/monitor/read", id: RequestId, params: ThreadMonitorReadParams, } | { "method": "thread/monitor/stop", id: RequestId, params: ThreadMonitorStopParams, } | { "method": "thread/monitor/restart", id: RequestId, params: ThreadMonitorRestartParams, } | { "method": "thread/monitor/delete", id: RequestId, params: ThreadMonitorDeleteParams, } | { "method": "webhook/event/list", id: RequestId, params: WebhookEventListParams, } | { "method": "webhook/event/read", id: RequestId, params: WebhookEventReadParams, } | { "method": "webhook/event/mark", id: RequestId, params: WebhookEventMarkParams, } | { "method": "webhook/event/ingest", id: RequestId, params: WebhookEventIngestParams, } | { "method": "missionControl/overview", id: RequestId, params: MissionControlOverviewParams, } | { "method": "missionControl/enqueueInstruction", id: RequestId, params: MissionControlEnqueueInstructionParams, } | { "method": "missionControl/mailboxReceipts", id: RequestId, params: MissionControlMailboxReceiptsParams, } | { "method": "missionControl/respondInteraction", id: RequestId, params: MissionControlRespondInteractionParams, } | { "method": "worktree/list", id: RequestId, params: WorktreeListParams, } | { "method": "worktree/read", id: RequestId, params: WorktreeReadParams, } | { "method": "worktree/create", id: RequestId, params: WorktreeCreateParams, } | { "method": "worktree/reconcile", id: RequestId, params: WorktreeReconcileParams, } | { "method": "worktree/attach", id: RequestId, params: WorktreeAttachParams, } | { "method": "worktree/detach", id: RequestId, params: WorktreeDetachParams, } | { "method": "worktree/release", id: RequestId, params: WorktreeReleaseParams, } | { "method": "worktree/cleanup", id: RequestId, params: WorktreeCleanupParams, } | { "method": "worktree/mergeCandidate/list", id: RequestId, params: WorktreeMergeCandidateListParams, } | { "method": "worktree/mergeCandidate/refresh", id: RequestId, params: WorktreeMergeCandidateRefreshParams, } | { "method": "worktree/mergeCandidate/apply", id: RequestId, params: WorktreeMergeCandidateApplyParams, } | { "method": "worktree/mergeCandidate/dismiss", id: RequestId, params: WorktreeMergeCandidateDismissParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/recap", id: RequestId, params: ThreadRecapParams, } | { "method": "thread/shellCommand", id: RequestId, params: ThreadShellCommandParams, } | { "method": "thread/queuedMessage/list", id: RequestId, params: ThreadQueuedMessageListParams, } | { "method": "thread/queuedMessage/update", id: RequestId, params: ThreadQueuedMessageUpdateParams, } | { "method": "thread/queuedMessage/move", id: RequestId, params: ThreadQueuedMessageMoveParams, } | { "method": "thread/approveGuardianDeniedAction", id: RequestId, params: ThreadApproveGuardianDeniedActionParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "activeSession/list", id: RequestId, params: ActiveSessionListParams, } | { "method": "activeSession/send", id: RequestId, params: ActiveSessionSendParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "thread/inject_items", id: RequestId, params: ThreadInjectItemsParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "skills/extraRoots/set", id: RequestId, params: SkillsExtraRootsSetParams, } | { "method": "hooks/list", id: RequestId, params: HooksListParams, } | { "method": "marketplace/add", id: RequestId, params: MarketplaceAddParams, } | { "method": "marketplace/remove", id: RequestId, params: MarketplaceRemoveParams, } | { "method": "marketplace/upgrade", id: RequestId, params: MarketplaceUpgradeParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "plugin/installed", id: RequestId, params: PluginInstalledParams, } | { "method": "plugin/read", id: RequestId, params: PluginReadParams, } | { "method": "plugin/skill/read", id: RequestId, params: PluginSkillReadParams, } | { "method": "plugin/share/save", id: RequestId, params: PluginShareSaveParams, } | { "method": "plugin/share/updateTargets", id: RequestId, params: PluginShareUpdateTargetsParams, } | { "method": "plugin/share/list", id: RequestId, params: PluginShareListParams, } | { "method": "plugin/share/checkout", id: RequestId, params: PluginShareCheckoutParams, } | { "method": "plugin/share/delete", id: RequestId, params: PluginShareDeleteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "fs/readFile", id: RequestId, params: FsReadFileParams, } | { "method": "fs/writeFile", id: RequestId, params: FsWriteFileParams, } | { "method": "fs/createDirectory", id: RequestId, params: FsCreateDirectoryParams, } | { "method": "fs/getMetadata", id: RequestId, params: FsGetMetadataParams, } | { "method": "fs/readDirectory", id: RequestId, params: FsReadDirectoryParams, } | { "method": "fs/remove", id: RequestId, params: FsRemoveParams, } | { "method": "fs/copy", id: RequestId, params: FsCopyParams, } | { "method": "fs/watch", id: RequestId, params: FsWatchParams, } | { "method": "fs/unwatch", id: RequestId, params: FsUnwatchParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "plugin/uninstall", id: RequestId, params: PluginUninstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "modelGateway/list", id: RequestId, params: ModelGatewayListParams, } | { "method": "modelProvider/list", id: RequestId, params: ModelProviderListParams, } | { "method": "modelProvider/capabilities/read", id: RequestId, params: ModelProviderCapabilitiesReadParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "permissionProfile/list", id: RequestId, params: PermissionProfileListParams, } | { "method": "experimentalFeature/enablement/set", id: RequestId, params: ExperimentalFeatureEnablementSetParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "mcpServer/resource/read", id: RequestId, params: McpResourceReadParams, } | { "method": "mcpServer/tool/call", id: RequestId, params: McpServerToolCallParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "windowsSandbox/readiness", id: RequestId, params: undefined, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "authProfile/list", id: RequestId, params: AuthProfileListParams, } | { "method": "authProfile/saveCurrent", id: RequestId, params: AuthProfileSaveCurrentParams, } | { "method": "authProfile/switch", id: RequestId, params: AuthProfileSwitchParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: GetAccountRateLimitsParams, } | { "method": "account/usage/read", id: RequestId, params: undefined, } | { "method": "account/sendAddCreditsNudgeEmail", id: RequestId, params: SendAddCreditsNudgeEmailParams, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, }; +export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/unsubscribe", id: RequestId, params: ThreadUnsubscribeParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/goal/set", id: RequestId, params: ThreadGoalSetParams, } | { "method": "thread/goal/get", id: RequestId, params: ThreadGoalGetParams, } | { "method": "thread/goal/list", id: RequestId, params: ThreadGoalListParams, } | { "method": "thread/goalPlan/activateNode", id: RequestId, params: ThreadGoalPlanActivateNodeParams, } | { "method": "thread/goalPlan/addGoal", id: RequestId, params: ThreadGoalPlanAddGoalParams, } | { "method": "thread/goal/clear", id: RequestId, params: ThreadGoalClearParams, } | { "method": "thread/schedule/create", id: RequestId, params: ThreadScheduleCreateParams, } | { "method": "thread/schedule/list", id: RequestId, params: ThreadScheduleListParams, } | { "method": "thread/schedule/get", id: RequestId, params: ThreadScheduleGetParams, } | { "method": "thread/schedule/update", id: RequestId, params: ThreadScheduleUpdateParams, } | { "method": "thread/schedule/pause", id: RequestId, params: ThreadSchedulePauseParams, } | { "method": "thread/schedule/resume", id: RequestId, params: ThreadScheduleResumeParams, } | { "method": "thread/schedule/delete", id: RequestId, params: ThreadScheduleDeleteParams, } | { "method": "thread/schedule/runNow", id: RequestId, params: ThreadScheduleRunNowParams, } | { "method": "thread/monitor/create", id: RequestId, params: ThreadMonitorCreateParams, } | { "method": "thread/monitor/list", id: RequestId, params: ThreadMonitorListParams, } | { "method": "thread/monitor/read", id: RequestId, params: ThreadMonitorReadParams, } | { "method": "thread/monitor/stop", id: RequestId, params: ThreadMonitorStopParams, } | { "method": "thread/monitor/restart", id: RequestId, params: ThreadMonitorRestartParams, } | { "method": "thread/monitor/delete", id: RequestId, params: ThreadMonitorDeleteParams, } | { "method": "webhook/event/list", id: RequestId, params: WebhookEventListParams, } | { "method": "webhook/event/read", id: RequestId, params: WebhookEventReadParams, } | { "method": "webhook/event/mark", id: RequestId, params: WebhookEventMarkParams, } | { "method": "webhook/event/ingest", id: RequestId, params: WebhookEventIngestParams, } | { "method": "missionControl/overview", id: RequestId, params: MissionControlOverviewParams, } | { "method": "missionControl/enqueueInstruction", id: RequestId, params: MissionControlEnqueueInstructionParams, } | { "method": "missionControl/mailboxReceipts", id: RequestId, params: MissionControlMailboxReceiptsParams, } | { "method": "missionControl/respondInteraction", id: RequestId, params: MissionControlRespondInteractionParams, } | { "method": "worktree/list", id: RequestId, params: WorktreeListParams, } | { "method": "worktree/read", id: RequestId, params: WorktreeReadParams, } | { "method": "worktree/create", id: RequestId, params: WorktreeCreateParams, } | { "method": "worktree/reconcile", id: RequestId, params: WorktreeReconcileParams, } | { "method": "worktree/attach", id: RequestId, params: WorktreeAttachParams, } | { "method": "worktree/detach", id: RequestId, params: WorktreeDetachParams, } | { "method": "worktree/release", id: RequestId, params: WorktreeReleaseParams, } | { "method": "worktree/cleanup", id: RequestId, params: WorktreeCleanupParams, } | { "method": "worktree/mergeCandidate/list", id: RequestId, params: WorktreeMergeCandidateListParams, } | { "method": "worktree/mergeCandidate/refresh", id: RequestId, params: WorktreeMergeCandidateRefreshParams, } | { "method": "worktree/mergeCandidate/apply", id: RequestId, params: WorktreeMergeCandidateApplyParams, } | { "method": "worktree/mergeCandidate/dismiss", id: RequestId, params: WorktreeMergeCandidateDismissParams, } | { "method": "pullRequest/overview", id: RequestId, params: PullRequestOverviewParams, } | { "method": "pullRequest/list", id: RequestId, params: PullRequestListParams, } | { "method": "pullRequest/read", id: RequestId, params: PullRequestReadParams, } | { "method": "thread/metadata/update", id: RequestId, params: ThreadMetadataUpdateParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/compact/start", id: RequestId, params: ThreadCompactStartParams, } | { "method": "thread/recap", id: RequestId, params: ThreadRecapParams, } | { "method": "thread/shellCommand", id: RequestId, params: ThreadShellCommandParams, } | { "method": "thread/queuedMessage/list", id: RequestId, params: ThreadQueuedMessageListParams, } | { "method": "thread/queuedMessage/update", id: RequestId, params: ThreadQueuedMessageUpdateParams, } | { "method": "thread/queuedMessage/move", id: RequestId, params: ThreadQueuedMessageMoveParams, } | { "method": "thread/approveGuardianDeniedAction", id: RequestId, params: ThreadApproveGuardianDeniedActionParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "activeSession/list", id: RequestId, params: ActiveSessionListParams, } | { "method": "activeSession/send", id: RequestId, params: ActiveSessionSendParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "thread/inject_items", id: RequestId, params: ThreadInjectItemsParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "skills/extraRoots/set", id: RequestId, params: SkillsExtraRootsSetParams, } | { "method": "hooks/list", id: RequestId, params: HooksListParams, } | { "method": "marketplace/add", id: RequestId, params: MarketplaceAddParams, } | { "method": "marketplace/remove", id: RequestId, params: MarketplaceRemoveParams, } | { "method": "marketplace/upgrade", id: RequestId, params: MarketplaceUpgradeParams, } | { "method": "plugin/list", id: RequestId, params: PluginListParams, } | { "method": "plugin/installed", id: RequestId, params: PluginInstalledParams, } | { "method": "plugin/read", id: RequestId, params: PluginReadParams, } | { "method": "plugin/skill/read", id: RequestId, params: PluginSkillReadParams, } | { "method": "plugin/share/save", id: RequestId, params: PluginShareSaveParams, } | { "method": "plugin/share/updateTargets", id: RequestId, params: PluginShareUpdateTargetsParams, } | { "method": "plugin/share/list", id: RequestId, params: PluginShareListParams, } | { "method": "plugin/share/checkout", id: RequestId, params: PluginShareCheckoutParams, } | { "method": "plugin/share/delete", id: RequestId, params: PluginShareDeleteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "fs/readFile", id: RequestId, params: FsReadFileParams, } | { "method": "fs/writeFile", id: RequestId, params: FsWriteFileParams, } | { "method": "fs/createDirectory", id: RequestId, params: FsCreateDirectoryParams, } | { "method": "fs/getMetadata", id: RequestId, params: FsGetMetadataParams, } | { "method": "fs/readDirectory", id: RequestId, params: FsReadDirectoryParams, } | { "method": "fs/remove", id: RequestId, params: FsRemoveParams, } | { "method": "fs/copy", id: RequestId, params: FsCopyParams, } | { "method": "fs/watch", id: RequestId, params: FsWatchParams, } | { "method": "fs/unwatch", id: RequestId, params: FsUnwatchParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "plugin/install", id: RequestId, params: PluginInstallParams, } | { "method": "plugin/uninstall", id: RequestId, params: PluginUninstallParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/steer", id: RequestId, params: TurnSteerParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "modelGateway/list", id: RequestId, params: ModelGatewayListParams, } | { "method": "modelProvider/list", id: RequestId, params: ModelProviderListParams, } | { "method": "modelProvider/capabilities/read", id: RequestId, params: ModelProviderCapabilitiesReadParams, } | { "method": "experimentalFeature/list", id: RequestId, params: ExperimentalFeatureListParams, } | { "method": "permissionProfile/list", id: RequestId, params: PermissionProfileListParams, } | { "method": "experimentalFeature/enablement/set", id: RequestId, params: ExperimentalFeatureEnablementSetParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "mcpServer/resource/read", id: RequestId, params: McpResourceReadParams, } | { "method": "mcpServer/tool/call", id: RequestId, params: McpServerToolCallParams, } | { "method": "windowsSandbox/setupStart", id: RequestId, params: WindowsSandboxSetupStartParams, } | { "method": "windowsSandbox/readiness", id: RequestId, params: undefined, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "authProfile/list", id: RequestId, params: AuthProfileListParams, } | { "method": "authProfile/saveCurrent", id: RequestId, params: AuthProfileSaveCurrentParams, } | { "method": "authProfile/switch", id: RequestId, params: AuthProfileSwitchParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: GetAccountRateLimitsParams, } | { "method": "account/usage/read", id: RequestId, params: undefined, } | { "method": "account/sendAddCreditsNudgeEmail", id: RequestId, params: SendAddCreditsNudgeEmailParams, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "command/exec/write", id: RequestId, params: CommandExecWriteParams, } | { "method": "command/exec/terminate", id: RequestId, params: CommandExecTerminateParams, } | { "method": "command/exec/resize", id: RequestId, params: CommandExecResizeParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "externalAgentConfig/detect", id: RequestId, params: ExternalAgentConfigDetectParams, } | { "method": "externalAgentConfig/import", id: RequestId, params: ExternalAgentConfigImportParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequest.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequest.ts new file mode 100644 index 0000000000..3550f9aa6e --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequest.ts @@ -0,0 +1,7 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PullRequestReviewDecision } from "./PullRequestReviewDecision"; +import type { PullRequestState } from "./PullRequestState"; + +export type PullRequest = { id: string, number: number, title: string, state: PullRequestState, isDraft: boolean, author: string | null, url: string | null, repository: string | null, headRef: string | null, baseRef: string | null, reviewDecision: PullRequestReviewDecision | null, createdAt: number, updatedAt: number, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListParams.ts new file mode 100644 index 0000000000..aad4c4f265 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListParams.ts @@ -0,0 +1,6 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PullRequestState } from "./PullRequestState"; + +export type PullRequestListParams = { baseRepoPath?: string | null, state?: PullRequestState | null, cursor?: string | null, limit?: number | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListResponse.ts new file mode 100644 index 0000000000..54a5205cae --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestListResponse.ts @@ -0,0 +1,7 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PullRequest } from "./PullRequest"; +import type { PullRequestQueryState } from "./PullRequestQueryState"; + +export type PullRequestListResponse = { queryState: PullRequestQueryState, data: Array, nextCursor: string | null, message: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverview.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverview.ts new file mode 100644 index 0000000000..0ba5fe3e9d --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverview.ts @@ -0,0 +1,9 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PullRequest } from "./PullRequest"; + +/** + * Aggregate view of the pull requests relevant to the current repository. + */ +export type PullRequestOverview = { totalOpen: number, totalDraft: number, authoredByViewer: number, awaitingViewerReview: number, recentlyUpdated: Array, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewParams.ts new file mode 100644 index 0000000000..c22c27140a --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewParams.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PullRequestOverviewParams = { baseRepoPath?: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewResponse.ts new file mode 100644 index 0000000000..a9a7a05c5b --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestOverviewResponse.ts @@ -0,0 +1,7 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PullRequestOverview } from "./PullRequestOverview"; +import type { PullRequestQueryState } from "./PullRequestQueryState"; + +export type PullRequestOverviewResponse = { queryState: PullRequestQueryState, overview: PullRequestOverview | null, message: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestQueryState.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestQueryState.ts new file mode 100644 index 0000000000..7b6e82d231 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestQueryState.ts @@ -0,0 +1,14 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * In-band outcome of a pull-request query. + * + * Pull-request data is sourced asynchronously and may be unavailable (for + * example when no GitHub remote is configured or the backing processor has not + * been implemented yet). Rather than surfacing these outcomes as JSON-RPC + * errors, every pull-request response carries a [`PullRequestQueryState`] so + * clients can render empty/loading/degraded states in-band. + */ +export type PullRequestQueryState = "ready" | "loading" | "unavailable"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadParams.ts new file mode 100644 index 0000000000..1a550c0570 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadParams.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PullRequestReadParams = { number: number, baseRepoPath?: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadResponse.ts new file mode 100644 index 0000000000..8c5ab1daa5 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReadResponse.ts @@ -0,0 +1,7 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PullRequest } from "./PullRequest"; +import type { PullRequestQueryState } from "./PullRequestQueryState"; + +export type PullRequestReadResponse = { queryState: PullRequestQueryState, pullRequest: PullRequest | null, message: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReviewDecision.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReviewDecision.ts new file mode 100644 index 0000000000..d77e6702ff --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestReviewDecision.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PullRequestReviewDecision = "approved" | "changesRequested" | "reviewRequired"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestState.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestState.ts new file mode 100644 index 0000000000..138b9fdaa2 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/PullRequestState.ts @@ -0,0 +1,5 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PullRequestState = "open" | "closed" | "merged" | "draft"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts index 05b02ac667..95ab324bc3 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts @@ -373,6 +373,17 @@ export type { ProcessExitedNotification } from "./ProcessExitedNotification"; export type { ProcessOutputDeltaNotification } from "./ProcessOutputDeltaNotification"; export type { ProcessOutputStream } from "./ProcessOutputStream"; export type { ProcessTerminalSize } from "./ProcessTerminalSize"; +export type { PullRequest } from "./PullRequest"; +export type { PullRequestListParams } from "./PullRequestListParams"; +export type { PullRequestListResponse } from "./PullRequestListResponse"; +export type { PullRequestOverview } from "./PullRequestOverview"; +export type { PullRequestOverviewParams } from "./PullRequestOverviewParams"; +export type { PullRequestOverviewResponse } from "./PullRequestOverviewResponse"; +export type { PullRequestQueryState } from "./PullRequestQueryState"; +export type { PullRequestReadParams } from "./PullRequestReadParams"; +export type { PullRequestReadResponse } from "./PullRequestReadResponse"; +export type { PullRequestReviewDecision } from "./PullRequestReviewDecision"; +export type { PullRequestState } from "./PullRequestState"; export type { RateLimitReachedType } from "./RateLimitReachedType"; export type { RateLimitSnapshot } from "./RateLimitSnapshot"; export type { RateLimitWindow } from "./RateLimitWindow"; diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index b3db267d94..894e4219a4 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -994,6 +994,21 @@ client_request_definitions! { serialization: global("worktree"), response: v2::WorktreeMergeCandidateDismissResponse, }, + PullRequestOverview => "pullRequest/overview" { + params: v2::PullRequestOverviewParams, + serialization: global_shared_read("pull-request"), + response: v2::PullRequestOverviewResponse, + }, + PullRequestList => "pullRequest/list" { + params: v2::PullRequestListParams, + serialization: global_shared_read("pull-request"), + response: v2::PullRequestListResponse, + }, + PullRequestRead => "pullRequest/read" { + params: v2::PullRequestReadParams, + serialization: global_shared_read("pull-request"), + response: v2::PullRequestReadResponse, + }, #[experimental("machineRegistry/list")] MachineRegistryList => "machineRegistry/list" { params: v2::MachineRegistryListParams, diff --git a/codex-rs/app-server-protocol/src/protocol/v2/mod.rs b/codex-rs/app-server-protocol/src/protocol/v2/mod.rs index 44990104ba..4e74abf33b 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/mod.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/mod.rs @@ -25,6 +25,7 @@ mod pending_interaction; mod permissions; mod plugin; mod process; +mod pull_request; mod realtime; mod remote_control; mod remote_dispatch; @@ -62,6 +63,7 @@ pub use pending_interaction::*; pub use permissions::*; pub use plugin::*; pub use process::*; +pub use pull_request::*; pub use realtime::*; pub use remote_control::*; pub use remote_dispatch::*; diff --git a/codex-rs/app-server-protocol/src/protocol/v2/pull_request.rs b/codex-rs/app-server-protocol/src/protocol/v2/pull_request.rs new file mode 100644 index 0000000000..1cd7d5b64a --- /dev/null +++ b/codex-rs/app-server-protocol/src/protocol/v2/pull_request.rs @@ -0,0 +1,144 @@ +use schemars::JsonSchema; +use serde::Deserialize; +use serde::Serialize; +use ts_rs::TS; + +/// In-band outcome of a pull-request query. +/// +/// Pull-request data is sourced asynchronously and may be unavailable (for +/// example when no GitHub remote is configured or the backing processor has not +/// been implemented yet). Rather than surfacing these outcomes as JSON-RPC +/// errors, every pull-request response carries a [`PullRequestQueryState`] so +/// clients can render empty/loading/degraded states in-band. +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(rename_all = "camelCase", export_to = "v2/")] +pub enum PullRequestQueryState { + /// The response data reflects the current, fully-loaded state. + Ready, + /// The response data is a partial snapshot while a refresh is in flight. + Loading, + /// Pull-request data could not be produced; see the accompanying message. + Unavailable, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(rename_all = "camelCase", export_to = "v2/")] +pub enum PullRequestState { + Open, + Closed, + Merged, + Draft, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(rename_all = "camelCase", export_to = "v2/")] +pub enum PullRequestReviewDecision { + Approved, + ChangesRequested, + ReviewRequired, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequest { + pub id: String, + #[ts(type = "number")] + pub number: i64, + pub title: String, + pub state: PullRequestState, + pub is_draft: bool, + #[ts(type = "string | null")] + pub author: Option, + #[ts(type = "string | null")] + pub url: Option, + #[ts(type = "string | null")] + pub repository: Option, + #[ts(type = "string | null")] + pub head_ref: Option, + #[ts(type = "string | null")] + pub base_ref: Option, + pub review_decision: Option, + #[ts(type = "number")] + pub created_at: i64, + #[ts(type = "number")] + pub updated_at: i64, +} + +/// Aggregate view of the pull requests relevant to the current repository. +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestOverview { + pub total_open: u32, + pub total_draft: u32, + pub authored_by_viewer: u32, + pub awaiting_viewer_review: u32, + pub recently_updated: Vec, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestOverviewParams { + #[ts(optional = nullable)] + pub base_repo_path: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestOverviewResponse { + pub query_state: PullRequestQueryState, + pub overview: Option, + #[ts(type = "string | null")] + pub message: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestListParams { + #[ts(optional = nullable)] + pub base_repo_path: Option, + #[ts(optional = nullable)] + pub state: Option, + #[ts(optional = nullable)] + pub cursor: Option, + #[ts(optional = nullable)] + pub limit: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestListResponse { + pub query_state: PullRequestQueryState, + pub data: Vec, + pub next_cursor: Option, + #[ts(type = "string | null")] + pub message: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestReadParams { + #[ts(type = "number")] + pub number: i64, + #[ts(optional = nullable)] + pub base_repo_path: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct PullRequestReadResponse { + pub query_state: PullRequestQueryState, + pub pull_request: Option, + #[ts(type = "string | null")] + pub message: Option, +} diff --git a/codex-rs/app-server/src/message_processor.rs b/codex-rs/app-server/src/message_processor.rs index 4ebc89e20d..2b40926fcf 100644 --- a/codex-rs/app-server/src/message_processor.rs +++ b/codex-rs/app-server/src/message_processor.rs @@ -73,6 +73,10 @@ use codex_app_server_protocol::JSONRPCErrorError; use codex_app_server_protocol::JSONRPCNotification; use codex_app_server_protocol::JSONRPCRequest; use codex_app_server_protocol::JSONRPCResponse; +use codex_app_server_protocol::PullRequestListResponse; +use codex_app_server_protocol::PullRequestOverviewResponse; +use codex_app_server_protocol::PullRequestQueryState; +use codex_app_server_protocol::PullRequestReadResponse; use codex_app_server_protocol::ServerRequestPayload; use codex_app_server_protocol::experimental_required_message; use codex_arg0::Arg0DispatchPaths; @@ -103,6 +107,10 @@ use tracing::Instrument; const EXTERNAL_AUTH_REFRESH_TIMEOUT: Duration = Duration::from_secs(10); +/// In-band message returned for `pullRequest/*` queries until the backing +/// `PullRequestRequestProcessor` is implemented (todos task 1ca04ab4). +const PULL_REQUEST_UNAVAILABLE_MESSAGE: &str = "pull request data source is not available yet"; + #[derive(Clone)] struct ExternalAuthRefreshBridge { outgoing: Arc, @@ -1534,6 +1542,36 @@ impl MessageProcessor { .worktree_merge_candidate_dismiss(params) .await } + ClientRequest::PullRequestOverview { .. } => { + // The pull-request data source (PullRequestRequestProcessor) is + // not wired up yet, so report the outcome in-band rather than + // failing the JSON-RPC request. + Ok(Some( + PullRequestOverviewResponse { + query_state: PullRequestQueryState::Unavailable, + overview: None, + message: Some(PULL_REQUEST_UNAVAILABLE_MESSAGE.to_string()), + } + .into(), + )) + } + ClientRequest::PullRequestList { .. } => Ok(Some( + PullRequestListResponse { + query_state: PullRequestQueryState::Unavailable, + data: Vec::new(), + next_cursor: None, + message: Some(PULL_REQUEST_UNAVAILABLE_MESSAGE.to_string()), + } + .into(), + )), + ClientRequest::PullRequestRead { .. } => Ok(Some( + PullRequestReadResponse { + query_state: PullRequestQueryState::Unavailable, + pull_request: None, + message: Some(PULL_REQUEST_UNAVAILABLE_MESSAGE.to_string()), + } + .into(), + )), ClientRequest::MachineRegistryList { params, .. } => { self.machine_registry_processor.list(params).await }