openapi: 3.1.0
info:
  title: "Intent-Driven Script Flow API Extension"
  description: |
    [AC-IDS-02] 意图驱动话术流程的 API 扩展规范

    本文档描述对现有 ScriptFlow API 的扩展，增加意图驱动话术生成能力。
    这是对 `spec/ai-service/openapi.admin.yaml` 的向后兼容扩展。

    **变更摘要**:
    - 扩展 `FlowStep` schema，增加意图驱动字段
    - 所有新字段均为可选（optional），确保向后兼容
    - 复用现有的 CRUD 接口，无需新增接口

    **影响接口**:
    - POST /admin/script-flows
    - PUT /admin/script-flows/{id}
    - GET /admin/script-flows/{id}
  version: "1.0.0"
  x-contract-level: L1
  x-extends: "../ai-service/openapi.admin.yaml"

components:
  schemas:
    # [AC-IDS-01] 扩展的 FlowStep Schema
    FlowStepExtended:
      type: object
      required: [stepNo, content]
      properties:
        # === 原有字段（保持不变）===
        stepNo:
          type: integer
          description: "步骤序号（从1开始）"
          example: 1

        content:
          type: string
          description: |
            话术内容。根据 script_mode 的不同有不同含义：
            - fixed 模式：固定话术文本
            - flexible 模式：fallback 话术（LLM 生成失败时使用）
            - template 模式：话术模板（包含 {变量名} 占位符）
          example: "您好，请问怎么称呼您？"

        waitInput:
          type: boolean
          default: true
          description: "是否等待用户输入"

        timeoutSeconds:
          type: integer
          default: 120
          description: "等待超时时间（秒）"
          minimum: 10
          maximum: 600

        timeoutAction:
          type: string
          enum: [repeat, skip, transfer]
          default: repeat
          description: |
            超时后的动作：
            - repeat: 重复当前步骤
            - skip: 跳过进入下一步
            - transfer: 转人工

        nextConditions:
          type: array
          description: "条件跳转配置"
          items:
            type: object
            properties:
              keywords:
                type: array
                items:
                  type: string
                description: "关键词列表"
              pattern:
                type: string
                description: "正则表达式模式"
              gotoStep:
                type: integer
                description: "跳转到的步骤号"

        defaultNext:
          type: integer
          nullable: true
          description: "默认下一步（null 表示顺序执行）"

        # === 新增字段（意图驱动）===
        script_mode:
          type: string
          enum: [fixed, flexible, template]
          default: fixed
          description: |
            [AC-IDS-01] 话术模式：
            - fixed: 固定话术（向后兼容，默认模式）
            - flexible: 灵活话术（AI 根据意图和上下文生成）
            - template: 模板话术（AI 填充变量）
          example: "flexible"

        intent:
          type: string
          nullable: true
          description: |
            [AC-IDS-01] 步骤意图（flexible 模式必填）
            描述这一步要达到的目的，而不是具体说什么话。
          example: "获取用户真实姓名"

        intent_description:
          type: string
          nullable: true
          description: |
            [AC-IDS-01] 意图详细说明（可选）
            提供更详细的上下文信息，帮助 AI 更好地理解意图。
          example: "需要获取用户的真实姓名用于后续身份确认，如果用户已经说了姓名则直接确认，如果没说则礼貌询问"

        script_constraints:
          type: array
          items:
            type: string
          nullable: true
          description: |
            [AC-IDS-01] 话术约束条件（flexible 模式推荐配置）
            对生成话术的限制条件，例如语气、风格、长度等。
          example:
            - "必须礼貌"
            - "语气自然，不要生硬"
            - "如果用户已经说了姓名，直接确认即可"
            - "如果用户拒绝，不要强迫"

        expected_variables:
          type: array
          items:
            type: string
          nullable: true
          description: |
            [AC-IDS-01] 期望提取的变量（可选）
            这一步期望从用户输入中提取的变量名称。
          example: ["user_name"]

    # 扩展的 ScriptFlowCreate（用于创建流程）
    ScriptFlowCreateExtended:
      type: object
      required: [name, steps]
      properties:
        name:
          type: string
          description: "流程名称"
          example: "客户信息收集流程"

        description:
          type: string
          nullable: true
          description: "流程描述"
          example: "收集客户姓名、电话、需求等基本信息"

        steps:
          type: array
          description: "流程步骤列表"
          items:
            $ref: "#/components/schemas/FlowStepExtended"

        isEnabled:
          type: boolean
          default: true
          description: "是否启用"

    # 扩展的 ScriptFlowDetail（用于返回流程详情）
    ScriptFlowDetailExtended:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: "流程ID"

        name:
          type: string
          description: "流程名称"

        description:
          type: string
          nullable: true
          description: "流程描述"

        steps:
          type: array
          description: "流程步骤列表"
          items:
            $ref: "#/components/schemas/FlowStepExtended"

        isEnabled:
          type: boolean
          description: "是否启用"

        stepCount:
          type: integer
          description: "步骤数量"

        linkedRuleCount:
          type: integer
          description: "关联的意图规则数量"

        createdAt:
          type: string
          format: date-time
          description: "创建时间"

        updatedAt:
          type: string
          format: date-time
          description: "更新时间"

  examples:
    # 示例1：固定话术模式（向后兼容）
    FixedModeStep:
      summary: "固定话术步骤（传统模式）"
      value:
        stepNo: 1
        content: "您好，请问您贵姓？"
        waitInput: true
        timeoutSeconds: 60
        script_mode: "fixed"

    # 示例2：灵活话术模式
    FlexibleModeStep:
      summary: "灵活话术步骤（意图驱动）"
      value:
        stepNo: 1
        script_mode: "flexible"
        intent: "获取用户真实姓名"
        intent_description: "需要获取用户的真实姓名用于后续身份确认，如果用户已经说了姓名则直接确认，如果没说则礼貌询问"
        script_constraints:
          - "必须礼貌"
          - "语气自然，不要生硬"
          - "如果用户已经说了姓名，直接确认即可"
          - "如果用户拒绝，不要强迫"
        expected_variables:
          - "user_name"
        content: "您好，请问怎么称呼您？"  # fallback 话术
        waitInput: true
        timeoutSeconds: 60

    # 示例3：模板话术模式
    TemplateModeStep:
      summary: "模板话术步骤"
      value:
        stepNo: 2
        script_mode: "template"
        content: "好的{user_name}，请问您{inquiry_style}？"
        intent: "询问用户需求"
        script_constraints:
          - "根据用户姓名调整称呼方式"
          - "询问方式要自然"
        expected_variables:
          - "user_requirement"
        waitInput: true

    # 示例4：完整流程（混合模式）
    MixedModeFlow:
      summary: "混合模式流程（包含固定、灵活、模板三种步骤）"
      value:
        name: "客户信息收集流程"
        description: "收集客户基本信息并了解需求"
        steps:
          - stepNo: 1
            script_mode: "fixed"
            content: "您好，欢迎咨询！"
            waitInput: false

          - stepNo: 2
            script_mode: "flexible"
            intent: "获取用户姓名"
            intent_description: "礼貌询问用户姓名"
            script_constraints:
              - "必须礼貌"
              - "语气自然"
            content: "请问怎么称呼您？"
            waitInput: true
            expected_variables: ["user_name"]

          - stepNo: 3
            script_mode: "template"
            content: "好的{user_name}，请问您有什么需要帮助的吗？"
            intent: "询问用户需求"
            waitInput: true
            expected_variables: ["user_requirement"]

