135 lines
3.9 KiB
Go
135 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/matst80/go-openapi-compat/pkg/openapi"
|
|
)
|
|
|
|
func main() {
|
|
baseURL := os.Getenv("OPENAI_BASE_URL")
|
|
if baseURL == "" {
|
|
baseURL = "http://10.10.11.33:8082/v1/"
|
|
}
|
|
apiKey := os.Getenv("OPENAI_API_KEY")
|
|
|
|
client := openapi.NewClient(baseURL, apiKey)
|
|
model := "Jackrong/Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF"
|
|
|
|
session := openapi.NewSession(client, model)
|
|
session.DefaultRequestOptions.Seed = 42
|
|
session.SetSystemPrompt("You are an expert software architect. You have access to shell and file tools to explore, analyze, and modify the codebase. Use them to provide deep insights and implement changes. blocks with git diffs will be applied")
|
|
|
|
// Setup composite registry with standard tools
|
|
composite := &openapi.CompositeRegistry{}
|
|
|
|
// Base registry for custom tools
|
|
baseRegistry := openapi.NewMapRegistry()
|
|
composite.Add(baseRegistry)
|
|
|
|
// Add standard shell and file tools
|
|
composite.Add(openapi.NewShellRegistry())
|
|
composite.Add(openapi.NewFileRegistry(".")) // Use current directory as base
|
|
|
|
session.SetRegistry(composite)
|
|
|
|
// Tools for reasoning about abstractions
|
|
baseRegistry.Register("analyze_abstraction", "Analyze a specific code abstraction",
|
|
map[string]any{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"name": map[string]any{"type": "string"},
|
|
"description": map[string]any{"type": "string"},
|
|
},
|
|
},
|
|
func(ctx context.Context, s *openapi.Session, args json.RawMessage) (any, error) {
|
|
var params struct{ Name, Description string }
|
|
json.Unmarshal(args, ¶ms)
|
|
return map[string]string{
|
|
"analysis": fmt.Sprintf("The abstraction '%s' (%s) follows the 'Decorator' and 'Strategy' patterns by using hooks for extensibility.", params.Name, params.Description),
|
|
"score": "9/10",
|
|
}, nil
|
|
})
|
|
|
|
baseRegistry.Register("update_instructions", "Update the architect's system instructions",
|
|
map[string]any{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"new_instructions": map[string]any{"type": "string"},
|
|
},
|
|
},
|
|
func(ctx context.Context, s *openapi.Session, args json.RawMessage) (any, error) {
|
|
var params struct{ NewInstructions string }
|
|
json.Unmarshal(args, ¶ms)
|
|
s.SetSystemPrompt(params.NewInstructions)
|
|
return "Instructions updated successfully.", nil
|
|
})
|
|
|
|
// Setup hooks for UI updates
|
|
session.SetHooks(openapi.SessionHooks{
|
|
BeforeToolCall: func(ctx context.Context, s *openapi.Session, tc *openapi.ToolCall) error {
|
|
fmt.Printf("\n[Tool] Executing: %s(%s)...\n", tc.Function.Name, tc.Function.Arguments)
|
|
return nil
|
|
},
|
|
OnReasoning: func(ctx context.Context, s *openapi.Session, reasoning string) error {
|
|
fmt.Printf("\n[Thinking] %s", reasoning)
|
|
return nil
|
|
},
|
|
OnDone: func(ctx context.Context, s *openapi.Session) error {
|
|
fmt.Printf("\nDone.\n")
|
|
return nil
|
|
},
|
|
OnError: func(ctx context.Context, s *openapi.Session, err error) {
|
|
fmt.Printf("\n[Error] %v\n", err)
|
|
},
|
|
})
|
|
|
|
fmt.Printf("Interactive Architect Session (BaseURL: %s)\n", baseURL)
|
|
fmt.Println("Type your message and press Enter. Type 'exit' to quit.")
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for {
|
|
fmt.Print("\nUser > ")
|
|
if !scanner.Scan() {
|
|
break
|
|
}
|
|
input := scanner.Text()
|
|
if input == "exit" || input == "quit" {
|
|
break
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
|
|
chunks, errs := session.Chat(ctx, input)
|
|
|
|
fmt.Print("Assistant > ")
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
for chunk := range chunks {
|
|
if len(chunk.Choices) > 0 {
|
|
fmt.Print(chunk.Choices[0].Delta.Content)
|
|
}
|
|
}
|
|
}()
|
|
|
|
select {
|
|
case <-done:
|
|
fmt.Print("\nDone.\n")
|
|
// Stream completed
|
|
case err := <-errs:
|
|
if err != nil {
|
|
fmt.Printf("\nError: %v\n", err)
|
|
}
|
|
case <-ctx.Done():
|
|
fmt.Println("\nTimeout reached.")
|
|
}
|
|
cancel()
|
|
fmt.Println()
|
|
}
|
|
}
|