fix(llm): mount openclaw home dir (#24449)

This commit is contained in:
Zexi Li
2026-03-13 20:38:28 +08:00
committed by GitHub
parent f1df0e3ac1
commit ace220a0ca
4 changed files with 114 additions and 12 deletions
-8
View File
@@ -81,11 +81,3 @@ const (
)
type LLMEnvKey string
const (
LLM_OPENCLAW_GATEWAY_TOKEN = LLMEnvKey("OPENCLAW_GATEWAY_TOKEN")
LLM_OPENCLAW_AUTH_USERNAME = LLMEnvKey("AUTH_USERNAME")
LLM_OPENCLAW_CUSTOM_USER = LLMEnvKey("CUSTOM_USER")
LLM_OPENCLAW_AUTH_PASSWORD = LLMEnvKey("AUTH_PASSWORD")
LLM_OPENCLAW_PASSWORD = LLMEnvKey("PASSWORD")
)
+42
View File
@@ -0,0 +1,42 @@
package llm
const (
LLM_OPENCLAW_GATEWAY_TOKEN = LLMEnvKey("OPENCLAW_GATEWAY_TOKEN")
LLM_OPENCLAW_AUTH_USERNAME = LLMEnvKey("AUTH_USERNAME")
LLM_OPENCLAW_CUSTOM_USER = LLMEnvKey("CUSTOM_USER")
LLM_OPENCLAW_AUTH_PASSWORD = LLMEnvKey("AUTH_PASSWORD")
LLM_OPENCLAW_PASSWORD = LLMEnvKey("PASSWORD")
LLM_OPENCLAW_CUSTOM_CONFIG = LLMEnvKey("OPENCLAW_CUSTOM_CONFIG")
LLM_OPENCLAW_CUSTOM_CONFIG_FILE = "/opt/openclaw_base_config.json"
// templates
LLM_OPENCLAW_TEMPLATE_AGENTS_MD_B64 = LLMEnvKey("OPENCLAW_TEMPLATE_AGENTS_MD_B64")
LLM_OPENCLAW_TEMPLATE_SOUL_MD_B64 = LLMEnvKey("OPENCLAW_TEMPLATE_SOUL_MD_B64")
LLM_OPENCLAW_TEMPLATE_USER_MD_B64 = LLMEnvKey("OPENCLAW_TEMPLATE_USER_MD_B64")
)
type OpenClawConfig struct {
Browser *OpenClawConfigBrowser `json:"browser"`
Agents *OpenClawConfigAgents `json:"agents"`
}
type OpenClawConfigAgents map[string]*OpenClawConfigAgent
type OpenClawConfigAgent struct {
Model *OpenClawConfigAgentModel `json:"model"`
ImageModel *OpenClawConfigAgentModel `json:"imageModel"`
Workspace string `json:"workspace"`
}
type OpenClawConfigAgentModel struct {
Primary string `json:"primary"`
}
// ref: https://docs.openclaw.ai/tools/browser#configuration
type OpenClawConfigBrowser struct {
Enabled bool `json:"enabled"`
SSRFPolicy map[string]interface{} `json:"ssrfPolicy"`
DefaultProfile string `json:"defaultProfile"`
Headless bool `json:"headless"`
NoSandbox bool `json:"noSandbox"`
}
@@ -57,6 +57,9 @@ func (t text) GetRuntimeMountHostPath(pod IPodInfo, ctrId string, vm *hostapi.Co
dirPath = rootFsPath
}
mntPath := filepath.Join(dirPath, fmt.Sprintf("%s-%s", ctrId, strings.ReplaceAll(vm.MountPath, "/", "_")))
if err := EnsureDir(filepath.Dir(mntPath)); err != nil {
return "", errors.Wrapf(err, "mkdir %s", filepath.Dir(mntPath))
}
if err := t.writeContent(ti, mntPath); err != nil {
return "", errors.Wrapf(err, "write content %s to %s", ti, mntPath)
}
+69 -4
View File
@@ -2,6 +2,7 @@ package llm_container
import (
"context"
"encoding/base64"
"fmt"
"strings"
@@ -23,7 +24,8 @@ const (
// browserContainerName = "browser"
// openclawBrowserImage = "registry.cn-beijing.aliyuncs.com/cloudpods/openclaw-browser:latest"
openclawDataDir = "/data"
browserConfigDir = "/config"
desktopConfigDir = "/config"
homeDir = "/home/"
// openclawBrowserCDPPort = "9222"
)
@@ -230,6 +232,28 @@ func (c *openclaw) GetContainerSpec(ctx context.Context, llm *models.SLLM, image
// }
// }
func (c *openclaw) getOpenClawBaseConfig(llm *models.SLLM) *api.OpenClawConfig {
return &api.OpenClawConfig{
Browser: &api.OpenClawConfigBrowser{
Enabled: true,
DefaultProfile: "openclaw",
SSRFPolicy: map[string]interface{}{
"dangerouslyAllowPrivateNetwork": true,
},
Headless: false,
NoSandbox: false,
},
Agents: &api.OpenClawConfigAgents{
"defaults": &api.OpenClawConfigAgent{
// TODO: 支持从 llm spec 里面自动选择
ImageModel: &api.OpenClawConfigAgentModel{
Primary: "moonshot/kimi-k2.5",
},
},
},
}
}
func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, image *models.SLLMImage, sku *models.SLLMSku, props []string, devices []computeapi.SIsolatedDevice, diskId string) []*computeapi.PodContainerCreateInput {
diskIndex := 0
@@ -240,7 +264,15 @@ func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, imag
SubDirectory: "config",
},
Type: commonapi.CONTAINER_VOLUME_MOUNT_TYPE_DISK,
MountPath: browserConfigDir,
MountPath: desktopConfigDir,
},
{
Disk: &commonapi.ContainerVolumeMountDisk{
Index: &diskIndex,
SubDirectory: "home",
},
Type: commonapi.CONTAINER_VOLUME_MOUNT_TYPE_DISK,
MountPath: homeDir,
},
{
Disk: &commonapi.ContainerVolumeMountDisk{
@@ -250,6 +282,13 @@ func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, imag
Type: commonapi.CONTAINER_VOLUME_MOUNT_TYPE_DISK,
MountPath: openclawDataDir,
},
{
Type: commonapi.CONTAINER_VOLUME_MOUNT_TYPE_TEXT,
Text: &commonapi.ContainerVolumeMountText{
Content: jsonutils.Marshal(c.getOpenClawBaseConfig(llm)).PrettyString(),
},
MountPath: api.LLM_OPENCLAW_CUSTOM_CONFIG_FILE,
},
}
httpAuthUsername := "admin"
httpAuthPassword := "clawadmin@123"
@@ -268,6 +307,10 @@ func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, imag
{Key: "PUID", Value: "1000"},
{Key: "PGID", Value: "1000"},
{Key: "LC_ALL", Value: "zh_CN.UTF-8"},
// webtop envs: https://github.com/linuxserver/docker-webtop?tab=readme-ov-file#advanced-configuration
// {Key: "DISABLE_SUDO", Value: "true"},
// Provider
// {Key: "MOONSHOT_API_KEY", Value: "abc"},
// {Key: "OPENCLAW_PRIMARY_MODEL", Value: "moonshot/kimi-k2.5"},
@@ -276,12 +319,13 @@ func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, imag
{Key: string(api.LLM_OPENCLAW_CUSTOM_USER), Value: httpAuthUsername},
{Key: string(api.LLM_OPENCLAW_AUTH_PASSWORD), Value: httpAuthPassword},
{Key: string(api.LLM_OPENCLAW_PASSWORD), Value: httpAuthPassword},
{Key: string(api.LLM_OPENCLAW_CUSTOM_CONFIG), Value: api.LLM_OPENCLAW_CUSTOM_CONFIG_FILE},
// // Browser sidecar
// {Key: "BROWSER_CDP_URL", Value: "http://localhost" + ":" + openclawBrowserCDPPort},
// {Key: "BROWSER_DEFAULT_PROFILE", Value: "openclaw"},
// {Key: "BROWSER_EVALUATE_ENABLED", Value: "true"},
// OpenClaw env
{Key: "OPENCLAW_GATEWAY_TOKEN", Value: "abcd"},
{Key: "OPENCLAW_GATEWAY_TOKEN", Value: llm.GetId()},
{Key: "OPENCLAW_GATEWAY_PORT", Value: "18789"},
{Key: "OPENCLAW_GATEWAY_BIND", Value: "loopback"},
{Key: "OPENCLAW_STATE_DIR", Value: "/config/.openclaw"},
@@ -299,7 +343,7 @@ func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, imag
Index: &diskIndex,
SubDirectory: "rootfs",
},
Persistent: true,
Persistent: false,
},
}
// inject credential envs
@@ -320,6 +364,27 @@ func (c *openclaw) GetContainerSpecs(ctx context.Context, llm *models.SLLM, imag
for _, channel := range skuSpec.Channels {
openclawSpec.Envs = appendCredentialEnvs(openclawSpec.Envs, channel.Credential)
}
// inject workspace templates
if skuSpec.WorkspaceTemplates != nil {
if skuSpec.WorkspaceTemplates.AgentsMD != "" {
openclawSpec.Envs = append(openclawSpec.Envs, &commonapi.ContainerKeyValue{
Key: string(api.LLM_OPENCLAW_TEMPLATE_AGENTS_MD_B64),
Value: base64.StdEncoding.EncodeToString([]byte(skuSpec.WorkspaceTemplates.AgentsMD)),
})
}
if skuSpec.WorkspaceTemplates.SoulMD != "" {
openclawSpec.Envs = append(openclawSpec.Envs, &commonapi.ContainerKeyValue{
Key: string(api.LLM_OPENCLAW_TEMPLATE_SOUL_MD_B64),
Value: base64.StdEncoding.EncodeToString([]byte(skuSpec.WorkspaceTemplates.SoulMD)),
})
}
if skuSpec.WorkspaceTemplates.UserMD != "" {
openclawSpec.Envs = append(openclawSpec.Envs, &commonapi.ContainerKeyValue{
Key: string(api.LLM_OPENCLAW_TEMPLATE_USER_MD_B64),
Value: base64.StdEncoding.EncodeToString([]byte(skuSpec.WorkspaceTemplates.UserMD)),
})
}
}
return []*computeapi.PodContainerCreateInput{
{