# 接口路径说明（复用现有接口，无需新增）
paths:
  /admin/script-flows:
    post:
      summary: "创建话术流程"
      description: |
        [AC-IDS-02] 创建新的话术流程。
        支持意图驱动的步骤配置（通过 FlowStepExtended schema）。
      operationId: createScriptFlow
      parameters:
        - $ref: "../ai-service/openapi.admin.yaml#/components/parameters/XTenantId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ScriptFlowCreateExtended"
            examples:
              mixedMode:
                $ref: "#/components/examples/MixedModeFlow"
      responses:
        "201":
          description: "创建成功"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScriptFlowDetailExtended"
        "400":
          description: "请求参数错误"
        "401":
          $ref: "../ai-service/openapi.admin.yaml#/components/responses/Unauthorized"

  /admin/script-flows/{id}:
    get:
      summary: "获取话术流程详情"
      description: |
        [AC-IDS-02] 获取指定流程的详细信息。
        返回包含意图驱动字段的完整步骤配置。
      operationId: getScriptFlow
      parameters:
        - $ref: "../ai-service/openapi.admin.yaml#/components/parameters/XTenantId"
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: "获取成功"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScriptFlowDetailExtended"
        "404":
          description: "流程不存在"

    put:
      summary: "更新话术流程"
      description: |
        [AC-IDS-02] 更新现有流程的配置。
        支持修改步骤的话术模式和意图配置。
      operationId: updateScriptFlow
      parameters:
        - $ref: "../ai-service/openapi.admin.yaml#/components/parameters/XTenantId"
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ScriptFlowCreateExtended"
      responses:
        "200":
          description: "更新成功"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ScriptFlowDetailExtended"
        "404":
          description: "流程不存在"

# 向后兼容性说明
x-compatibility:
  backward-compatible: true
  migration-required: false
  notes: |
    本扩展完全向后兼容：

    1. **数据兼容性**
       - 所有新字段均为可选（nullable）
       - 未指定 script_mode 时默认为 'fixed'
       - 现有流程数据无需迁移即可正常工作

    2. **API 兼容性**
       - 复用现有接口，无需修改接口路径
       - 请求体向后兼容（新字段可选）
       - 响应体向后兼容（新字段可能为 null）

    3. **客户端兼容性**
       - 旧版客户端可以忽略新字段
       - 新版客户端可以处理缺失的新字段

    4. **执行兼容性**
       - 未指定 script_mode 的步骤按 fixed 模式执行
       - 保持与现有流程完全相同的行为

# 验收标准映射
x-acceptance-criteria:
  - id: AC-IDS-01
    description: "扩展 ScriptFlow 数据模型"
    schema: FlowStepExtended
    status: defined

  - id: AC-IDS-02
    description: "扩展 Admin API 契约"
    paths:
      - POST /admin/script-flows
      - PUT /admin/script-flows/{id}
      - GET /admin/script-flows/{id}
    status: defined
