feat: RoutingWorkflow + LLM Router + Memory Activity
ci / test (push) Successful in 2m12s

- Add RoutingWorkflow: generic state machine executor for WorkflowSpec
- Add LLM Router: natural language → WorkflowSpec generation
- Add RetrieveMemoryActivity: query poimen-memory for context
- Add activities: AnalyzeCode, SecurityScan, GenerateReport, Notify, etc.
- Add agent-prompts/router: LLM prompt documentation
- Extend starter with --route flag for routing workflows
- Remove orchestrator job (trigger via API/message instead)
- Clean up: move docs to Desktop, add .gitignore for *.md
This commit is contained in:
Test
2026-09-02 19:21:53 -07:00
parent 5a465b145c
commit a0e64224a7
74 changed files with 3950 additions and 12421 deletions
+110
View File
@@ -0,0 +1,110 @@
package routing
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
var (
// llmBaseURL is the base URL for the LLM API
llmBaseURL string
)
func init() {
llmBaseURL = os.Getenv("LOCAL_LLM_BASE_URL")
if llmBaseURL == "" {
llmBaseURL = "https://api.riotpiao.com"
}
}
// LLMClient is a simple LLM client for routing
type LLMClient struct {
baseURL string
httpClient *http.Client
}
// NewLLMClient creates a new LLM client
func NewLLMClient() *LLMClient {
return &LLMClient{
baseURL: llmBaseURL,
httpClient: &http.Client{},
}
}
// llmRequest is the request body for the OpenAI-compatible API
type llmRequest struct {
Model string `json:"model"`
Messages []llmMessage `json:"messages"`
Stream bool `json:"stream"`
}
type llmMessage struct {
Role string `json:"role"`
Content string `json:"content"`
}
// llmResponse is the response from the OpenAI-compatible API
type llmResponse struct {
Choices []struct {
Message struct {
Content string `json:"content"`
} `json:"message"`
} `json:"choices"`
}
// Chat sends a chat completion request
func (c *LLMClient) Chat(ctx context.Context, systemPrompt, userMessage string) (string, error) {
req := llmRequest{
Model: "reasoning",
Messages: []llmMessage{
{Role: "system", Content: systemPrompt},
{Role: "user", Content: userMessage},
},
Stream: false,
}
reqBody, err := json.Marshal(req)
if err != nil {
return "", fmt.Errorf("failed to marshal request: %w", err)
}
httpReq, err := http.NewRequestWithContext(ctx, "POST",
fmt.Sprintf("%s/v1/chat/completions", c.baseURL),
bytes.NewReader(reqBody))
if err != nil {
return "", fmt.Errorf("failed to create HTTP request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
resp, err := c.httpClient.Do(httpReq)
if err != nil {
return "", fmt.Errorf("failed to connect to LLM API at %s: %w", c.baseURL, err)
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %w", err)
}
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("LLM API returned status %d: %s", resp.StatusCode, string(respBody))
}
var respObj llmResponse
if err := json.Unmarshal(respBody, &respObj); err != nil {
return "", fmt.Errorf("failed to unmarshal response: %w", err)
}
if len(respObj.Choices) == 0 {
return "", fmt.Errorf("no choices in response from LLM API")
}
return respObj.Choices[0].Message.Content, nil
}