瀏覽代碼

feat: 实现完整服务

huangzhichao 1 月之前
父節點
當前提交
c7faa1ac19

+ 1 - 0
package.json

@@ -24,6 +24,7 @@
     "@nestjs/common": "^10.0.0",
     "@nestjs/core": "^10.0.0",
     "@nestjs/platform-express": "^10.0.0",
+    "@nestjs/swagger": "^11.1.3",
     "axios": "^1.8.4",
     "class-transformer": "^0.5.1",
     "class-validator": "^0.14.1",

+ 79 - 0
pnpm-lock.yaml

@@ -20,6 +20,9 @@ importers:
       '@nestjs/platform-express':
         specifier: ^10.0.0
         version: 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.15)
+      '@nestjs/swagger':
+        specifier: ^11.1.3
+        version: 11.1.3(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.15)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
       axios:
         specifier: ^1.8.4
         version: 1.8.4
@@ -446,6 +449,9 @@ packages:
     resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
     engines: {node: '>=8'}
 
+  '@microsoft/tsdoc@0.15.1':
+    resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
+
   '@nestjs/axios@4.0.0':
     resolution: {integrity: sha512-1cB+Jyltu/uUPNQrpUimRHEQHrnQrpLzVj6dU3dgn6iDDDdahr10TgHFGTmw5VuJ9GzKZsCLDL78VSwJAs/9JQ==}
     peerDependencies:
@@ -496,6 +502,19 @@ packages:
       '@nestjs/websockets':
         optional: true
 
+  '@nestjs/mapped-types@2.1.0':
+    resolution: {integrity: sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==}
+    peerDependencies:
+      '@nestjs/common': ^10.0.0 || ^11.0.0
+      class-transformer: ^0.4.0 || ^0.5.0
+      class-validator: ^0.13.0 || ^0.14.0
+      reflect-metadata: ^0.1.12 || ^0.2.0
+    peerDependenciesMeta:
+      class-transformer:
+        optional: true
+      class-validator:
+        optional: true
+
   '@nestjs/platform-express@10.4.15':
     resolution: {integrity: sha512-63ZZPkXHjoDyO7ahGOVcybZCRa7/Scp6mObQKjcX/fTEq1YJeU75ELvMsuQgc8U2opMGOBD7GVuc4DV0oeDHoA==}
     peerDependencies:
@@ -507,6 +526,23 @@ packages:
     peerDependencies:
       typescript: '>=4.8.2'
 
+  '@nestjs/swagger@11.1.3':
+    resolution: {integrity: sha512-vhbW/Xu05Diti/EwYQp3Ea7Hj2M++wiakCcxqUUDA2n7NvCZC8LKsrcGynw6/x/lugdXyklYS+s2FhdAfeAikg==}
+    peerDependencies:
+      '@fastify/static': ^8.0.0
+      '@nestjs/common': ^11.0.1
+      '@nestjs/core': ^11.0.1
+      class-transformer: '*'
+      class-validator: '*'
+      reflect-metadata: ^0.1.12 || ^0.2.0
+    peerDependenciesMeta:
+      '@fastify/static':
+        optional: true
+      class-transformer:
+        optional: true
+      class-validator:
+        optional: true
+
   '@nestjs/testing@10.4.15':
     resolution: {integrity: sha512-eGlWESkACMKti+iZk1hs6FUY/UqObmMaa8HAN9JLnaYkoLf1Jeh+EuHlGnfqo/Rq77oznNLIyaA3PFjrFDlNUg==}
     peerDependencies:
@@ -548,6 +584,9 @@ packages:
   '@rtsao/scc@1.1.0':
     resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
 
+  '@scarf/scarf@1.4.0':
+    resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==}
+
   '@sinclair/typebox@0.27.8':
     resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
 
@@ -2498,6 +2537,10 @@ packages:
   path-to-regexp@3.3.0:
     resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
 
