api.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { consumeSse } from '/@/views/ventAI/manageAssistent/api/sse';
  2. import type { SSERawEvent } from './types';
  3. // [审计-第四轮 M1] 重放自我方 fix/base-agent-token(M1/M2/M3):取基座登录态的令牌(与对话链路 manageAssistent/api/client.ts 同源)
  4. import { getToken } from '/@/utils/auth';
  5. enum Api {
  6. clickTun = '/ventAI/api/interpret/click/tun',
  7. clickDevice = '/ventAI/api/interpret/click/device',
  8. }
  9. /**
  10. * 巷道数据解读(SSE 流式)
  11. * @param params - { tun_id, tun_name }
  12. * @param onEvent - 每个 SSE 事件的回调
  13. * @returns 流完成后的 thread_id、session_id
  14. */
  15. export async function fetchTunnelInterpretation(
  16. params: { tun_id: string; tun_name: string; mode?: string },
  17. onEvent: (event: SSERawEvent) => void
  18. ): Promise<{ thread_id: string; session_id: string }> {
  19. return ssePost(Api.clickTun, params, onEvent);
  20. }
  21. /**
  22. * 设备数据解读(SSE 流式)
  23. * @param params - { device_id, device_name, device_type }
  24. * @param onEvent - 每个 SSE 事件的回调
  25. * @returns 流完成后的 thread_id、session_id
  26. */
  27. export async function fetchDeviceInterpretation(
  28. params: { device_id: string; device_name: string; device_type: string; mode?: string },
  29. onEvent: (event: SSERawEvent) => void
  30. ): Promise<{ thread_id: string; session_id: string }> {
  31. return ssePost(Api.clickDevice, params, onEvent);
  32. }
  33. /** SSE 流式 POST 请求的通用实现 */
  34. async function ssePost(
  35. url: string,
  36. body: Record<string, string>,
  37. onEvent: (event: SSERawEvent) => void
  38. ): Promise<{ thread_id: string; session_id: string }> {
  39. const response = await fetch(url, {
  40. method: 'POST',
  41. headers: {
  42. 'Content-Type': 'application/json',
  43. // [审计-第四轮 M1] 重放自我方 fix/base-agent-token(M1/M2/M3)
  44. // 原行为:点选解读不带令牌,是基座里唯一一条「匿名」调 TfAgents 的路径,
  45. // 消耗只能记到兜底账号 click-anonymous,无法按登录人记账。
  46. // 现行为:补上与对话链路同名的请求头(TfAgents 侧读小写 x-access-token,HTTP 头不区分大小写)。
  47. // 为什么:恢复按登录人记账归因。
  48. // ⚠️ 令牌是「可选」语义:getToken() 为空时仍照常发请求(TfAgents 侧有 click-anonymous 兜底),
  49. // 禁止加「未登录就拦截/跳登录」的判断(我方 D5 决策)——那会把未登录场景直接变成不可用。
  50. 'X-Access-Token': getToken(),
  51. },
  52. body: JSON.stringify(body),
  53. });
  54. if (!response.ok) {
  55. throw new Error(`HTTP错误: ${response.status}`);
  56. }
  57. // 该接口只把 done / error 当终止事件(与统一对话不同,不含 interrupt)
  58. const { sessionId, threadId } = await consumeSse<SSERawEvent>(response, onEvent, { terminateOn: ['done', 'error'] });
  59. return { thread_id: threadId, session_id: sessionId };
  60. }