refactor: abstract chat message structs and migrate to official openai-go SDK

### CHANGES

- Introduce local `chat` package for message abstraction
- Replace sashabaranov/go-openai with official openai-go SDK
- Update OpenAI, Azure, and Exolab plugins for new client
- Refactor all AI providers to use internal chat types
- Decouple codebase from third-party AI provider structs
- Replace deprecated `ioutil` functions with `os` equivalents
This commit is contained in:
Kayvan Sylvan
2025-06-28 07:28:49 -07:00
parent aa028a4a57
commit 09e01eddf4
27 changed files with 346 additions and 271 deletions

View File

@@ -3,14 +3,13 @@ package restapi
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"strings"
goopenai "github.com/sashabaranov/go-openai"
"github.com/danielmiessler/fabric/chat"
"github.com/danielmiessler/fabric/common"
"github.com/danielmiessler/fabric/core"
@@ -95,7 +94,7 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
// Load and prepend strategy prompt if strategyName is set
if p.StrategyName != "" {
strategyFile := filepath.Join(os.Getenv("HOME"), ".config", "fabric", "strategies", p.StrategyName+".json")
data, err := ioutil.ReadFile(strategyFile)
data, err := os.ReadFile(strategyFile)
if err == nil {
var s struct {
Prompt string `json:"prompt"`
@@ -115,7 +114,7 @@ func (h *ChatHandler) HandleChat(c *gin.Context) {
// Pass the language received in the initial request to the common.ChatRequest
chatReq := &common.ChatRequest{
Message: &goopenai.ChatCompletionMessage{
Message: &chat.ChatCompletionMessage{
Role: "user",
Content: p.UserInput,
},

View File

@@ -103,7 +103,6 @@ func ServeOllama(registry *core.PluginRegistry, address string, version string)
r.GET("/api/tags", typeConversion.ollamaTags)
r.GET("/api/version", func(c *gin.Context) {
c.Data(200, "application/json", []byte(fmt.Sprintf("{\"%s\"}", version)))
return
})
r.POST("/api/chat", typeConversion.ollamaChat)
@@ -262,15 +261,10 @@ func (f APIConvert) ollamaChat(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": err})
return
}
for _, bytein := range marshalled {
res = append(res, bytein)
}
for _, bytebreak := range []byte("\n") {
res = append(res, bytebreak)
}
res = append(res, marshalled...)
res = append(res, '\n')
}
c.Data(200, "application/json", res)
//c.JSON(200, forwardedResponse)
return
}

View File

@@ -2,7 +2,6 @@ package restapi
import (
"encoding/json"
"io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -23,7 +22,7 @@ func NewStrategiesHandler(r *gin.Engine) {
r.GET("/strategies", func(c *gin.Context) {
strategiesDir := filepath.Join(os.Getenv("HOME"), ".config", "fabric", "strategies")
files, err := ioutil.ReadDir(strategiesDir)
files, err := os.ReadDir(strategiesDir)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read strategies directory"})
return
@@ -37,7 +36,7 @@ func NewStrategiesHandler(r *gin.Engine) {
}
fullPath := filepath.Join(strategiesDir, file.Name())
data, err := ioutil.ReadFile(fullPath)
data, err := os.ReadFile(fullPath)
if err != nil {
continue
}