+  path-to-regexp@8.2.0:
+    resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
+    engines: {node: '>=16'}
+
   path-type@4.0.0:
     resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
     engines: {node: '>=8'}
@@ -2883,6 +2926,9 @@ packages:
     resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
     engines: {node: '>= 0.4'}
 
+  swagger-ui-dist@5.21.0:
+    resolution: {integrity: sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==}
+
   symbol-observable@4.0.0:
     resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==}
     engines: {node: '>=0.10'}
@@ -3710,6 +3756,8 @@ snapshots:
 
   '@lukeed/csprng@1.1.0': {}
 
+  '@microsoft/tsdoc@0.15.1': {}
+
   '@nestjs/axios@4.0.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.8.4)(rxjs@7.8.2)':
     dependencies:
       '@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -3769,6 +3817,14 @@ snapshots:
     transitivePeerDependencies:
       - encoding
 
+  '@nestjs/mapped-types@2.1.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)':
+    dependencies:
+      '@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
+      reflect-metadata: 0.2.2
+    optionalDependencies:
+      class-transformer: 0.5.1
+      class-validator: 0.14.1
+
   '@nestjs/platform-express@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.15)':
     dependencies:
       '@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -3803,6 +3859,21 @@ snapshots:
     transitivePeerDependencies:
       - chokidar
 
