feat(agent-call): add contract-driven mock executor
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: agent-call Executor Control API
|
||||
version: 1.0.0
|
||||
description: >-
|
||||
Internal control, query, replay, and recording hand-off API. Call execution
|
||||
enters through RabbitMQ, not HTTP.
|
||||
servers:
|
||||
- url: https://executor.internal
|
||||
security:
|
||||
- bearerAuth: []
|
||||
paths:
|
||||
/internal/v1/outbound/tasks/{task_id}/controls:
|
||||
post:
|
||||
operationId: controlTask
|
||||
summary: Persist a pause, resume, or stop barrier
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- $ref: '#/components/parameters/RequestId'
|
||||
- $ref: '#/components/parameters/IdempotencyKey'
|
||||
- $ref: '#/components/parameters/TaskId'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ControlRequest'
|
||||
responses:
|
||||
'202':
|
||||
description: Reliably persisted, not yet necessarily applied
|
||||
headers:
|
||||
Location:
|
||||
schema: {type: string}
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ControlAccepted'}
|
||||
'409': {$ref: '#/components/responses/Conflict'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'403': {$ref: '#/components/responses/Forbidden'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/internal/v1/outbound/commands/{command_id}:
|
||||
get:
|
||||
operationId: getCommand
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- $ref: '#/components/parameters/RequestId'
|
||||
- $ref: '#/components/parameters/CommandId'
|
||||
responses:
|
||||
'200':
|
||||
description: Command snapshot
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Command'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/internal/v1/outbound/calls/{call_id}:
|
||||
get:
|
||||
operationId: getCall
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- $ref: '#/components/parameters/RequestId'
|
||||
- $ref: '#/components/parameters/CallId'
|
||||
responses:
|
||||
'200':
|
||||
description: Call snapshot
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Call'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
/internal/v1/outbound/calls/{call_id}/replays:
|
||||
post:
|
||||
operationId: replayCall
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- $ref: '#/components/parameters/RequestId'
|
||||
- $ref: '#/components/parameters/IdempotencyKey'
|
||||
- $ref: '#/components/parameters/CallId'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ReplayRequest'}
|
||||
responses:
|
||||
'202':
|
||||
description: Replay persisted for bounded broker delivery
|
||||
headers:
|
||||
Location: {schema: {type: string}}
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ReplayAccepted'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
'410': {$ref: '#/components/responses/ReplayExpired'}
|
||||
/internal/v1/outbound/commands/{source_command_id}/replays:
|
||||
post:
|
||||
operationId: replayCommand
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/TenantId'
|
||||
- $ref: '#/components/parameters/RequestId'
|
||||
- $ref: '#/components/parameters/IdempotencyKey'
|
||||
- $ref: '#/components/parameters/SourceCommandId'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ReplayRequest'}
|
||||
responses:
|
||||
'202':
|
||||
description: Replay persisted for bounded broker delivery
|
||||
headers:
|
||||
Location: {schema: {type: string}}
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/ReplayAccepted'}
|
||||
'401': {$ref: '#/components/responses/Unauthorized'}
|
||||
'404': {$ref: '#/components/responses/NotFound'}
|
||||
'410': {$ref: '#/components/responses/ReplayExpired'}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
parameters:
|
||||
TenantId:
|
||||
name: X-Tenant-ID
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string}
|
||||
RequestId:
|
||||
name: X-Request-ID
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string}
|
||||
IdempotencyKey:
|
||||
name: Idempotency-Key
|
||||
in: header
|
||||
required: true
|
||||
schema: {type: string}
|
||||
TaskId:
|
||||
name: task_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {$ref: '#/components/schemas/Id'}
|
||||
CommandId:
|
||||
name: command_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {$ref: '#/components/schemas/Id'}
|
||||
SourceCommandId:
|
||||
name: source_command_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {$ref: '#/components/schemas/Id'}
|
||||
CallId:
|
||||
name: call_id
|
||||
in: path
|
||||
required: true
|
||||
schema: {$ref: '#/components/schemas/Id'}
|
||||
schemas:
|
||||
Id:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 128
|
||||
pattern: '^[^\\s/\\\\]+$'
|
||||
ControlRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [command_id, action, expected_task_revision, reason]
|
||||
properties:
|
||||
command_id: {$ref: '#/components/schemas/Id'}
|
||||
action: {type: string, enum: [pause, resume, stop]}
|
||||
expected_task_revision: {type: integer, minimum: 1}
|
||||
active_call_policy: {type: string, enum: [drain, hangup]}
|
||||
reason: {type: string, minLength: 1, maxLength: 512}
|
||||
ControlAccepted:
|
||||
type: object
|
||||
required:
|
||||
- command_id
|
||||
- tenant_id
|
||||
- tenant_key
|
||||
- task_id
|
||||
- status
|
||||
- requested_task_revision
|
||||
- accepted_at
|
||||
properties:
|
||||
command_id: {$ref: '#/components/schemas/Id'}
|
||||
tenant_id: {type: string}
|
||||
tenant_key: {type: string}
|
||||
task_id: {$ref: '#/components/schemas/Id'}
|
||||
status: {const: accepted}
|
||||
requested_task_revision: {type: integer}
|
||||
accepted_at: {type: string, format: date-time}
|
||||
ReplayRequest:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [command_id, reason]
|
||||
properties:
|
||||
command_id: {$ref: '#/components/schemas/Id'}
|
||||
reason: {type: string, minLength: 1, maxLength: 512}
|
||||
ReplayAccepted:
|
||||
type: object
|
||||
required: [command_id, status, snapshot_cutoff]
|
||||
properties:
|
||||
command_id: {$ref: '#/components/schemas/Id'}
|
||||
status: {const: accepted}
|
||||
snapshot_cutoff: {type: string, format: date-time}
|
||||
Command:
|
||||
type: object
|
||||
required:
|
||||
- command_id
|
||||
- command_type
|
||||
- tenant_id
|
||||
- tenant_key
|
||||
- status
|
||||
- aggregate_version
|
||||
properties:
|
||||
command_id: {$ref: '#/components/schemas/Id'}
|
||||
command_type: {type: string}
|
||||
tenant_id: {type: string}
|
||||
tenant_key: {type: string}
|
||||
task_id: {type: [string, 'null']}
|
||||
execution_id: {type: [string, 'null']}
|
||||
call_id: {type: [string, 'null']}
|
||||
status: {type: string}
|
||||
reason_code: {type: [string, 'null']}
|
||||
wait_reason_code: {type: [string, 'null']}
|
||||
accepted_at: {type: [string, 'null'], format: date-time}
|
||||
waiting_since: {type: [string, 'null'], format: date-time}
|
||||
admission_deadline: {type: [string, 'null'], format: date-time}
|
||||
requested_task_revision: {type: [integer, 'null']}
|
||||
applied_task_revision: {type: [integer, 'null']}
|
||||
task_state: {type: [string, 'null']}
|
||||
updated_at: {type: string, format: date-time}
|
||||
aggregate_version: {type: integer, minimum: 1}
|
||||
Call:
|
||||
type: object
|
||||
required:
|
||||
- call_id
|
||||
- execution_id
|
||||
- call_state
|
||||
- call_version
|
||||
- attempts
|
||||
- transcript
|
||||
- recordings
|
||||
- delivery
|
||||
- snapshot_at
|
||||
properties:
|
||||
call_id: {type: string}
|
||||
execution_id: {type: string}
|
||||
task_id: {type: string}
|
||||
task_item_id: {type: string}
|
||||
call_state: {type: string}
|
||||
call_version: {type: integer}
|
||||
reason_code: {type: [string, 'null']}
|
||||
outcome: {type: [string, 'null']}
|
||||
started_at: {type: [string, 'null'], format: date-time}
|
||||
ended_at: {type: [string, 'null'], format: date-time}
|
||||
duration_ms: {type: [integer, 'null']}
|
||||
attempts: {type: array, items: {type: object}}
|
||||
transcript: {type: object}
|
||||
recordings: {type: array, items: {type: object}}
|
||||
delivery: {type: object}
|
||||
snapshot_at: {type: string, format: date-time}
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Unauthorized
|
||||
content:
|
||||
application/problem+json:
|
||||
schema: {$ref: '#/components/schemas/Problem'}
|
||||
Forbidden:
|
||||
description: Forbidden
|
||||
content:
|
||||
application/problem+json:
|
||||
schema: {$ref: '#/components/schemas/Problem'}
|
||||
NotFound:
|
||||
description: Not found without cross-tenant enumeration
|
||||
content:
|
||||
application/problem+json:
|
||||
schema: {$ref: '#/components/schemas/Problem'}
|
||||
Conflict:
|
||||
description: Idempotency or revision conflict
|
||||
content:
|
||||
application/problem+json:
|
||||
schema: {$ref: '#/components/schemas/Problem'}
|
||||
ReplayExpired:
|
||||
description: Retention window expired
|
||||
content:
|
||||
application/problem+json:
|
||||
schema: {$ref: '#/components/schemas/Problem'}
|
||||
Problem:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required: [type, title, status, code, detail, request_id, retryable]
|
||||
properties:
|
||||
type: {type: string, format: uri-reference}
|
||||
title: {type: string}
|
||||
status: {type: integer}
|
||||
code: {type: string}
|
||||
detail: {type: string}
|
||||
request_id: {type: string}
|
||||
retryable: {type: boolean}
|
||||
Reference in New Issue
Block a user