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