238 lines
5.7 KiB
Go
238 lines
5.7 KiB
Go
package adapters
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"go.uber.org/zap"
|
|
"google.golang.org/protobuf/types/known/structpb"
|
|
|
|
"iop/apps/node/internal/adapters/cli"
|
|
"iop/apps/node/internal/adapters/mock"
|
|
"iop/apps/node/internal/adapters/ollama"
|
|
"iop/apps/node/internal/adapters/vllm"
|
|
"iop/packages/go/config"
|
|
iop "iop/proto/gen/iop"
|
|
)
|
|
|
|
// BuildFromPayload creates a Registry from a NodeConfigPayload received from edge.
|
|
func BuildFromPayload(payload *iop.NodeConfigPayload, logger *zap.Logger) (*Registry, error) {
|
|
reg := NewRegistry()
|
|
reg.Register(mock.New(logger))
|
|
|
|
for _, ac := range payload.GetAdapters() {
|
|
if !ac.GetEnabled() {
|
|
continue
|
|
}
|
|
switch ac.GetType() {
|
|
case "mock":
|
|
// mock is always registered above.
|
|
case "ollama":
|
|
var cfg config.OllamaConf
|
|
if m := ac.GetOllama(); m != nil {
|
|
cfg = ollamaConfFromProto(m)
|
|
} else {
|
|
cfg = ollamaConfFromStruct(ac.GetSettings())
|
|
}
|
|
reg.Register(ollama.New(cfg, logger))
|
|
case "vllm":
|
|
var cfg config.VllmConf
|
|
if m := ac.GetVllm(); m != nil {
|
|
cfg = vllmConfFromProto(m)
|
|
} else {
|
|
cfg = vllmConfFromStruct(ac.GetSettings())
|
|
}
|
|
reg.Register(vllm.New(cfg, logger))
|
|
case "cli":
|
|
var cfg config.CLIConf
|
|
if m := ac.GetCli(); m != nil {
|
|
cfg = cliConfFromProto(m)
|
|
} else {
|
|
cfg = cliConfFromStruct(ac.GetSettings())
|
|
}
|
|
reg.Register(cli.New(cfg, logger))
|
|
default:
|
|
return nil, fmt.Errorf("adapters: unknown adapter type %q", ac.GetType())
|
|
}
|
|
}
|
|
return reg, nil
|
|
}
|
|
|
|
func ollamaConfFromProto(m *iop.OllamaAdapterConfig) config.OllamaConf {
|
|
return config.OllamaConf{
|
|
Enabled: true,
|
|
BaseURL: m.GetBaseUrl(),
|
|
ContextSize: int(m.GetContextSize()),
|
|
}
|
|
}
|
|
|
|
func vllmConfFromProto(m *iop.VllmAdapterConfig) config.VllmConf {
|
|
return config.VllmConf{Enabled: true, Endpoint: m.GetEndpoint()}
|
|
}
|
|
|
|
func cliConfFromProto(m *iop.CLIAdapterConfig) config.CLIConf {
|
|
cfg := config.CLIConf{Enabled: true, Profiles: make(map[string]config.CLIProfileConf)}
|
|
for name, p := range m.GetProfiles() {
|
|
cfg.Profiles[name] = cliProfileFromProto(p)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func cliProfileFromProto(p *iop.CLIProfileConfig) config.CLIProfileConf {
|
|
if p == nil {
|
|
return config.CLIProfileConf{}
|
|
}
|
|
prof := config.CLIProfileConf{
|
|
Command: p.GetCommand(),
|
|
Args: append([]string(nil), p.GetArgs()...),
|
|
Env: append([]string(nil), p.GetEnv()...),
|
|
Persistent: p.GetPersistent(),
|
|
Terminal: p.GetTerminal(),
|
|
ResponseIdleTimeoutMS: int(p.GetResponseIdleTimeoutMs()),
|
|
StartupIdleTimeoutMS: int(p.GetStartupIdleTimeoutMs()),
|
|
OutputFormat: p.GetOutputFormat(),
|
|
Mode: p.GetMode(),
|
|
ResumeArgs: append([]string(nil), p.GetResumeArgs()...),
|
|
}
|
|
if marker := p.GetCompletionMarker(); marker != nil {
|
|
prof.CompletionMarker = config.CompletionMarkerConf{
|
|
Line: marker.GetLine(),
|
|
Regex: marker.GetRegex(),
|
|
}
|
|
}
|
|
return prof
|
|
}
|
|
|
|
// Legacy structpb fallback paths for payloads from older edge versions
|
|
// that populate AdapterConfig.settings instead of the typed oneof.
|
|
|
|
func ollamaConfFromStruct(s *structpb.Struct) config.OllamaConf {
|
|
cfg := config.OllamaConf{Enabled: true}
|
|
if s == nil {
|
|
return cfg
|
|
}
|
|
m := s.AsMap()
|
|
if v, ok := m["base_url"].(string); ok {
|
|
cfg.BaseURL = v
|
|
}
|
|
if v, ok := intSetting(m, "context_size"); ok {
|
|
cfg.ContextSize = v
|
|
} else if v, ok := intSetting(m, "num_ctx"); ok {
|
|
cfg.ContextSize = v
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func intSetting(m map[string]any, key string) (int, bool) {
|
|
v, ok := m[key]
|
|
if !ok {
|
|
return 0, false
|
|
}
|
|
switch n := v.(type) {
|
|
case int:
|
|
return n, true
|
|
case int32:
|
|
return int(n), true
|
|
case int64:
|
|
return int(n), true
|
|
case float64:
|
|
return int(n), true
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
func vllmConfFromStruct(s *structpb.Struct) config.VllmConf {
|
|
cfg := config.VllmConf{Enabled: true}
|
|
if s == nil {
|
|
return cfg
|
|
}
|
|
m := s.AsMap()
|
|
if v, ok := m["endpoint"].(string); ok {
|
|
cfg.Endpoint = v
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func cliConfFromStruct(s *structpb.Struct) config.CLIConf {
|
|
cfg := config.CLIConf{Enabled: true, Profiles: make(map[string]config.CLIProfileConf)}
|
|
if s == nil {
|
|
return cfg
|
|
}
|
|
m := s.AsMap()
|
|
profiles, ok := m["profiles"].(map[string]any)
|
|
if !ok {
|
|
return cfg
|
|
}
|
|
for name, pAny := range profiles {
|
|
p, ok := pAny.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
prof := config.CLIProfileConf{}
|
|
if v, ok := p["command"].(string); ok {
|
|
prof.Command = v
|
|
}
|
|
prof.Args = stringsFromAny(p["args"])
|
|
prof.Env = stringsFromAny(p["env"])
|
|
if v, ok := boolFromAny(p["persistent"]); ok {
|
|
prof.Persistent = v
|
|
}
|
|
if v, ok := boolFromAny(p["terminal"]); ok {
|
|
prof.Terminal = v
|
|
}
|
|
if v, ok := intFromAny(p["response_idle_timeout_ms"]); ok {
|
|
prof.ResponseIdleTimeoutMS = v
|
|
}
|
|
if v, ok := intFromAny(p["startup_idle_timeout_ms"]); ok {
|
|
prof.StartupIdleTimeoutMS = v
|
|
}
|
|
if v, ok := p["output_format"].(string); ok {
|
|
prof.OutputFormat = v
|
|
}
|
|
if v, ok := p["mode"].(string); ok {
|
|
prof.Mode = v
|
|
}
|
|
prof.ResumeArgs = stringsFromAny(p["resume_args"])
|
|
if marker, ok := p["completion_marker"].(map[string]any); ok {
|
|
if v, ok := marker["line"].(string); ok {
|
|
prof.CompletionMarker.Line = v
|
|
}
|
|
if v, ok := marker["regex"].(string); ok {
|
|
prof.CompletionMarker.Regex = v
|
|
}
|
|
}
|
|
cfg.Profiles[name] = prof
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func stringsFromAny(v any) []string {
|
|
arr, ok := v.([]any)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
out := make([]string, 0, len(arr))
|
|
for _, a := range arr {
|
|
if s, ok := a.(string); ok {
|
|
out = append(out, s)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func boolFromAny(v any) (bool, bool) {
|
|
if b, ok := v.(bool); ok {
|
|
return b, true
|
|
}
|
|
return false, false
|
|
}
|
|
|
|
func intFromAny(v any) (int, bool) {
|
|
if f, ok := v.(float64); ok {
|
|
return int(f), true
|
|
}
|
|
if i, ok := v.(int); ok {
|
|
return i, true
|
|
}
|
|
return 0, false
|
|
}
|