Skip to content

Commit 17045e8

Browse files
andriypolanskiandriy-polanskicursoragent
authored
fix(openapi): document agent/pending-actions approval-queue routes (#9307) (#9426)
The list/propose/decide pending-actions routes were live (and MCP-backed) but absent from OpenAPI while agent/audit-feed was documented. Add response + propose request schemas mirroring the MCP tool shapes, register the three paths, regenerate openapi.json, and add a parity regression test. Replaces conflict-closed #9416 on current main. Co-authored-by: Andriy Polanski <andriy.polanski@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 4b761fa commit 17045e8

5 files changed

Lines changed: 543 additions & 4 deletions

File tree

apps/loopover-ui/public/openapi.json

Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15386,6 +15386,210 @@
1538615386
"nullable": true
1538715387
}
1538815388
}
15389+
},
15390+
"ListPendingActionsResponse": {
15391+
"type": "object",
15392+
"properties": {
15393+
"repoFullName": {
15394+
"type": "string"
15395+
},
15396+
"status": {
15397+
"type": "string"
15398+
},
15399+
"pendingActions": {
15400+
"type": "array",
15401+
"items": {
15402+
"type": "object",
15403+
"properties": {
15404+
"id": {
15405+
"type": "string"
15406+
},
15407+
"actionClass": {
15408+
"type": "string"
15409+
},
15410+
"pullNumber": {
15411+
"type": "number"
15412+
},
15413+
"status": {
15414+
"type": "string"
15415+
},
15416+
"autonomyLevel": {
15417+
"type": "string"
15418+
},
15419+
"reason": {
15420+
"type": "string",
15421+
"nullable": true
15422+
},
15423+
"decidedBy": {
15424+
"type": "string",
15425+
"nullable": true
15426+
},
15427+
"decidedAt": {
15428+
"type": "string",
15429+
"nullable": true
15430+
},
15431+
"createdAt": {
15432+
"type": "string"
15433+
}
15434+
},
15435+
"required": [
15436+
"id",
15437+
"actionClass",
15438+
"pullNumber",
15439+
"status",
15440+
"autonomyLevel",
15441+
"reason",
15442+
"decidedBy",
15443+
"decidedAt",
15444+
"createdAt"
15445+
]
15446+
}
15447+
}
15448+
}
15449+
},
15450+
"ProposeActionRequest": {
15451+
"type": "object",
15452+
"properties": {
15453+
"pullNumber": {
15454+
"type": "integer",
15455+
"minimum": 0,
15456+
"exclusiveMinimum": true
15457+
},
15458+
"actionClass": {
15459+
"type": "string",
15460+
"enum": [
15461+
"review",
15462+
"request_changes",
15463+
"approve",
15464+
"merge",
15465+
"close",
15466+
"label",
15467+
"review_state_label"
15468+
]
15469+
},
15470+
"reason": {
15471+
"type": "string",
15472+
"maxLength": 500
15473+
},
15474+
"label": {
15475+
"type": "string",
15476+
"minLength": 1,
15477+
"maxLength": 100
15478+
},
15479+
"reviewBody": {
15480+
"type": "string",
15481+
"maxLength": 60000
15482+
},
15483+
"mergeMethod": {
15484+
"type": "string",
15485+
"enum": [
15486+
"merge",
15487+
"squash",
15488+
"rebase"
15489+
]
15490+
},
15491+
"closeComment": {
15492+
"type": "string",
15493+
"maxLength": 60000
15494+
}
15495+
},
15496+
"required": [
15497+
"pullNumber",
15498+
"actionClass"
15499+
]
15500+
},
15501+
"ProposeActionResponse": {
15502+
"type": "object",
15503+
"properties": {
15504+
"created": {
15505+
"type": "boolean"
15506+
},
15507+
"action": {
15508+
"type": "object",
15509+
"properties": {
15510+
"id": {
15511+
"type": "string"
15512+
},
15513+
"actionClass": {
15514+
"type": "string"
15515+
},
15516+
"pullNumber": {
15517+
"type": "number"
15518+
},
15519+
"status": {
15520+
"type": "string"
15521+
},
15522+
"reason": {
15523+
"type": "string",
15524+
"nullable": true
15525+
}
15526+
},
15527+
"required": [
15528+
"id",
15529+
"actionClass",
15530+
"pullNumber",
15531+
"status",
15532+
"reason"
15533+
]
15534+
}
15535+
}
15536+
},
15537+
"DecidePendingActionResponse": {
15538+
"type": "object",
15539+
"properties": {
15540+
"status": {
15541+
"type": "string"
15542+
},
15543+
"executionOutcome": {
15544+
"type": "string"
15545+
},
15546+
"action": {
15547+
"type": "object",
15548+
"properties": {
15549+
"id": {
15550+
"type": "string"
15551+
},
15552+
"actionClass": {
15553+
"type": "string"
15554+
},
15555+
"pullNumber": {
15556+
"type": "number"
15557+
},
15558+
"status": {
15559+
"type": "string"
15560+
},
15561+
"autonomyLevel": {
15562+
"type": "string"
15563+
},
15564+
"reason": {
15565+
"type": "string",
15566+
"nullable": true
15567+
},
15568+
"decidedBy": {
15569+
"type": "string",
15570+
"nullable": true
15571+
},
15572+
"decidedAt": {
15573+
"type": "string",
15574+
"nullable": true
15575+
},
15576+
"createdAt": {
15577+
"type": "string"
15578+
}
15579+
},
15580+
"required": [
15581+
"id",
15582+
"actionClass",
15583+
"pullNumber",
15584+
"status",
15585+
"autonomyLevel",
15586+
"reason",
15587+
"decidedBy",
15588+
"decidedAt",
15589+
"createdAt"
15590+
]
15591+
}
15592+
}
1538915593
}
1539015594
},
1539115595
"parameters": {},
@@ -20279,6 +20483,186 @@
2027920483
}
2028020484
]
2028120485
}
20486+
},
20487+
"/v1/repos/{owner}/{repo}/agent/pending-actions": {
20488+
"get": {
20489+
"summary": "Maintainer-scoped agent approval queue of pending staged actions",
20490+
"parameters": [
20491+
{
20492+
"schema": {
20493+
"type": "string"
20494+
},
20495+
"required": true,
20496+
"name": "owner",
20497+
"in": "path"
20498+
},
20499+
{
20500+
"schema": {
20501+
"type": "string"
20502+
},
20503+
"required": true,
20504+
"name": "repo",
20505+
"in": "path"
20506+
}
20507+
],
20508+
"responses": {
20509+
"200": {
20510+
"description": "Pending agent actions staged for maintainer approval (#784), mirroring the loopover_list_pending_actions MCP tool.",
20511+
"content": {
20512+
"application/json": {
20513+
"schema": {
20514+
"$ref": "#/components/schemas/ListPendingActionsResponse"
20515+
}
20516+
}
20517+
}
20518+
},
20519+
"403": {
20520+
"description": "Insufficient role"
20521+
}
20522+
},
20523+
"security": [
20524+
{
20525+
"LoopOverBearer": []
20526+
},
20527+
{
20528+
"LoopOverSessionCookie": []
20529+
}
20530+
]
20531+
},
20532+
"post": {
20533+
"summary": "Stage an agent action into the approval queue for maintainer review",
20534+
"parameters": [
20535+
{
20536+
"schema": {
20537+
"type": "string"
20538+
},
20539+
"required": true,
20540+
"name": "owner",
20541+
"in": "path"
20542+
},
20543+
{
20544+
"schema": {
20545+
"type": "string"
20546+
},
20547+
"required": true,
20548+
"name": "repo",
20549+
"in": "path"
20550+
}
20551+
],
20552+
"requestBody": {
20553+
"content": {
20554+
"application/json": {
20555+
"schema": {
20556+
"$ref": "#/components/schemas/ProposeActionRequest"
20557+
}
20558+
}
20559+
}
20560+
},
20561+
"responses": {
20562+
"200": {
20563+
"description": "The staged (or already-present) pending action (#6744), mirroring the loopover_propose_action MCP tool VERBATIM.",
20564+
"content": {
20565+
"application/json": {
20566+
"schema": {
20567+
"$ref": "#/components/schemas/ProposeActionResponse"
20568+
}
20569+
}
20570+
}
20571+
},
20572+
"400": {
20573+
"description": "Malformed propose-action request body"
20574+
},
20575+
"403": {
20576+
"description": "Insufficient role"
20577+
},
20578+
"409": {
20579+
"description": "The LoopOver App is not installed on this repository"
20580+
}
20581+
},
20582+
"security": [
20583+
{
20584+
"LoopOverBearer": []
20585+
},
20586+
{
20587+
"LoopOverSessionCookie": []
20588+
}
20589+
]
20590+
}
20591+
},
20592+
"/v1/repos/{owner}/{repo}/agent/pending-actions/{id}/{decision}": {
20593+
"post": {
20594+
"summary": "Accept (execute) or reject a staged agent action in the approval queue",
20595+
"parameters": [
20596+
{
20597+
"schema": {
20598+
"type": "string"
20599+
},
20600+
"required": true,
20601+
"name": "owner",
20602+
"in": "path"
20603+
},
20604+
{
20605+
"schema": {
20606+
"type": "string"
20607+
},
20608+
"required": true,
20609+
"name": "repo",
20610+
"in": "path"
20611+
},
20612+
{
20613+
"schema": {
20614+
"type": "string"
20615+
},
20616+
"required": true,
20617+
"name": "id",
20618+
"in": "path"
20619+
},
20620+
{
20621+
"schema": {
20622+
"type": "string",
20623+
"enum": [
20624+
"accept",
20625+
"reject"
20626+
]
20627+
},
20628+
"required": true,
20629+
"name": "decision",
20630+
"in": "path"
20631+
}
20632+
],
20633+
"responses": {
20634+
"200": {
20635+
"description": "The decided action's outcome (#779): accept executes it live, reject cancels it. Mirrors the loopover_decide_pending_action MCP tool.",
20636+
"content": {
20637+
"application/json": {
20638+
"schema": {
20639+
"$ref": "#/components/schemas/DecidePendingActionResponse"
20640+
}
20641+
}
20642+
}
20643+
},
20644+
"400": {
20645+
"description": "Decision is not 'accept' or 'reject'"
20646+
},
20647+
"403": {
20648+
"description": "Insufficient role"
20649+
},
20650+
"404": {
20651+
"description": "Pending action not found for this repository"
20652+
},
20653+
"409": {
20654+
"description": "Pending action was already decided"
20655+
}
20656+
},
20657+
"security": [
20658+
{
20659+
"LoopOverBearer": []
20660+
},
20661+
{
20662+
"LoopOverSessionCookie": []
20663+
}
20664+
]
20665+
}
2028220666
}
2028320667
},
2028420668
"servers": [

0 commit comments

Comments
 (0)