+  '@nestjs/swagger@11.1.3(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.15)(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)':
+    dependencies:
+      '@microsoft/tsdoc': 0.15.1
+      '@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
+      '@nestjs/core': 10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.2)
+      '@nestjs/mapped-types': 2.1.0(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)
+      js-yaml: 4.1.0
+      lodash: 4.17.21
+      path-to-regexp: 8.2.0
+      reflect-metadata: 0.2.2
+      swagger-ui-dist: 5.21.0
+    optionalDependencies:
+      class-transformer: 0.5.1
+      class-validator: 0.14.1
+
   '@nestjs/testing@10.4.15(@nestjs/common@10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.15)(@nestjs/platform-express@10.4.15)':
     dependencies:
       '@nestjs/common': 10.4.15(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -3838,6 +3909,8 @@ snapshots:
 
   '@rtsao/scc@1.1.0': {}
 
+  '@scarf/scarf@1.4.0': {}
+
   '@sinclair/typebox@0.27.8': {}
 
   '@sinonjs/commons@3.0.1':
@@ -6227,6 +6300,8 @@ snapshots:
 
   path-to-regexp@3.3.0: {}
 
+  path-to-regexp@8.2.0: {}
+
   path-type@4.0.0: {}
 
   picocolors@1.1.1: {}
@@ -6652,6 +6727,10 @@ snapshots:
 
   supports-preserve-symlinks-flag@1.0.0: {}
 
+  swagger-ui-dist@5.21.0:
+    dependencies:
+      '@scarf/scarf': 1.4.0
+
   symbol-observable@4.0.0: {}
 
   synckit@0.10.2:

+ 12 - 0
src/decorators/cors.decorator.ts

@@ -0,0 +1,12 @@
+import { applyDecorators, Header, SetMetadata } from '@nestjs/common'
+
+export function Cors() {
+  return applyDecorators(
+    Header('Access-Control-Allow-Origin', '*'),
+    Header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'),
+    Header('Access-Control-Allow-Headers', 'Content-Type, Authorization'),
+    Header('Access-Control-Allow-Credentials', 'true'),
+    Header('Access-Control-Max-Age', '86400'),
+    SetMetadata('cors', true)
+  )
+}

+ 0 - 0
src/module/agent-server/dto/index.ts → src/dto/agent-server.ts


+ 20 - 0
src/interface/agent-server.interface.ts

@@ -0,0 +1,20 @@
+import { ServiceResponse } from '../response/response.interface'
+
+export interface IAgentServerService {
+  listStaffs(): Promise<ServiceResponse<StaffsType[]>>
+  getStaffProfile(staff_id: string): Promise<ServiceResponse<StaffProfile>>
+  getUserProfile(user_id: string): Promise<ServiceResponse<UserProfile>>
+  listUsers(
+    user_name: string,
+    user_union_id: string
+  ): Promise<ServiceResponse<UserProfile[]>>
+  getDialogueHistory(
+    staff_id: string,
+    user_id: string,
+    recent_minutes: string
+  ): Promise<ServiceResponse<DialogueHistory[]>>
+  listModels(): Promise<ServiceResponse<Model[]>>
+  listScenes(): Promise<ServiceResponse<any[]>>
+  getBasePrompt(): Promise<ServiceResponse<string>>
+  runPrompt(prompt: any): Promise<ServiceResponse<any>>
+}

+ 45 - 104
src/module/agent-server/agent-server.controller.ts

@@ -1,136 +1,77 @@
-import {
-  Controller,
-  Get,
-  Header,
-  HttpCode,
-  Query,
-  Post,
-  Body
-} from '@nestjs/common'
+import { Controller, Get, Query } from '@nestjs/common'
+import { ApiOperation, ApiTags } from '@nestjs/swagger'
 
-import { AgentServerService } from './agent-server.service'
-import {
-  GetStaffProfileDto,
-  ListUsersDto,
-  GetDialogueHistoryDto,
-  RunPromptDto
-} from './dto'
+import { ListUsersDto, RunPromptDto } from '@/dto/agent-server'
 
-interface ApiResponse<T> {
-  code: number
-  msg: string
-  data: T | null
-}
+import { AgentServerService } from './service/agent-server.service'
 
-@Controller('agentServer')
+@ApiTags('agent-server')
+@Controller('agent-server')
 export class AgentServerController {
   constructor(private readonly agentServerService: AgentServerService) {}
 
-  private handleResponse<T>(response: {
-    data: T
-    code: number
-    msg: string
-  }): ApiResponse<T> {
-    if (response.code === 200) {
-      return {
-        code: 0,
-        msg: '请求成功',
-        data: response.data
-      }
-    }
-    return {
-      code: 1,
-      msg: response.msg,
-      data: null
-    }
-  }
-
-  // 获取所有员工列表
-  @Get('listStaffs')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
+  @Get('staffs')
+  @ApiOperation({ summary: '获取客服列表' })
   async listStaffs() {
-    const response = await this.agentServerService.listStaffs()
-    return this.handleResponse(response)
+    return this.agentServerService.listStaffs()
   }
 
-  // 获取员工详情
-  @Get('getStaffProfile')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
-  async getStaffProfile(@Query() getStaffProfileDto: GetStaffProfileDto) {
-    const response = await this.agentServerService.getStaffProfile(
-      getStaffProfileDto.staff_id
-    )
-    return this.handleResponse(response)
+  @Get('staff/profile')
+  @ApiOperation({ summary: '获取客服信息' })
+  async getStaffProfile(@Query('staff_id') staff_id: string) {
+    return this.agentServerService.getStaffProfile(staff_id)
   }
 
-  // 获取用户详情
-  @Get('getUserProfile')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
-  async getUserProfile(@Query() listUsersDto: ListUsersDto) {
-    const response = await this.agentServerService.getUserProfile(
-      listUsersDto.user_union_id
-    )
-    return this.handleResponse(response)
+  @Get('user/profile')
+  @ApiOperation({ summary: '获取用户信息' })
+  async getUserProfile(@Query('user_id') user_id: string) {
+    return this.agentServerService.getUserProfile(user_id)
   }
 
-  // 获取所有用户列表(根据用户名和用户union_id)
-  @Get('listUsers')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
-  async listUsers(@Query() listUsersDto: ListUsersDto) {
-    const response = await this.agentServerService.listUsers(
-      listUsersDto.user_name,
-      listUsersDto.user_union_id
+  @Get('users')
+  @ApiOperation({ summary: '获取用户列表' })
+  async listUsers(@Query() query: ListUsersDto) {
+    return this.agentServerService.listUsers(
+      query.user_name,
+      query.user_union_id
     )
-    return this.handleResponse(response)
   }
 
-  @Get('getDialogueHistory')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
+  @Get('dialogue/history')
+  @ApiOperation({ summary: '获取对话历史' })
   async getDialogueHistory(
-    @Query() getDialogueHistoryDto: GetDialogueHistoryDto
+    @Query('staff_id') staff_id: string,
+    @Query('user_id') user_id: string,
+    @Query('recent_minutes') recent_minutes: string
   ) {
-    const response = await this.agentServerService.getDialogueHistory(
-      getDialogueHistoryDto.staff_id,
-      getDialogueHistoryDto.user_id,
-      getDialogueHistoryDto.recent_minutes
+    return this.agentServerService.getDialogueHistory(
+      staff_id,
+      user_id,
+      recent_minutes
     )
-    return this.handleResponse(response)
   }
 
-  @Get('listModels')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
+  @Get('models')
+  @ApiOperation({ summary: '获取模型列表' })
   async listModels() {
-    const response = await this.agentServerService.listModels()
-    return this.handleResponse(response)
+    return this.agentServerService.listModels()
   }
 
-  @Get('listScenes')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
+  @Get('scenes')
+  @ApiOperation({ summary: '获取场景列表' })
   async listScenes() {
-    const response = await this.agentServerService.listScenes()
-    return this.handleResponse(response)
+    return this.agentServerService.listScenes()
   }
 
-  @Get('getBasePrompt')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
+  @Get('base-prompt')
+  @ApiOperation({ summary: '获取基础提示词' })
   async getBasePrompt() {
-    const response = await this.agentServerService.getBasePrompt()
-    return this.handleResponse(response)
+    return this.agentServerService.getBasePrompt()
   }
 
-  @Post('runPrompt')
-  @Header('Access-Control-Allow-Origin', '*')
-  @HttpCode(200)
-  async runPrompt(@Body() runPromptDto: RunPromptDto) {
-    const response = await this.agentServerService.runPrompt(runPromptDto)
-    return this.handleResponse(response)
+  @Get('run-prompt')
+  @ApiOperation({ summary: '运行提示词' })
+  async runPrompt(@Query() query: RunPromptDto) {
+    return this.agentServerService.runPrompt(query)
   }
 }

+ 9 - 2
src/module/agent-server/agent-server.module.ts

@@ -2,7 +2,8 @@ import { HttpModule } from '@nestjs/axios'
 import { Module } from '@nestjs/common'
 
 import { AgentServerController } from './agent-server.controller'
-import { AgentServerService } from './agent-server.service'
+import { AgentServerHttpService } from './service/agent-server-http.service'
+import { AgentServerService } from './service/agent-server.service'
 
 @Module({
   imports: [
@@ -12,6 +13,12 @@ import { AgentServerService } from './agent-server.service'
     })
   ],
   controllers: [AgentServerController],
-  providers: [AgentServerService]
+  providers: [
+    {
+      provide: 'IAgentServerService',
+      useClass: AgentServerHttpService
+    },
+    AgentServerService
+  ]
 })
 export class AgentServerModule {}

+ 0 - 71
src/module/agent-server/agent-server.service.ts

@@ -1,71 +0,0 @@
-import { HttpService } from '@nestjs/axios'
-import { Injectable } from '@nestjs/common'
-import { lastValueFrom } from 'rxjs'
-
-import { RunPromptDto } from './dto'
-
-@Injectable()
-export class AgentServerService {
-  private readonly baseUrl = 'http://192.168.206.189:8083/api'
-
-  constructor(private readonly httpService: HttpService) {}
-
-  private async makeRequest<T>(
-    endpoint: string,
-    params?: Record<string, any>
-  ): Promise<AgentServerResponseType<T>> {
-    const url = `${this.baseUrl}/${endpoint}`
-    const responseObservable = await this.httpService.get<
-      AgentServerResponseType<T>
-    >(url, { params })
-    const { data } = await lastValueFrom(responseObservable)
-    return data
-  }
-
-  async listStaffs() {
-    return this.makeRequest<StaffsType>('listStaffs')
-  }
-
-  async getStaffProfile(staff_id: string) {
-    return this.makeRequest<StaffProfile>('getStaffProfile', { staff_id })
-  }
-
-  async getUserProfile(user_id: string) {
-    return this.makeRequest<UserProfile>('getUserProfile', { user_id })
-  }
-
-  async listUsers(user_name: string, user_union_id: string) {
-    return this.makeRequest<UserProfile>('listUsers', {
-      user_name,
-      user_union_id
-    })
-  }
-
-  async getDialogueHistory(
-    staff_id: string,
-    user_id: string,
-    recent_minutes: string
-  ) {
-    return this.makeRequest<DialogueHistory>('getDialogueHistory', {
-      staff_id,
-      user_id,
-      recent_minutes
-    })
-  }
-
-  async listModels() {
-    return this.makeRequest<Model>('listModels')
-  }
-
-  async listScenes() {
-    return this.makeRequest<Scene>('listScenes')
-  }
-
-  async getBasePrompt() {
-    return this.makeRequest<BasePrompt>('getBasePrompt')
-  }
-
-  async runPrompt(runPromptDto: RunPromptDto) {
-    return this.makeRequest<RunPromptDto>('runPrompt', runPromptDto)
-  }
-}

+ 87 - 0
src/module/agent-server/service/agent-server-http.service.ts

@@ -0,0 +1,87 @@
+import { HttpService } from '@nestjs/axios'
+import { Injectable } from '@nestjs/common'
+import { lastValueFrom } from 'rxjs'
+
+import { IAgentServerService } from '@/interface/agent-server.interface'
+import { ServiceResponse } from '@/response/response.interface'
+import { HttpStatusCode } from '@/response/status-code.enum'
+
+@Injectable()
+export class AgentServerHttpService implements IAgentServerService {
+  private readonly baseUrl = 'http://192.168.206.189:8083/api'
+
+  constructor(private readonly httpService: HttpService) {}
+
+  private async makeRequest<T>(
+    endpoint: string,
+    params?: Record<string, any>
+  ): Promise<ServiceResponse<T>> {
+    try {
+      const url = `${this.baseUrl}/${endpoint}`
+      const responseObservable = await this.httpService.get<ServiceResponse<T>>(
+        url,
+        { params }
+      )
+      const { data } = await lastValueFrom(responseObservable)
+      return data
+    } catch (error) {
+      return {
+        code: HttpStatusCode.INTERNAL_SERVER_ERROR,
+        msg: error.message,
+        data: null as T
+      }
+    }
+  }
+
+  async listStaffs(): Promise<ServiceResponse<StaffsType[]>> {
+    return this.makeRequest<StaffsType[]>('listStaffs')
+  }
+
+  async getStaffProfile(
+    staff_id: string
+  ): Promise<ServiceResponse<StaffProfile>> {
+    return this.makeRequest<StaffProfile>('getStaffProfile', { staff_id })
+  }
+
+  async getUserProfile(user_id: string): Promise<ServiceResponse<UserProfile>> {
+    return this.makeRequest<UserProfile>('getUserProfile', { user_id })
+  }
+
+  async listUsers(
+    user_name: string,
+    user_union_id: string
+  ): Promise<ServiceResponse<UserProfile[]>> {
+    return this.makeRequest<UserProfile[]>('listUsers', {
+      user_name,
+      user_union_id
+    })
+  }
+
+  async getDialogueHistory(
+    staff_id: string,
+    user_id: string,
+    recent_minutes: string
+  ): Promise<ServiceResponse<DialogueHistory[]>> {
+    return this.makeRequest<DialogueHistory[]>('getDialogueHistory', {
+      staff_id,
+      user_id,
+      recent_minutes
+    })
+  }
+
+  async listModels(): Promise<ServiceResponse<Model[]>> {
+    return this.makeRequest<Model[]>('listModels')
+  }
+
+  async listScenes(): Promise<ServiceResponse<any[]>> {
+    return this.makeRequest<any[]>('listScenes')
+  }
+
+  async getBasePrompt(): Promise<ServiceResponse<string>> {
+    return this.makeRequest<string>('getBasePrompt')
+  }
+
+  async runPrompt(prompt: any): Promise<ServiceResponse<any>> {
+    return this.makeRequest<any>('runPrompt', prompt)
+  }
+}

+ 97 - 0
src/module/agent-server/service/agent-server.service.ts

@@ -0,0 +1,97 @@
+import { Inject, Injectable } from '@nestjs/common'
+
+import { IAgentServerService } from '@/interface/agent-server.interface'
+import { ServiceResponse } from '@/response/response.interface'
+import { HttpStatusCode } from '@/response/status-code.enum'
+
+@Injectable()
+export class AgentServerService implements IAgentServerService {
+  constructor(
+    @Inject('IAgentServerService')
+    private readonly httpService: IAgentServerService
+  ) {}
+
+  async listStaffs(): Promise<ServiceResponse<StaffsType[]>> {
+    return this.httpService.listStaffs()
+  }
+
+  async getStaffProfile(
+    staff_id: string
+  ): Promise<ServiceResponse<StaffProfile>> {
+    if (!staff_id) {
+      return {
+        code: HttpStatusCode.BAD_REQUEST,
+        msg: 'staff_id不能为空',
+        data: null
+      }
+    }
+    return this.httpService.getStaffProfile(staff_id)
+  }
+
+  async getUserProfile(user_id: string): Promise<ServiceResponse<UserProfile>> {
+    if (!user_id) {
+      return {
+        code: HttpStatusCode.BAD_REQUEST,
+        msg: 'user_id不能为空',
+        data: null
+      }
+    }
+    return this.httpService.getUserProfile(user_id)
+  }
+
+  async listUsers(
+    user_name: string,
+    user_union_id: string
+  ): Promise<ServiceResponse<UserProfile[]>> {
+    if (!user_name && !user_union_id) {
+      return {
+        code: HttpStatusCode.BAD_REQUEST,
+        msg: 'user_name和user_union_id不能同时为空',
+        data: null
+      }
+    }
+    return this.httpService.listUsers(user_name, user_union_id)
+  }
+
+  async getDialogueHistory(
+    staff_id: string,
+    user_id: string,
+    recent_minutes: string
+  ): Promise<ServiceResponse<DialogueHistory[]>> {
+    if (!staff_id || !user_id) {
+      return {
+        code: HttpStatusCode.BAD_REQUEST,
+        msg: 'staff_id和user_id不能为空',
+        data: null
+      }
+    }
+    return this.httpService.getDialogueHistory(
+      staff_id,
+      user_id,
+      recent_minutes
+    )
+  }
+
+  async listModels(): Promise<ServiceResponse<Model[]>> {
+    return this.httpService.listModels()
+  }
+
+  async listScenes(): Promise<ServiceResponse<any[]>> {
+    return this.httpService.listScenes()
+  }
+
+  async getBasePrompt(): Promise<ServiceResponse<string>> {
+    return this.httpService.getBasePrompt()
+  }
+
+  async runPrompt(prompt: any): Promise<ServiceResponse<any>> {
+    if (!prompt) {
+      return {
+        code: HttpStatusCode.BAD_REQUEST,
+        msg: 'prompt不能为空',
+        data: null
+      }
+    }
+    return this.httpService.runPrompt(prompt)
+  }
+}

+ 10 - 0
src/response/message.constant.ts

@@ -0,0 +1,10 @@
+export const ResponseMessage = {
+  SUCCESS: '请求成功',
+  BAD_REQUEST: '请求参数错误',
+  UNAUTHORIZED: '未授权',
+  FORBIDDEN: '禁止访问',
+  NOT_FOUND: '资源不存在',
+  INTERNAL_SERVER_ERROR: '服务器内部错误',
+  TOO_MANY_REQUESTS: '请求过于频繁',
+  UNKNOWN_ERROR: '未知错误'
+}

+ 11 - 0
src/response/response.interface.ts

@@ -0,0 +1,11 @@
+export interface ApiResponse<T> {
+  code: number
+  msg: string
+  data: T | null
+}
+
+export interface ServiceResponse<T> {
+  code: number
+  msg: string
+  data: T
+}

+ 39 - 0
src/response/response.util.ts

@@ -0,0 +1,39 @@
+import { ResponseMessage } from './message.constant'
+import { ApiResponse, ServiceResponse } from './response.interface'
+import { HttpStatusCode, BusinessCode } from './status-code.enum'
+
+export class ResponseUtil {
+  private static readonly statusCodeMap: Record<number, number> = {
+    [HttpStatusCode.OK]: BusinessCode.SUCCESS,
+    [HttpStatusCode.BAD_REQUEST]: BusinessCode.BAD_REQUEST,
+    [HttpStatusCode.UNAUTHORIZED]: BusinessCode.UNAUTHORIZED,
+    [HttpStatusCode.FORBIDDEN]: BusinessCode.FORBIDDEN,
+    [HttpStatusCode.NOT_FOUND]: BusinessCode.NOT_FOUND,
+    [HttpStatusCode.INTERNAL_SERVER_ERROR]: BusinessCode.INTERNAL_SERVER_ERROR,
+    [HttpStatusCode.TOO_MANY_REQUESTS]: BusinessCode.TOO_MANY_REQUESTS
+  }
+
+  private static readonly defaultMessages: Record<number, string> = {
+    [HttpStatusCode.OK]: ResponseMessage.SUCCESS,
+    [HttpStatusCode.BAD_REQUEST]: ResponseMessage.BAD_REQUEST,
+    [HttpStatusCode.UNAUTHORIZED]: ResponseMessage.UNAUTHORIZED,
+    [HttpStatusCode.FORBIDDEN]: ResponseMessage.FORBIDDEN,
+    [HttpStatusCode.NOT_FOUND]: ResponseMessage.NOT_FOUND,
+    [HttpStatusCode.INTERNAL_SERVER_ERROR]:
+      ResponseMessage.INTERNAL_SERVER_ERROR,
+    [HttpStatusCode.TOO_MANY_REQUESTS]: ResponseMessage.TOO_MANY_REQUESTS
+  }
+
+  static handleResponse<T>(response: ServiceResponse<T>): ApiResponse<T> {
+    const { code, msg, data } = response
+    const businessCode = this.statusCodeMap[code] || BusinessCode.UNKNOWN_ERROR
+    const message =
+      msg || this.defaultMessages[code] || ResponseMessage.UNKNOWN_ERROR
+
+    return {
+      code: businessCode,
+      msg: message,
+      data: businessCode === BusinessCode.SUCCESS ? data : null
+    }
+  }
+}

+ 20 - 0
src/response/status-code.enum.ts

@@ -0,0 +1,20 @@
+export enum HttpStatusCode {
+  OK = 200,
+  BAD_REQUEST = 400,
+  UNAUTHORIZED = 401,
+  FORBIDDEN = 403,
+  NOT_FOUND = 404,
+  INTERNAL_SERVER_ERROR = 500,
+  TOO_MANY_REQUESTS = 429
+}
+
+export enum BusinessCode {
+  SUCCESS = 0,
+  BAD_REQUEST = 1,
+  UNAUTHORIZED = 2,
+  FORBIDDEN = 3,
+  NOT_FOUND = 4,
+  INTERNAL_SERVER_ERROR = 5,
+  TOO_MANY_REQUESTS = 6,
+  UNKNOWN_ERROR = 99
+}