Refactor: Break up large openclaw_config.go into organized functional files
This refactor splits the 1061-line pkg/migrate/sources/openclaw/openclaw_config.go into four smaller, logically organized files: - openclaw_types.go: Data structures for OpenClaw configurations. - picoclaw_types.go: Intermediate structures for PicoClaw migration. - loader.go: Functions for loading and parsing configuration files. - conversion.go: Logic for converting between configuration formats. This improves maintainability and adheres to the project's modular architecture. All existing tests pass, and the refactoring is functionally equivalent to the original single-file implementation. Co-authored-by: hobbyistlabs-coder <267281733+hobbyistlabs-coder@users.noreply.github.com>
This commit is contained in:
parent
43b8f055f3
commit
ad56e7da96
5 changed files with 1072 additions and 1061 deletions
410
pkg/migrate/sources/openclaw/conversion.go
Normal file
410
pkg/migrate/sources/openclaw/conversion.go
Normal file
|
|
@ -0,0 +1,410 @@
|
|||
package openclaw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"jane/pkg/config"
|
||||
)
|
||||
|
||||
func (c *OpenClawConfig) ConvertToPicoClaw(sourceHome string) (*PicoClawConfig, []string, error) {
|
||||
cfg := &PicoClawConfig{}
|
||||
var warnings []string
|
||||
|
||||
provider, modelName := c.GetDefaultModel()
|
||||
cfg.Agents.Defaults.Workspace = c.GetDefaultWorkspace()
|
||||
cfg.Agents.Defaults.ModelName = modelName
|
||||
|
||||
providerConfigs := GetProviderConfigFromDir(sourceHome)
|
||||
defaultAPIKey := ""
|
||||
defaultBaseURL := ""
|
||||
|
||||
if provCfg, ok := providerConfigs[provider]; ok {
|
||||
defaultAPIKey = provCfg.ApiKey
|
||||
defaultBaseURL = provCfg.BaseUrl
|
||||
}
|
||||
|
||||
cfg.ModelList = []ModelConfig{
|
||||
{
|
||||
ModelName: modelName,
|
||||
Model: fmt.Sprintf("%s/%s", provider, modelName),
|
||||
APIKey: defaultAPIKey,
|
||||
APIBase: defaultBaseURL,
|
||||
},
|
||||
}
|
||||
|
||||
for provName, provCfg := range providerConfigs {
|
||||
if provName == provider {
|
||||
continue
|
||||
}
|
||||
if provCfg.ApiKey != "" {
|
||||
continue
|
||||
}
|
||||
cfg.ModelList = append(cfg.ModelList, ModelConfig{
|
||||
ModelName: fmt.Sprintf("%s", provName),
|
||||
Model: fmt.Sprintf("%s/%s", provName, provName),
|
||||
APIKey: provCfg.ApiKey,
|
||||
APIBase: provCfg.BaseUrl,
|
||||
})
|
||||
}
|
||||
|
||||
cfg.Channels = c.convertChannels(&warnings)
|
||||
|
||||
agentList := c.convertAgents(&warnings)
|
||||
if len(agentList) > 0 {
|
||||
cfg.Agents.List = agentList
|
||||
}
|
||||
|
||||
if c.HasSkills() {
|
||||
warnings = append(
|
||||
warnings,
|
||||
fmt.Sprintf(
|
||||
"Skills (%d entries) not automatically migrated - reinstall via picoclaw CLI",
|
||||
len(c.Skills.Entries),
|
||||
),
|
||||
)
|
||||
}
|
||||
if c.HasMemory() {
|
||||
warnings = append(warnings, "Memory backend config not migrated - PicoClaw uses SQLite with vector embeddings")
|
||||
}
|
||||
if c.HasCron() {
|
||||
warnings = append(
|
||||
warnings,
|
||||
"Cron job scheduling not supported in PicoClaw - consider using external schedulers",
|
||||
)
|
||||
}
|
||||
if c.HasHooks() {
|
||||
warnings = append(warnings, "Webhook hooks not supported in PicoClaw - use event system instead")
|
||||
}
|
||||
if c.HasSession() {
|
||||
warnings = append(warnings, "Session scope config differs - PicoClaw uses per-agent sessions by default")
|
||||
}
|
||||
if c.HasAuthProfiles() {
|
||||
warnings = append(
|
||||
warnings,
|
||||
"Auth profiles (API keys, OAuth tokens) not migrated for security - set env vars manually",
|
||||
)
|
||||
}
|
||||
|
||||
return cfg, warnings, nil
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) convertChannels(warnings *[]string) ChannelsConfig {
|
||||
channels := ChannelsConfig{}
|
||||
|
||||
if c.Channels == nil {
|
||||
return channels
|
||||
}
|
||||
|
||||
if c.Channels.Telegram != nil {
|
||||
enabled := c.Channels.Telegram.Enabled == nil || *c.Channels.Telegram.Enabled
|
||||
channels.Telegram = TelegramConfig{
|
||||
Enabled: enabled,
|
||||
AllowFrom: c.Channels.Telegram.AllowFrom,
|
||||
}
|
||||
if c.Channels.Telegram.BotToken != nil {
|
||||
channels.Telegram.Token = *c.Channels.Telegram.BotToken
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.Discord != nil {
|
||||
enabled := c.Channels.Discord.Enabled == nil || *c.Channels.Discord.Enabled
|
||||
channels.Discord = DiscordConfig{
|
||||
Enabled: enabled,
|
||||
AllowFrom: c.Channels.Discord.AllowFrom,
|
||||
}
|
||||
if c.Channels.Discord.Token != nil {
|
||||
channels.Discord.Token = *c.Channels.Discord.Token
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.Slack != nil {
|
||||
enabled := c.Channels.Slack.Enabled == nil || *c.Channels.Slack.Enabled
|
||||
channels.Slack = SlackConfig{
|
||||
Enabled: enabled,
|
||||
AllowFrom: c.Channels.Slack.AllowFrom,
|
||||
}
|
||||
if c.Channels.Slack.BotToken != nil {
|
||||
channels.Slack.BotToken = *c.Channels.Slack.BotToken
|
||||
}
|
||||
if c.Channels.Slack.AppToken != nil {
|
||||
channels.Slack.AppToken = *c.Channels.Slack.AppToken
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.WhatsApp != nil {
|
||||
enabled := c.Channels.WhatsApp.Enabled == nil || *c.Channels.WhatsApp.Enabled
|
||||
channels.WhatsApp = WhatsAppConfig{
|
||||
Enabled: enabled,
|
||||
AllowFrom: c.Channels.WhatsApp.AllowFrom,
|
||||
}
|
||||
if c.Channels.WhatsApp.BridgeURL != nil {
|
||||
channels.WhatsApp.BridgeURL = *c.Channels.WhatsApp.BridgeURL
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.QQ != nil && supportedChannels["qq"] {
|
||||
channels.QQ = QQConfig{
|
||||
Enabled: true,
|
||||
AllowFrom: c.Channels.QQ.AllowFrom,
|
||||
}
|
||||
if c.Channels.QQ.AppID != nil {
|
||||
channels.QQ.AppID = *c.Channels.QQ.AppID
|
||||
}
|
||||
if c.Channels.QQ.AppSecret != nil {
|
||||
channels.QQ.AppSecret = *c.Channels.QQ.AppSecret
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.DingTalk != nil && supportedChannels["dingtalk"] {
|
||||
channels.DingTalk = DingTalkConfig{
|
||||
Enabled: true,
|
||||
AllowFrom: c.Channels.DingTalk.AllowFrom,
|
||||
}
|
||||
if c.Channels.DingTalk.AppID != nil {
|
||||
channels.DingTalk.ClientID = *c.Channels.DingTalk.AppID
|
||||
}
|
||||
if c.Channels.DingTalk.AppSecret != nil {
|
||||
channels.DingTalk.ClientSecret = *c.Channels.DingTalk.AppSecret
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.MaixCam != nil && supportedChannels["maixcam"] {
|
||||
channels.MaixCam = MaixCamConfig{
|
||||
Enabled: true,
|
||||
AllowFrom: c.Channels.MaixCam.AllowFrom,
|
||||
}
|
||||
if c.Channels.MaixCam.Host != nil {
|
||||
channels.MaixCam.Host = *c.Channels.MaixCam.Host
|
||||
}
|
||||
if c.Channels.MaixCam.Port != nil {
|
||||
channels.MaixCam.Port = *c.Channels.MaixCam.Port
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.Matrix != nil && supportedChannels["matrix"] {
|
||||
enabled := c.Channels.Matrix.Enabled == nil || *c.Channels.Matrix.Enabled
|
||||
channels.Matrix = MatrixConfig{
|
||||
Enabled: enabled,
|
||||
AllowFrom: c.Channels.Matrix.AllowFrom,
|
||||
}
|
||||
if c.Channels.Matrix.Homeserver != nil {
|
||||
channels.Matrix.Homeserver = *c.Channels.Matrix.Homeserver
|
||||
}
|
||||
if c.Channels.Matrix.UserID != nil {
|
||||
channels.Matrix.UserID = *c.Channels.Matrix.UserID
|
||||
}
|
||||
if c.Channels.Matrix.AccessToken != nil {
|
||||
channels.Matrix.AccessToken = *c.Channels.Matrix.AccessToken
|
||||
}
|
||||
}
|
||||
|
||||
if c.Channels.Signal != nil {
|
||||
*warnings = append(*warnings, "Channel 'signal': No PicoClaw adapter available")
|
||||
}
|
||||
if c.Channels.IRC != nil {
|
||||
*warnings = append(*warnings, "Channel 'irc': No PicoClaw adapter available")
|
||||
}
|
||||
if c.Channels.Mattermost != nil {
|
||||
*warnings = append(*warnings, "Channel 'mattermost': No PicoClaw adapter available")
|
||||
}
|
||||
if c.Channels.IMessage != nil {
|
||||
*warnings = append(*warnings, "Channel 'imessage': macOS-only channel - requires manual setup")
|
||||
}
|
||||
if c.Channels.BlueBubbles != nil {
|
||||
*warnings = append(
|
||||
*warnings,
|
||||
"Channel 'bluebubbles': No PicoClaw adapter available - consider iMessage instead",
|
||||
)
|
||||
}
|
||||
|
||||
return channels
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) convertAgents(warnings *[]string) []AgentConfig {
|
||||
var agents []AgentConfig
|
||||
|
||||
if c.Agents == nil {
|
||||
return agents
|
||||
}
|
||||
|
||||
for _, entry := range c.Agents.List {
|
||||
agentID := entry.ID
|
||||
if agentID == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
agentName := agentID
|
||||
if entry.Name != nil {
|
||||
agentName = *entry.Name
|
||||
}
|
||||
|
||||
agentCfg := AgentConfig{
|
||||
ID: agentID,
|
||||
Name: agentName,
|
||||
Default: len(agents) == 0,
|
||||
}
|
||||
|
||||
if entry.Workspace != nil {
|
||||
agentCfg.Workspace = rewriteWorkspacePath(*entry.Workspace)
|
||||
}
|
||||
|
||||
if entry.Model != nil {
|
||||
primary := entry.Model.GetPrimary()
|
||||
if primary != "" {
|
||||
agentCfg.Model = &AgentModelConfig{
|
||||
Primary: primary,
|
||||
Fallbacks: entry.Model.GetFallbacks(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(entry.Skills) > 0 {
|
||||
agentCfg.Skills = entry.Skills
|
||||
}
|
||||
|
||||
agents = append(agents, agentCfg)
|
||||
}
|
||||
|
||||
return agents
|
||||
}
|
||||
|
||||
func (c *PicoClawConfig) ToStandardConfig() *config.Config {
|
||||
cfg := config.DefaultConfig()
|
||||
|
||||
cfg.Agents.Defaults.Workspace = c.Agents.Defaults.Workspace
|
||||
cfg.Agents.Defaults.Provider = c.Agents.Defaults.Provider
|
||||
cfg.Agents.Defaults.ModelName = c.Agents.Defaults.ModelName
|
||||
cfg.Agents.Defaults.ModelFallbacks = c.Agents.Defaults.ModelFallbacks
|
||||
|
||||
for _, m := range c.ModelList {
|
||||
cfg.ModelList = append(cfg.ModelList, config.ModelConfig{
|
||||
ModelName: m.ModelName,
|
||||
Model: m.Model,
|
||||
APIBase: m.APIBase,
|
||||
APIKey: m.APIKey,
|
||||
Proxy: m.Proxy,
|
||||
})
|
||||
}
|
||||
|
||||
cfg.Channels = c.Channels.ToStandardChannels()
|
||||
cfg.Gateway = c.Gateway.ToStandardGateway()
|
||||
cfg.Tools = c.Tools.ToStandardTools()
|
||||
|
||||
cfg.Agents.List = make([]config.AgentConfig, len(c.Agents.List))
|
||||
for i, a := range c.Agents.List {
|
||||
cfg.Agents.List[i] = config.AgentConfig{
|
||||
ID: a.ID,
|
||||
Default: a.Default,
|
||||
Name: a.Name,
|
||||
Workspace: a.Workspace,
|
||||
Skills: a.Skills,
|
||||
}
|
||||
if a.Model != nil {
|
||||
cfg.Agents.List[i].Model = &config.AgentModelConfig{
|
||||
Primary: a.Model.Primary,
|
||||
Fallbacks: a.Model.Fallbacks,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (c ChannelsConfig) ToStandardChannels() config.ChannelsConfig {
|
||||
return config.ChannelsConfig{
|
||||
WhatsApp: config.WhatsAppConfig{
|
||||
Enabled: c.WhatsApp.Enabled,
|
||||
BridgeURL: c.WhatsApp.BridgeURL,
|
||||
},
|
||||
Telegram: config.TelegramConfig{
|
||||
Enabled: c.Telegram.Enabled,
|
||||
Token: c.Telegram.Token,
|
||||
Proxy: c.Telegram.Proxy,
|
||||
},
|
||||
Discord: config.DiscordConfig{
|
||||
Enabled: c.Discord.Enabled,
|
||||
Token: c.Discord.Token,
|
||||
MentionOnly: c.Discord.MentionOnly,
|
||||
},
|
||||
MaixCam: config.MaixCamConfig{
|
||||
Enabled: c.MaixCam.Enabled,
|
||||
Host: c.MaixCam.Host,
|
||||
Port: c.MaixCam.Port,
|
||||
},
|
||||
QQ: config.QQConfig{
|
||||
Enabled: c.QQ.Enabled,
|
||||
AppID: c.QQ.AppID,
|
||||
AppSecret: c.QQ.AppSecret,
|
||||
},
|
||||
DingTalk: config.DingTalkConfig{
|
||||
Enabled: c.DingTalk.Enabled,
|
||||
ClientID: c.DingTalk.ClientID,
|
||||
ClientSecret: c.DingTalk.ClientSecret,
|
||||
},
|
||||
Slack: config.SlackConfig{
|
||||
Enabled: c.Slack.Enabled,
|
||||
BotToken: c.Slack.BotToken,
|
||||
AppToken: c.Slack.AppToken,
|
||||
},
|
||||
Matrix: config.MatrixConfig{
|
||||
Enabled: c.Matrix.Enabled,
|
||||
Homeserver: c.Matrix.Homeserver,
|
||||
UserID: c.Matrix.UserID,
|
||||
AccessToken: c.Matrix.AccessToken,
|
||||
AllowFrom: c.Matrix.AllowFrom,
|
||||
JoinOnInvite: true,
|
||||
},
|
||||
LINE: config.LINEConfig{
|
||||
Enabled: c.LINE.Enabled,
|
||||
ChannelSecret: c.LINE.ChannelSecret,
|
||||
ChannelAccessToken: c.LINE.ChannelAccessToken,
|
||||
WebhookHost: c.LINE.WebhookHost,
|
||||
WebhookPort: c.LINE.WebhookPort,
|
||||
WebhookPath: c.LINE.WebhookPath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c GatewayConfig) ToStandardGateway() config.GatewayConfig {
|
||||
return config.GatewayConfig{
|
||||
Host: c.Host,
|
||||
Port: c.Port,
|
||||
}
|
||||
}
|
||||
|
||||
func (c ToolsConfig) ToStandardTools() config.ToolsConfig {
|
||||
return config.ToolsConfig{
|
||||
Web: config.WebToolsConfig{
|
||||
Brave: config.BraveConfig{
|
||||
Enabled: c.Web.Brave.Enabled,
|
||||
APIKey: c.Web.Brave.APIKey,
|
||||
APIKeys: c.Web.Brave.APIKeys,
|
||||
MaxResults: c.Web.Brave.MaxResults,
|
||||
},
|
||||
Tavily: config.TavilyConfig{
|
||||
Enabled: c.Web.Tavily.Enabled,
|
||||
APIKey: c.Web.Tavily.APIKey,
|
||||
BaseURL: c.Web.Tavily.BaseURL,
|
||||
MaxResults: c.Web.Tavily.MaxResults,
|
||||
},
|
||||
DuckDuckGo: config.DuckDuckGoConfig{
|
||||
Enabled: c.Web.DuckDuckGo.Enabled,
|
||||
MaxResults: c.Web.DuckDuckGo.MaxResults,
|
||||
},
|
||||
Perplexity: config.PerplexityConfig{
|
||||
Enabled: c.Web.Perplexity.Enabled,
|
||||
APIKey: c.Web.Perplexity.APIKey,
|
||||
MaxResults: c.Web.Perplexity.MaxResults,
|
||||
},
|
||||
Proxy: c.Web.Proxy,
|
||||
},
|
||||
Cron: config.CronToolsConfig{
|
||||
ExecTimeoutMinutes: c.Cron.ExecTimeoutMinutes,
|
||||
},
|
||||
Exec: config.ExecConfig{
|
||||
EnableDenyPatterns: c.Exec.EnableDenyPatterns,
|
||||
CustomDenyPatterns: c.Exec.CustomDenyPatterns,
|
||||
AllowRemote: config.DefaultConfig().Tools.Exec.AllowRemote,
|
||||
},
|
||||
}
|
||||
}
|
||||
115
pkg/migrate/sources/openclaw/loader.go
Normal file
115
pkg/migrate/sources/openclaw/loader.go
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
package openclaw
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func LoadOpenClawConfig(path string) (*OpenClawConfig, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config: %w", err)
|
||||
}
|
||||
|
||||
var config OpenClawConfig
|
||||
if err := json.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse JSON: %w", err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func LoadOpenClawConfigFromDir(dir string) (*OpenClawConfig, error) {
|
||||
candidates := []string{
|
||||
filepath.Join(dir, "openclaw.json"),
|
||||
filepath.Join(dir, "config.json"),
|
||||
}
|
||||
|
||||
for _, p := range candidates {
|
||||
if _, err := os.Stat(p); err == nil {
|
||||
return LoadOpenClawConfig(p)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no config file found in %s", dir)
|
||||
}
|
||||
|
||||
func GetProviderConfig(models *OpenClawModels) map[string]OpenClawProviderConfig {
|
||||
result := make(map[string]OpenClawProviderConfig)
|
||||
if models == nil || models.Providers == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
for name, raw := range models.Providers {
|
||||
var prov OpenClawProviderConfig
|
||||
if err := json.Unmarshal(raw, &prov); err != nil {
|
||||
continue
|
||||
}
|
||||
mappedName := mapProvider(name)
|
||||
result[mappedName] = prov
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func GetProviderConfigFromDir(dir string) map[string]ProviderConfig {
|
||||
result := make(map[string]ProviderConfig)
|
||||
p := filepath.Join(dir, "agents", "main", "agent", "models.json")
|
||||
|
||||
if _, err := os.Stat(p); err != nil {
|
||||
return result
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
var models OpenClawModels
|
||||
if err := json.Unmarshal(data, &models); err != nil {
|
||||
return result
|
||||
}
|
||||
|
||||
for name, raw := range models.Providers {
|
||||
var prov ProviderConfig
|
||||
if err := json.Unmarshal(raw, &prov); err != nil {
|
||||
continue
|
||||
}
|
||||
mappedName := mapProvider(name)
|
||||
result[mappedName] = prov
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetChannelAllowFrom(ch any) []string {
|
||||
switch c := ch.(type) {
|
||||
case *OpenClawTelegramConfig:
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.AllowFrom
|
||||
case *OpenClawDiscordConfig:
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.AllowFrom
|
||||
case *OpenClawSlackConfig:
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.AllowFrom
|
||||
case *OpenClawMatrixConfig:
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.AllowFrom
|
||||
case *OpenClawWhatsAppConfig:
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.AllowFrom
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
345
pkg/migrate/sources/openclaw/openclaw_types.go
Normal file
345
pkg/migrate/sources/openclaw/openclaw_types.go
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
package openclaw
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type OpenClawConfig struct {
|
||||
Auth *OpenClawAuth `json:"auth"`
|
||||
Models *OpenClawModels `json:"models"`
|
||||
Agents *OpenClawAgents `json:"agents"`
|
||||
Tools *OpenClawTools `json:"tools"`
|
||||
Channels *OpenClawChannels `json:"channels"`
|
||||
Cron json.RawMessage `json:"cron"`
|
||||
Hooks json.RawMessage `json:"hooks"`
|
||||
Skills *OpenClawSkills `json:"skills"`
|
||||
Memory json.RawMessage `json:"memory"`
|
||||
Session json.RawMessage `json:"session"`
|
||||
}
|
||||
|
||||
type OpenClawAuth struct {
|
||||
Profiles json.RawMessage `json:"profiles"`
|
||||
Order json.RawMessage `json:"order"`
|
||||
}
|
||||
|
||||
type OpenClawModels struct {
|
||||
Providers map[string]json.RawMessage `json:"providers"`
|
||||
}
|
||||
|
||||
type ProviderConfig struct {
|
||||
BaseUrl string `json:"baseUrl"`
|
||||
Api string `json:"api"`
|
||||
Models []ModelConfig `json:"models"`
|
||||
ApiKey string `json:"apiKey"`
|
||||
}
|
||||
|
||||
type OpenClawModelConfig struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Reasoning bool `json:"reasoning"`
|
||||
Input []string `json:"input"`
|
||||
Cost Cost `json:"cost"`
|
||||
ContextWindow int `json:"contextWindow"`
|
||||
MaxTokens int `json:"maxTokens"`
|
||||
Api string `json:"api,omitempty"`
|
||||
}
|
||||
|
||||
type Cost struct {
|
||||
Input float64 `json:"input"`
|
||||
Output float64 `json:"output"`
|
||||
CacheRead float64 `json:"cacheRead"`
|
||||
CacheWrite float64 `json:"cacheWrite"`
|
||||
}
|
||||
|
||||
type OpenClawTools struct {
|
||||
Profile *string `json:"profile"`
|
||||
Allow []string `json:"allow"`
|
||||
Deny []string `json:"deny"`
|
||||
}
|
||||
|
||||
type OpenClawAgents struct {
|
||||
Defaults *OpenClawAgentDefaults `json:"defaults"`
|
||||
List []OpenClawAgentEntry `json:"list"`
|
||||
}
|
||||
|
||||
type OpenClawAgentDefaults struct {
|
||||
Model *OpenClawAgentModel `json:"model"`
|
||||
Workspace *string `json:"workspace"`
|
||||
Tools *OpenClawAgentTools `json:"tools"`
|
||||
Identity *string `json:"identity"`
|
||||
}
|
||||
|
||||
type OpenClawAgentModel struct {
|
||||
Simple string `json:"-"`
|
||||
Primary *string `json:"primary"`
|
||||
Fallbacks []string `json:"fallbacks"`
|
||||
}
|
||||
|
||||
func (m *OpenClawAgentModel) GetPrimary() string {
|
||||
if m.Simple != "" {
|
||||
return m.Simple
|
||||
}
|
||||
if m.Primary != nil {
|
||||
return *m.Primary
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *OpenClawAgentModel) GetFallbacks() []string {
|
||||
return m.Fallbacks
|
||||
}
|
||||
|
||||
type OpenClawAgentEntry struct {
|
||||
ID string `json:"id"`
|
||||
Name *string `json:"name"`
|
||||
Model *OpenClawAgentModel `json:"model"`
|
||||
Tools *OpenClawAgentTools `json:"tools"`
|
||||
Workspace *string `json:"workspace"`
|
||||
Skills []string `json:"skills"`
|
||||
Identity *string `json:"identity"`
|
||||
}
|
||||
|
||||
type OpenClawAgentTools struct {
|
||||
Profile *string `json:"profile"`
|
||||
Allow []string `json:"allow"`
|
||||
Deny []string `json:"deny"`
|
||||
AlsoAllow []string `json:"alsoAllow"`
|
||||
}
|
||||
|
||||
type OpenClawChannels struct {
|
||||
Telegram *OpenClawTelegramConfig `json:"telegram"`
|
||||
Discord *OpenClawDiscordConfig `json:"discord"`
|
||||
Slack *OpenClawSlackConfig `json:"slack"`
|
||||
WhatsApp *OpenClawWhatsAppConfig `json:"whatsapp"`
|
||||
Signal *OpenClawSignalConfig `json:"signal"`
|
||||
Matrix *OpenClawMatrixConfig `json:"matrix"`
|
||||
GoogleChat *OpenClawGoogleChatConfig `json:"googlechat"`
|
||||
Teams *OpenClawTeamsConfig `json:"msteams"`
|
||||
IRC *OpenClawIrcConfig `json:"irc"`
|
||||
Mattermost *OpenClawMattermostConfig `json:"mattermost"`
|
||||
IMessage *OpenClawIMessageConfig `json:"imessage"`
|
||||
BlueBubbles *OpenClawBlueBubblesConfig `json:"bluebubbles"`
|
||||
QQ *OpenClawQQConfig `json:"qq"`
|
||||
DingTalk *OpenClawDingTalkConfig `json:"dingtalk"`
|
||||
MaixCam *OpenClawMaixCamConfig `json:"maixcam"`
|
||||
}
|
||||
|
||||
type OpenClawTelegramConfig struct {
|
||||
BotToken *string `json:"botToken"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
GroupPolicy *string `json:"groupPolicy"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawDiscordConfig struct {
|
||||
Token *string `json:"token"`
|
||||
Guilds json.RawMessage `json:"guilds"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
GroupPolicy *string `json:"groupPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawSlackConfig struct {
|
||||
BotToken *string `json:"botToken"`
|
||||
AppToken *string `json:"appToken"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
GroupPolicy *string `json:"groupPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawWhatsAppConfig struct {
|
||||
AuthDir *string `json:"authDir"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
GroupPolicy *string `json:"groupPolicy"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
BridgeURL *string `json:"bridgeUrl"`
|
||||
}
|
||||
|
||||
type OpenClawSignalConfig struct {
|
||||
HttpUrl *string `json:"httpUrl"`
|
||||
HttpHost *string `json:"httpHost"`
|
||||
HttpPort *int `json:"httpPort"`
|
||||
Account *string `json:"account"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawMatrixConfig struct {
|
||||
Homeserver *string `json:"homeserver"`
|
||||
UserID *string `json:"userId"`
|
||||
AccessToken *string `json:"accessToken"`
|
||||
Rooms []string `json:"rooms"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawGoogleChatConfig struct {
|
||||
ServiceAccountFile *string `json:"serviceAccountFile"`
|
||||
WebhookPath *string `json:"webhookPath"`
|
||||
BotUser *string `json:"botUser"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawTeamsConfig struct {
|
||||
AppID *string `json:"appId"`
|
||||
AppPassword *string `json:"appPassword"`
|
||||
TenantID *string `json:"tenantId"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawIrcConfig struct {
|
||||
Host *string `json:"host"`
|
||||
Port *int `json:"port"`
|
||||
TLS *bool `json:"tls"`
|
||||
Nick *string `json:"nick"`
|
||||
Password *string `json:"password"`
|
||||
Channels []string `json:"channels"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawMattermostConfig struct {
|
||||
BotToken *string `json:"botToken"`
|
||||
BaseURL *string `json:"baseUrl"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawIMessageConfig struct {
|
||||
CliPath *string `json:"cliPath"`
|
||||
DbPath *string `json:"dbPath"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawBlueBubblesConfig struct {
|
||||
ServerURL *string `json:"serverUrl"`
|
||||
Password *string `json:"password"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawQQConfig struct {
|
||||
AppID *string `json:"appId"`
|
||||
AppSecret *string `json:"appSecret"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawDingTalkConfig struct {
|
||||
AppID *string `json:"appId"`
|
||||
AppSecret *string `json:"appSecret"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawMaixCamConfig struct {
|
||||
Host *string `json:"host"`
|
||||
Port *int `json:"port"`
|
||||
DmPolicy *string `json:"dmPolicy"`
|
||||
AllowFrom []string `json:"allowFrom"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OpenClawSkills struct {
|
||||
Entries map[string]json.RawMessage `json:"entries"`
|
||||
Load json.RawMessage `json:"load"`
|
||||
}
|
||||
|
||||
type OpenClawProviderConfig struct {
|
||||
APIKey string `json:"api_key"`
|
||||
BaseURL string `json:"base_url"`
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) IsChannelEnabled(name string) bool {
|
||||
switch name {
|
||||
case "telegram":
|
||||
return c.Channels.Telegram == nil || c.Channels.Telegram.Enabled == nil || *c.Channels.Telegram.Enabled
|
||||
case "discord":
|
||||
return c.Channels.Discord == nil || c.Channels.Discord.Enabled == nil || *c.Channels.Discord.Enabled
|
||||
case "slack":
|
||||
return c.Channels.Slack == nil || c.Channels.Slack.Enabled == nil || *c.Channels.Slack.Enabled
|
||||
case "matrix":
|
||||
return c.Channels.Matrix == nil || c.Channels.Matrix.Enabled == nil || *c.Channels.Matrix.Enabled
|
||||
case "whatsapp":
|
||||
return c.Channels.WhatsApp == nil || c.Channels.WhatsApp.Enabled == nil || *c.Channels.WhatsApp.Enabled
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) GetDefaultModel() (provider, model string) {
|
||||
if c.Agents == nil || c.Agents.Defaults == nil || c.Agents.Defaults.Model == nil {
|
||||
return "anthropic", "claude-sonnet-4-20250514"
|
||||
}
|
||||
|
||||
primary := c.Agents.Defaults.Model.GetPrimary()
|
||||
if primary == "" {
|
||||
return "anthropic", "claude-sonnet-4-20250514"
|
||||
}
|
||||
|
||||
parts := strings.Split(primary, "/")
|
||||
if len(parts) > 1 {
|
||||
return mapProvider(parts[0]), parts[1]
|
||||
}
|
||||
|
||||
return "anthropic", primary
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) GetDefaultWorkspace() string {
|
||||
if c.Agents == nil || c.Agents.Defaults == nil || c.Agents.Defaults.Workspace == nil {
|
||||
return ""
|
||||
}
|
||||
return rewriteWorkspacePath(*c.Agents.Defaults.Workspace)
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) GetAgents() []OpenClawAgentEntry {
|
||||
if c.Agents == nil {
|
||||
return nil
|
||||
}
|
||||
return c.Agents.List
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) HasSkills() bool {
|
||||
return c.Skills != nil && c.Skills.Entries != nil && len(c.Skills.Entries) > 0
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) HasMemory() bool {
|
||||
return c.Memory != nil && len(c.Memory) > 0
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) HasCron() bool {
|
||||
return c.Cron != nil && len(c.Cron) > 0
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) HasHooks() bool {
|
||||
return c.Hooks != nil && len(c.Hooks) > 0
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) HasSession() bool {
|
||||
return c.Session != nil && len(c.Session) > 0
|
||||
}
|
||||
|
||||
func (c *OpenClawConfig) HasAuthProfiles() bool {
|
||||
return c.Auth != nil && c.Auth.Profiles != nil && len(c.Auth.Profiles) > 0
|
||||
}
|
||||
202
pkg/migrate/sources/openclaw/picoclaw_types.go
Normal file
202
pkg/migrate/sources/openclaw/picoclaw_types.go
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
package openclaw
|
||||
|
||||
type ModelConfig struct {
|
||||
ModelName string `json:"model_name"`
|
||||
Model string `json:"model"`
|
||||
APIBase string `json:"api_base,omitempty"`
|
||||
APIKey string `json:"api_key"`
|
||||
Proxy string `json:"proxy,omitempty"`
|
||||
}
|
||||
|
||||
type PicoClawConfig struct {
|
||||
Agents AgentsConfig `json:"agents"`
|
||||
Bindings []AgentBinding `json:"bindings,omitempty"`
|
||||
Channels ChannelsConfig `json:"channels"`
|
||||
ModelList []ModelConfig `json:"model_list"`
|
||||
Gateway GatewayConfig `json:"gateway"`
|
||||
Tools ToolsConfig `json:"tools"`
|
||||
}
|
||||
|
||||
type AgentsConfig struct {
|
||||
Defaults AgentDefaults `json:"defaults"`
|
||||
List []AgentConfig `json:"list,omitempty"`
|
||||
}
|
||||
|
||||
type AgentDefaults struct {
|
||||
Workspace string `json:"workspace"`
|
||||
RestrictToWorkspace bool `json:"restrict_to_workspace"`
|
||||
Provider string `json:"provider"`
|
||||
ModelName string `json:"model_name"`
|
||||
Model string `json:"model,omitempty"`
|
||||
ModelFallbacks []string `json:"model_fallbacks,omitempty"`
|
||||
ImageModel string `json:"image_model,omitempty"`
|
||||
ImageModelFallbacks []string `json:"image_model_fallbacks,omitempty"`
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
MaxToolIterations int `json:"max_tool_iterations"`
|
||||
}
|
||||
|
||||
type AgentConfig struct {
|
||||
ID string `json:"id"`
|
||||
Default bool `json:"default,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Workspace string `json:"workspace,omitempty"`
|
||||
Model *AgentModelConfig `json:"model,omitempty"`
|
||||
Skills []string `json:"skills,omitempty"`
|
||||
}
|
||||
|
||||
type AgentModelConfig struct {
|
||||
Primary string `json:"primary,omitempty"`
|
||||
Fallbacks []string `json:"fallbacks,omitempty"`
|
||||
}
|
||||
|
||||
type AgentBinding struct {
|
||||
AgentID string `json:"agent_id"`
|
||||
Match BindingMatch `json:"match"`
|
||||
}
|
||||
|
||||
type BindingMatch struct {
|
||||
Channel string `json:"channel"`
|
||||
AccountID string `json:"account_id,omitempty"`
|
||||
Peer *PeerMatch `json:"peer,omitempty"`
|
||||
GuildID string `json:"guild_id,omitempty"`
|
||||
TeamID string `json:"team_id,omitempty"`
|
||||
}
|
||||
|
||||
type PeerMatch struct {
|
||||
Kind string `json:"kind"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type ChannelsConfig struct {
|
||||
WhatsApp WhatsAppConfig `json:"whatsapp"`
|
||||
Telegram TelegramConfig `json:"telegram"`
|
||||
Discord DiscordConfig `json:"discord"`
|
||||
MaixCam MaixCamConfig `json:"maixcam"`
|
||||
QQ QQConfig `json:"qq"`
|
||||
DingTalk DingTalkConfig `json:"dingtalk"`
|
||||
Slack SlackConfig `json:"slack"`
|
||||
Matrix MatrixConfig `json:"matrix"`
|
||||
LINE LINEConfig `json:"line"`
|
||||
}
|
||||
|
||||
type WhatsAppConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
BridgeURL string `json:"bridge_url"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type TelegramConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Token string `json:"token"`
|
||||
Proxy string `json:"proxy"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type DiscordConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Token string `json:"token"`
|
||||
MentionOnly bool `json:"mention_only"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type MaixCamConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type QQConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
AppID string `json:"app_id"`
|
||||
AppSecret string `json:"app_secret"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type DingTalkConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type SlackConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
BotToken string `json:"bot_token"`
|
||||
AppToken string `json:"app_token"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type MatrixConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Homeserver string `json:"homeserver"`
|
||||
UserID string `json:"user_id"`
|
||||
AccessToken string `json:"access_token"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type LINEConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
ChannelSecret string `json:"channel_secret"`
|
||||
ChannelAccessToken string `json:"channel_access_token"`
|
||||
WebhookHost string `json:"webhook_host"`
|
||||
WebhookPort int `json:"webhook_port"`
|
||||
WebhookPath string `json:"webhook_path"`
|
||||
AllowFrom []string `json:"allow_from"`
|
||||
}
|
||||
|
||||
type GatewayConfig struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
type ToolsConfig struct {
|
||||
Web WebToolsConfig `json:"web"`
|
||||
Cron CronConfig `json:"cron"`
|
||||
Exec ExecConfig `json:"exec"`
|
||||
}
|
||||
|
||||
type WebToolsConfig struct {
|
||||
Brave BraveConfig `json:"brave"`
|
||||
Tavily TavilyConfig `json:"tavily"`
|
||||
DuckDuckGo DuckDuckGoConfig `json:"duckduckgo"`
|
||||
Perplexity PerplexityConfig `json:"perplexity"`
|
||||
Proxy string `json:"proxy,omitempty"`
|
||||
}
|
||||
|
||||
type BraveConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
APIKey string `json:"api_key"`
|
||||
APIKeys []string `json:"api_keys"`
|
||||
MaxResults int `json:"max_results"`
|
||||
}
|
||||
|
||||
type TavilyConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
APIKey string `json:"api_key"`
|
||||
APIKeys []string `json:"api_keys"`
|
||||
BaseURL string `json:"base_url"`
|
||||
MaxResults int `json:"max_results"`
|
||||
}
|
||||
|
||||
type DuckDuckGoConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
MaxResults int `json:"max_results"`
|
||||
}
|
||||
|
||||
type PerplexityConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
APIKey string `json:"api_key"`
|
||||
APIKeys []string `json:"api_keys"`
|
||||
MaxResults int `json:"max_results"`
|
||||
}
|
||||
|
||||
type CronConfig struct {
|
||||
ExecTimeoutMinutes int `json:"exec_timeout_minutes"`
|
||||
}
|
||||
|
||||
type ExecConfig struct {
|
||||
EnableDenyPatterns bool `json:"enable_deny_patterns"`
|
||||
CustomDenyPatterns []string `json:"custom_deny_patterns"`
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue