runWebUI 启动一个带简单前端的 HTTP 服务。 默认访问地址: http://localhost:8080
(_ context.Context, deps *agent.Dependencies, templateID, providerName, modelName, apiKey, addr string)
| 204 | // runWebUI 启动一个带简单前端的 HTTP 服务。 |
| 205 | // 默认访问地址: http://localhost:8080 |
| 206 | func runWebUI(_ context.Context, deps *agent.Dependencies, templateID, providerName, modelName, apiKey, addr string) error { |
| 207 | mux := http.NewServeMux() |
| 208 | |
| 209 | // 静态前端资源 |
| 210 | fs := http.FileServer(http.Dir("examples/plan-explore-ui/static")) |
| 211 | mux.Handle("/", fs) |
| 212 | |
| 213 | // SSE 接口: /api/chat/stream |
| 214 | mux.HandleFunc("/api/chat/stream", func(w http.ResponseWriter, r *http.Request) { |
| 215 | if r.Method != http.MethodPost { |
| 216 | http.Error(w, "method not allowed", http.StatusMethodNotAllowed) |
| 217 | return |
| 218 | } |
| 219 | |
| 220 | _, ok := w.(http.Flusher) |
| 221 | if !ok { |
| 222 | http.Error(w, "streaming unsupported", http.StatusInternalServerError) |
| 223 | return |
| 224 | } |
| 225 | |
| 226 | var req struct { |
| 227 | Input string `json:"input"` |
| 228 | } |
| 229 | if err := json.NewDecoder(r.Body).Decode(&req); err != nil { |
| 230 | http.Error(w, "invalid JSON body", http.StatusBadRequest) |
| 231 | return |
| 232 | } |
| 233 | |
| 234 | input := req.Input |
| 235 | if input == "" { |
| 236 | input = defaultPrompt() |
| 237 | } |
| 238 | |
| 239 | reqCtx := r.Context() |
| 240 | reqCtx, cancel := context.WithTimeout(reqCtx, 5*time.Minute) |
| 241 | defer cancel() |
| 242 | |
| 243 | ag, err := agent.Create(reqCtx, &types.AgentConfig{ |
| 244 | TemplateID: templateID, |
| 245 | ModelConfig: &types.ModelConfig{ |
| 246 | Provider: providerName, |
| 247 | Model: modelName, |
| 248 | APIKey: apiKey, |
| 249 | }, |
| 250 | Sandbox: &types.SandboxConfig{ |
| 251 | Kind: types.SandboxKindLocal, |
| 252 | WorkDir: ".", |
| 253 | }, |
| 254 | Middlewares: []string{"filesystem", "todolist"}, |
| 255 | }, deps) |
| 256 | if err != nil { |
| 257 | http.Error(w, "create agent failed: "+err.Error(), http.StatusInternalServerError) |
| 258 | return |
| 259 | } |
| 260 | defer func() { _ = ag.Close() }() |
| 261 | |
| 262 | eventCh := ag.Subscribe([]types.AgentChannel{ |
| 263 | types.ChannelProgress, |
no test coverage detected