iop/apps/edge/internal/node/mapper.go
toki 3624ff0f01 feat: node multi-target serving foundation
- Add inference provider extension phase and milestones for node multi-target serving
- Update edge cmd config and node mapper for multi-target support
- Add Ollama adapter updates and transport client changes
- Update config package and edge.yaml for new settings
- Extend runtime proto with multi-target serving fields
- Add agent task archives and plans for adapter registry, route catalog,
  engine profiles, edge options, commands/caps, runtime concurrency,
  and field smoke tests
2026-06-11 04:09:48 +09:00

109 lines
3.1 KiB
Go

package node
import (
"fmt"
"iop/packages/go/config"
iop "iop/proto/gen/iop"
)
// BuildConfigPayload converts a NodeRecord's adapter config to the proto payload
// sent to node during registration.
//
// After config normalisation, OllamaInstances and VllmInstances already contain
// the promoted legacy single-instance entries, so only the slice fields are
// iterated here. Duplicate instance names produce an error.
func BuildConfigPayload(rec *NodeRecord) (*iop.NodeConfigPayload, error) {
payload := &iop.NodeConfigPayload{
Runtime: &iop.NodeRuntimeConfig{
Concurrency: int32(rec.Runtime.Concurrency),
WorkspaceRoot: rec.Runtime.WorkspaceRoot,
},
}
payload.Adapters = append(payload.Adapters, &iop.AdapterConfig{
Type: "mock",
Enabled: true,
Config: &iop.AdapterConfig_Mock{Mock: &iop.MockAdapterConfig{}},
})
seen := make(map[string]struct{})
for _, inst := range rec.Adapters.OllamaInstances {
if !inst.Enabled {
continue
}
key := "ollama:" + inst.Name
if _, dup := seen[key]; dup {
return nil, fmt.Errorf("duplicate ollama instance name %q", inst.Name)
}
seen[key] = struct{}{}
payload.Adapters = append(payload.Adapters, &iop.AdapterConfig{
Type: "ollama",
Enabled: true,
Name: inst.Name,
Config: &iop.AdapterConfig_Ollama{
Ollama: &iop.OllamaAdapterConfig{
BaseUrl: inst.BaseURL,
ContextSize: int32(inst.ContextSize),
},
},
})
}
for _, inst := range rec.Adapters.VllmInstances {
if !inst.Enabled {
continue
}
key := "vllm:" + inst.Name
if _, dup := seen[key]; dup {
return nil, fmt.Errorf("duplicate vllm instance name %q", inst.Name)
}
seen[key] = struct{}{}
payload.Adapters = append(payload.Adapters, &iop.AdapterConfig{
Type: "vllm",
Enabled: true,
Name: inst.Name,
Config: &iop.AdapterConfig_Vllm{
Vllm: &iop.VllmAdapterConfig{Endpoint: inst.Endpoint},
},
})
}
if rec.Adapters.CLI.Enabled {
profiles := make(map[string]*iop.CLIProfileConfig, len(rec.Adapters.CLI.Profiles))
for name, p := range rec.Adapters.CLI.Profiles {
profiles[name] = cliProfileToProto(p)
}
payload.Adapters = append(payload.Adapters, &iop.AdapterConfig{
Type: "cli",
Enabled: true,
Config: &iop.AdapterConfig_Cli{
Cli: &iop.CLIAdapterConfig{Profiles: profiles},
},
})
}
return payload, nil
}
func cliProfileToProto(p config.CLIProfileConf) *iop.CLIProfileConfig {
out := &iop.CLIProfileConfig{
Command: p.Command,
Args: append([]string(nil), p.Args...),
Env: append([]string(nil), p.Env...),
Persistent: p.Persistent,
Terminal: p.Terminal,
ResponseIdleTimeoutMs: int32(p.ResponseIdleTimeoutMS),
StartupIdleTimeoutMs: int32(p.StartupIdleTimeoutMS),
OutputFormat: p.OutputFormat,
Mode: p.Mode,
ResumeArgs: append([]string(nil), p.ResumeArgs...),
}
if !p.CompletionMarker.Empty() {
out.CompletionMarker = &iop.CLICompletionMarker{
Line: p.CompletionMarker.Line,
Regex: p.CompletionMarker.Regex,
}
}
return out
}