ChatStreamHandler 提供基于 Server-Sent Events (SSE) 的流式 Chat 接口。 路径示例: POST /v1/agents/chat/stream 请求体与 ChatHandler 相同,但响应为 text/event-stream。 每个事件均为一行 JSON: data: {"cursor":1,"bookmark":{...},"event":{...}}\n\n 前端可以根据 event 字段中的具体类型(decoding types.*Event)来渲染流式思考/文本/工具调用等。
()
| 478 | // |
| 479 | // 前端可以根据 event 字段中的具体类型(decoding types.*Event)来渲染流式思考/文本/工具调用等。 |
| 480 | func (s *Server) ChatStreamHandler() http.Handler { |
| 481 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 482 | start := time.Now() |
| 483 | |
| 484 | if r.Method != http.MethodPost { |
| 485 | http.Error(w, "method not allowed", http.StatusMethodNotAllowed) |
| 486 | return |
| 487 | } |
| 488 | |
| 489 | flusher, ok := w.(http.Flusher) |
| 490 | if !ok { |
| 491 | http.Error(w, "streaming unsupported", http.StatusInternalServerError) |
| 492 | return |
| 493 | } |
| 494 | |
| 495 | var req ChatRequest |
| 496 | if err := json.NewDecoder(r.Body).Decode(&req); err != nil { |
| 497 | http.Error(w, "invalid JSON body", http.StatusBadRequest) |
| 498 | return |
| 499 | } |
| 500 | if req.TemplateID == "" || req.Input == "" { |
| 501 | http.Error(w, "template_id and input are required", http.StatusBadRequest) |
| 502 | return |
| 503 | } |
| 504 | |
| 505 | ctx := r.Context() |
| 506 | ctx, cancel := context.WithTimeout(ctx, 5*time.Minute) |
| 507 | defer cancel() |
| 508 | |
| 509 | agentConfig := &types.AgentConfig{ |
| 510 | TemplateID: req.TemplateID, |
| 511 | ModelConfig: req.ModelConfig, |
| 512 | Sandbox: req.Sandbox, |
| 513 | Middlewares: req.Middlewares, |
| 514 | Metadata: req.Metadata, |
| 515 | RoutingProfile: req.RoutingProfile, |
| 516 | } |
| 517 | |
| 518 | if req.SkillsPackage != nil { |
| 519 | agentConfig.SkillsPackage = req.SkillsPackage |
| 520 | } else if len(req.Skills) > 0 { |
| 521 | agentConfig.SkillsPackage = &types.SkillsPackageConfig{ |
| 522 | Source: "local", |
| 523 | Path: ".", |
| 524 | SkillsDir: "skills", |
| 525 | EnabledSkills: req.Skills, |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | ag, err := agent.Create(ctx, agentConfig, s.deps) |
| 530 | if err != nil { |
| 531 | logging.Error(ctx, "http.chat_stream.error", map[string]any{ |
| 532 | "template_id": req.TemplateID, |
| 533 | "routing_profile": req.RoutingProfile, |
| 534 | "stage": "create_agent", |
| 535 | "error": err.Error(), |
| 536 | "latency_ms": time.Since(start).Milliseconds(), |
| 537 | }) |
no test coverage detected