feat: implement streaming chat, skill routing, and SAFe PI planning tools

- Add /api/chat/stream endpoint with Server-Sent Events (SSE) for real-time message streaming
  * Implement StreamEvent types (thought, tool_call, tool_result, final, error)
  * Add StreamEventCallback mechanism for event propagation
  * Create StreamChatHandler in webui/bot with proper HTTP headers and flushing

- Implement LLM-based skill router for intelligent capability selection
  * Add optional routerLLM client for semantic routing
  * Implement routeSkillsWithLLM() to match user intent to available skills
  * Add matchSkillsByName() for fuzzy skill matching
  * Update buildUnifiedSystemPrompt() to use routed skills

- Add streaming support to ReAct pipeline
  * Implement runUnifiedReActStream() for streaming thought/action/observation
  * Emit StreamEvent at each ReAct step
  * Support callback error handling in streaming mode

- Integrate three new DevOps tools
  * tools/filedoc: Extract document content from file_id via OpenAI
  * tools/giteaticket: Create Gitea issues from PI plan items with SAFe metadata
  * tools/piplan: Publish PI planning blueprints with dependency tracking

- Add SAFe PI Planning skill
  * Implement PM/SA/RTE (iron triangle) workflow
  * Support for Feature, Enabler, and Dependency definition
  * Automatic task decomposition and Gitea integration

- Create frontend integration documentation
  * Complete SSE protocol specification
  * TypeScript fetch + ReadableStream example
  * LLM-ready refactoring template for other projects

- Simplify file handling
  * Remove legacy file context structures and dual-mode processing
  * Consolidate file operations into UploadAndCacheFiles()
  * Remove FilePromptMode configuration and related complexity

- Update configuration
  * Add Router model support (LLM_ROUTER_MODEL)
  * Add Gitea configuration (BaseURL, Token, Owner, Repo)
  * WebSearch and additional tool infrastructure

Tests: All 22 test packages passing, 8/8 webui tests including 3 new stream tests
This commit is contained in:
2026-03-11 17:58:19 +08:00
parent 0e1a800646
commit 8dc5354fa4
17 changed files with 3086 additions and 565 deletions

View File

@@ -126,9 +126,19 @@ func main() {
// 实例化 LLM 客户端
llmClient := llm.NewOpenAICompatibleClient(cfg.LLM, appLogger.WithComponent("llm"))
// 实例化路由 LLM 客户端(如果配置了独立的路由模型)
var routerLLMClient llm.Client
if cfg.LLM.RouterModel != "" {
routerCfg := cfg.LLM
routerCfg.Model = cfg.LLM.RouterModel
routerLLMClient = llm.NewOpenAICompatibleClient(routerCfg, appLogger.WithComponent("llm.router"))
appLogger.Infof("skill router enabled, model=%s", cfg.LLM.RouterModel)
}
// 创建编排器,整合 LLM、记忆系统、知识技能库与各种工具
engine := agent.NewOrchestrator(
llmClient,
routerLLMClient,
store,
toolRegistry,
soul,
@@ -207,11 +217,18 @@ func runMessageChannel(ctx context.Context, cfg config.Config, engine *agent.Orc
return wb.Run(
ctx,
func(ctx context.Context, msg webui.IncomingMessage) (string, error) {
if len(msg.FileIDs) > 0 {
return engine.HandleMessageWithFileIDs(ctx, msg.ChatID, msg.UserID, msg.Text, msg.FileIDs)
}
return engine.HandleMessage(ctx, msg.ChatID, msg.UserID, msg.Text)
},
func(ctx context.Context, msg webui.IncomingMessage, callback webui.StreamEventCallback) (string, error) {
return engine.HandleMessageStream(ctx, msg.ChatID, msg.UserID, msg.Text, func(event agent.StreamEvent) error {
return callback(webui.StreamEvent{
Type: webui.StreamEventType(event.Type),
Content: event.Content,
Step: event.Step,
ToolName: event.ToolName,
})
})
},
func(ctx context.Context, chatID, userID string, files []llm.InputFile) ([]string, error) {
return engine.UploadAndCacheFiles(ctx, chatID, userID, files)
},