560 lines
14 KiB
YAML
560 lines
14 KiB
YAML
openapi: 3.0.3
|
||
info:
|
||
title: Petstore Booking Agent M0 API
|
||
version: 0.1.0
|
||
description: |
|
||
智能预约 M0 冻结契约。M0 只生成并回填预约草稿,不注册 confirm endpoint,
|
||
不直接创建 Appointment。除鉴权拦截器的 HTTP 401 外,当前 Petstore 客户端以
|
||
响应体 code 作为业务结果;实现不得借本功能顺带重构全局响应语义。
|
||
security:
|
||
- bearerAuth: []
|
||
x-contract-status: frozen-for-m0
|
||
x-business-error-codes:
|
||
- UNAUTHENTICATED
|
||
- FORBIDDEN
|
||
- AGENT_DISABLED
|
||
- STORE_NOT_FOUND
|
||
- SESSION_NOT_FOUND
|
||
- SESSION_EXPIRED
|
||
- SESSION_TERMINAL
|
||
- DRAFT_VERSION_CONFLICT
|
||
- INVALID_INPUT
|
||
- INVALID_AUDIO
|
||
- AUDIO_TOO_LARGE
|
||
- RATE_LIMITED
|
||
- AGENT_UNAVAILABLE
|
||
- ASR_UNAVAILABLE
|
||
paths:
|
||
/api/booking-agent/sessions:
|
||
post:
|
||
operationId: createBookingAgentSession
|
||
summary: 创建 customer 智能预约会话
|
||
description: |
|
||
仅已登录 customer。M0 要求先在普通预约页选定门店;entrySource 由服务端固定为
|
||
appointment_create,不从客户端接收。
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/CreateSessionRequest'
|
||
responses:
|
||
'200':
|
||
description: 成功或带业务 code 的可理解失败
|
||
content:
|
||
application/json:
|
||
schema:
|
||
oneOf:
|
||
- $ref: '#/components/schemas/SessionEnvelope'
|
||
- $ref: '#/components/schemas/ErrorEnvelope'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthenticated'
|
||
|
||
/api/booking-agent/sessions/{sessionId}/messages:
|
||
post:
|
||
operationId: submitBookingAgentMessage
|
||
summary: 提交一轮已确认文字并刷新草稿
|
||
parameters:
|
||
- $ref: '#/components/parameters/SessionId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/SubmitMessageRequest'
|
||
responses:
|
||
'200':
|
||
description: 成功或带业务 code 的可理解失败
|
||
content:
|
||
application/json:
|
||
schema:
|
||
oneOf:
|
||
- $ref: '#/components/schemas/SessionEnvelope'
|
||
- $ref: '#/components/schemas/ErrorEnvelope'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthenticated'
|
||
|
||
/api/booking-agent/sessions/{sessionId}/transcriptions:
|
||
post:
|
||
operationId: transcribeBookingAgentAudio
|
||
summary: 转写当前 customer 会话的一段短音频
|
||
description: |
|
||
只做语音转写,不自动提交消息。客户端必须把返回文字放回可编辑输入框,用户确认后
|
||
再调用 messages。后端从 session 解析门店和 customer 范围,不接受客户端上传词表。
|
||
parameters:
|
||
- $ref: '#/components/parameters/SessionId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
multipart/form-data:
|
||
schema:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- audio
|
||
properties:
|
||
audio:
|
||
type: string
|
||
format: binary
|
||
description: 单段不超过 60 秒、3 MB;MIME 与真实文件头必须一致
|
||
responses:
|
||
'200':
|
||
description: 成功或带业务 code 的可理解失败
|
||
content:
|
||
application/json:
|
||
schema:
|
||
oneOf:
|
||
- $ref: '#/components/schemas/TranscriptionEnvelope'
|
||
- $ref: '#/components/schemas/ErrorEnvelope'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthenticated'
|
||
|
||
/api/booking-agent/sessions/{sessionId}/fallback:
|
||
post:
|
||
operationId: handoffBookingAgentDraft
|
||
summary: 结束助手并返回可回填普通表单的已验证草稿
|
||
parameters:
|
||
- $ref: '#/components/parameters/SessionId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/DraftVersionRequest'
|
||
responses:
|
||
'200':
|
||
description: 成功或带业务 code 的可理解失败
|
||
content:
|
||
application/json:
|
||
schema:
|
||
oneOf:
|
||
- $ref: '#/components/schemas/HandoffEnvelope'
|
||
- $ref: '#/components/schemas/ErrorEnvelope'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthenticated'
|
||
|
||
/api/booking-agent/sessions/{sessionId}:
|
||
delete:
|
||
operationId: cancelBookingAgentSession
|
||
summary: 结束本人智能预约会话
|
||
parameters:
|
||
- $ref: '#/components/parameters/SessionId'
|
||
responses:
|
||
'200':
|
||
description: 成功或带业务 code 的可理解失败
|
||
content:
|
||
application/json:
|
||
schema:
|
||
oneOf:
|
||
- $ref: '#/components/schemas/CancelEnvelope'
|
||
- $ref: '#/components/schemas/ErrorEnvelope'
|
||
'401':
|
||
$ref: '#/components/responses/Unauthenticated'
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: PetstoreSessionToken
|
||
|
||
parameters:
|
||
SessionId:
|
||
name: sessionId
|
||
in: path
|
||
required: true
|
||
description: 不可预测的 UUID;仍必须和 current.userId 联合查询
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
|
||
responses:
|
||
Unauthenticated:
|
||
description: session token 缺失、失效或账号权限已变化
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorEnvelope'
|
||
example:
|
||
code: 401
|
||
message: 登录已失效,请重新登录
|
||
bizCode: UNAUTHENTICATED
|
||
|
||
schemas:
|
||
CreateSessionRequest:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- storeId
|
||
properties:
|
||
storeId:
|
||
type: integer
|
||
format: int64
|
||
minimum: 1
|
||
|
||
SubmitMessageRequest:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- inputType
|
||
- text
|
||
- draftVersion
|
||
properties:
|
||
inputType:
|
||
type: string
|
||
enum:
|
||
- text
|
||
- voice
|
||
text:
|
||
type: string
|
||
minLength: 1
|
||
maxLength: 500
|
||
description: 用户确认后的当轮输入;服务端不得写日志或长期持久化
|
||
draftVersion:
|
||
type: integer
|
||
minimum: 0
|
||
|
||
DraftVersionRequest:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- draftVersion
|
||
properties:
|
||
draftVersion:
|
||
type: integer
|
||
minimum: 0
|
||
|
||
BookingAgentStatus:
|
||
type: string
|
||
enum:
|
||
- collecting
|
||
- proposing
|
||
- confirmable
|
||
- fallback
|
||
- expired
|
||
- cancelled
|
||
|
||
MissingField:
|
||
type: string
|
||
enum:
|
||
- pet
|
||
- service
|
||
- date
|
||
- time
|
||
|
||
BookingDraft:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- storeId
|
||
- storeName
|
||
- petId
|
||
- petName
|
||
- petType
|
||
- serviceTypeId
|
||
- serviceType
|
||
- durationMinutes
|
||
- dateConstraint
|
||
- timeWindow
|
||
- appointmentTime
|
||
- appointmentEndTime
|
||
- remark
|
||
- missingFields
|
||
properties:
|
||
storeId:
|
||
type: integer
|
||
format: int64
|
||
storeName:
|
||
type: string
|
||
maxLength: 128
|
||
petId:
|
||
type: integer
|
||
format: int64
|
||
nullable: true
|
||
petName:
|
||
type: string
|
||
nullable: true
|
||
maxLength: 64
|
||
petType:
|
||
type: string
|
||
nullable: true
|
||
maxLength: 32
|
||
serviceTypeId:
|
||
type: integer
|
||
format: int64
|
||
nullable: true
|
||
serviceType:
|
||
type: string
|
||
nullable: true
|
||
maxLength: 64
|
||
durationMinutes:
|
||
type: integer
|
||
nullable: true
|
||
minimum: 1
|
||
dateConstraint:
|
||
type: string
|
||
format: date
|
||
nullable: true
|
||
timeWindow:
|
||
$ref: '#/components/schemas/TimeWindow'
|
||
appointmentTime:
|
||
$ref: '#/components/schemas/NullableLocalDateTime'
|
||
appointmentEndTime:
|
||
$ref: '#/components/schemas/NullableLocalDateTime'
|
||
remark:
|
||
type: string
|
||
nullable: true
|
||
maxLength: 200
|
||
missingFields:
|
||
type: array
|
||
uniqueItems: true
|
||
items:
|
||
$ref: '#/components/schemas/MissingField'
|
||
|
||
TimeWindow:
|
||
type: object
|
||
nullable: true
|
||
additionalProperties: false
|
||
required:
|
||
- start
|
||
- end
|
||
properties:
|
||
start:
|
||
type: string
|
||
nullable: true
|
||
pattern: '^(?:[01]\d|2[0-3]):[0-5]\d$'
|
||
end:
|
||
type: string
|
||
nullable: true
|
||
pattern: '^(?:[01]\d|2[0-3]):[0-5]\d$'
|
||
|
||
SlotOption:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- startTime
|
||
- endTime
|
||
- label
|
||
properties:
|
||
startTime:
|
||
$ref: '#/components/schemas/LocalDateTime'
|
||
endTime:
|
||
$ref: '#/components/schemas/LocalDateTime'
|
||
label:
|
||
type: string
|
||
maxLength: 64
|
||
|
||
QuickReply:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- type
|
||
- value
|
||
- label
|
||
properties:
|
||
type:
|
||
type: string
|
||
enum:
|
||
- pet
|
||
- service
|
||
- slot
|
||
- date
|
||
- fallback
|
||
value:
|
||
type: string
|
||
maxLength: 128
|
||
label:
|
||
type: string
|
||
maxLength: 64
|
||
|
||
SessionView:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- sessionId
|
||
- status
|
||
- assistantMessage
|
||
- draft
|
||
- slotOptions
|
||
- quickReplies
|
||
- confirmable
|
||
- draftVersion
|
||
- expiresAt
|
||
properties:
|
||
sessionId:
|
||
type: string
|
||
format: uuid
|
||
status:
|
||
$ref: '#/components/schemas/BookingAgentStatus'
|
||
assistantMessage:
|
||
type: string
|
||
maxLength: 300
|
||
description: 服务端模板渲染,不包含模型思考或供应商错误
|
||
draft:
|
||
$ref: '#/components/schemas/BookingDraft'
|
||
slotOptions:
|
||
type: array
|
||
maxItems: 3
|
||
items:
|
||
$ref: '#/components/schemas/SlotOption'
|
||
quickReplies:
|
||
type: array
|
||
maxItems: 10
|
||
items:
|
||
$ref: '#/components/schemas/QuickReply'
|
||
confirmable:
|
||
type: boolean
|
||
draftVersion:
|
||
type: integer
|
||
minimum: 0
|
||
expiresAt:
|
||
$ref: '#/components/schemas/LocalDateTime'
|
||
|
||
LocalDateTime:
|
||
type: string
|
||
pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$'
|
||
description: Asia/Shanghai 下的本地日期时间,格式 yyyy-MM-ddTHH:mm:ss
|
||
|
||
NullableLocalDateTime:
|
||
type: string
|
||
nullable: true
|
||
pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$'
|
||
description: null 或 Asia/Shanghai 下的本地日期时间;非空时格式为 yyyy-MM-ddTHH:mm:ss
|
||
|
||
HandoffData:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- source
|
||
- draft
|
||
properties:
|
||
source:
|
||
type: string
|
||
enum:
|
||
- booking-agent-m0
|
||
draft:
|
||
$ref: '#/components/schemas/BookingDraft'
|
||
|
||
TranscriptionData:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- text
|
||
properties:
|
||
text:
|
||
type: string
|
||
maxLength: 500
|
||
description: 可编辑转写;不返回供应商原始响应或外部 request ID
|
||
|
||
CancelData:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- sessionId
|
||
- status
|
||
properties:
|
||
sessionId:
|
||
type: string
|
||
format: uuid
|
||
status:
|
||
type: string
|
||
enum:
|
||
- cancelled
|
||
|
||
SessionEnvelope:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- code
|
||
- data
|
||
properties:
|
||
code:
|
||
type: integer
|
||
enum:
|
||
- 200
|
||
data:
|
||
$ref: '#/components/schemas/SessionView'
|
||
|
||
TranscriptionEnvelope:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- code
|
||
- data
|
||
properties:
|
||
code:
|
||
type: integer
|
||
enum:
|
||
- 200
|
||
data:
|
||
$ref: '#/components/schemas/TranscriptionData'
|
||
|
||
HandoffEnvelope:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- code
|
||
- data
|
||
properties:
|
||
code:
|
||
type: integer
|
||
enum:
|
||
- 200
|
||
data:
|
||
$ref: '#/components/schemas/HandoffData'
|
||
|
||
CancelEnvelope:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- code
|
||
- data
|
||
properties:
|
||
code:
|
||
type: integer
|
||
enum:
|
||
- 200
|
||
data:
|
||
$ref: '#/components/schemas/CancelData'
|
||
|
||
ErrorEnvelope:
|
||
type: object
|
||
additionalProperties: false
|
||
required:
|
||
- code
|
||
- message
|
||
- bizCode
|
||
properties:
|
||
code:
|
||
type: integer
|
||
enum:
|
||
- 400
|
||
- 401
|
||
- 403
|
||
- 404
|
||
- 409
|
||
- 410
|
||
- 413
|
||
- 429
|
||
- 503
|
||
message:
|
||
type: string
|
||
maxLength: 200
|
||
bizCode:
|
||
type: string
|
||
enum:
|
||
- UNAUTHENTICATED
|
||
- FORBIDDEN
|
||
- AGENT_DISABLED
|
||
- STORE_NOT_FOUND
|
||
- SESSION_NOT_FOUND
|
||
- SESSION_EXPIRED
|
||
- SESSION_TERMINAL
|
||
- DRAFT_VERSION_CONFLICT
|
||
- INVALID_INPUT
|
||
- INVALID_AUDIO
|
||
- AUDIO_TOO_LARGE
|
||
- RATE_LIMITED
|
||
- AGENT_UNAVAILABLE
|
||
- ASR_UNAVAILABLE
|