11package substrate
22
33import (
4+ "bytes"
45 "context"
6+ _ "embed"
57 "encoding/base64"
68 "fmt"
79 "strings"
10+ "text/template"
811
912 "github.com/kagent-dev/kagent/go/api/v1alpha2"
1013 "github.com/kagent-dev/kagent/go/core/internal/utils"
@@ -14,6 +17,16 @@ import (
1417
1518const defaultSubstrateOpenClawGatewayPort = 80
1619
20+ //go:embed templates/openclaw_startup.sh.tmpl
21+ var openClawStartupScriptTmplContent string
22+
23+ var openClawStartupScriptTmpl = template .Must (template .New ("openclaw_startup" ).Parse (openClawStartupScriptTmplContent ))
24+
25+ type openClawStartupScriptData struct {
26+ OpenClawJSONBase64 string
27+ GatewayPort int
28+ }
29+
1730// buildOpenClawActorStartup returns the ateom workload startup script and container env for OpenClaw on Substrate.
1831// When spec.modelConfigRef is set, openclaw.json includes models/agents/channels like the OpenShell bootstrap path.
1932func (p * Provisioner ) buildOpenClawActorStartup (ctx context.Context , ah * v1alpha2.AgentHarness ) (script string , env []corev1.EnvVar , err error ) {
@@ -54,7 +67,10 @@ func (p *Provisioner) buildOpenClawActorStartup(ctx context.Context, ah *v1alpha
5467 }
5568 containerEnv = []corev1.EnvVar {{Name : "HOME" , Value : "/root" }}
5669 }
57- script = openClawStartupScript (jsonBytes , gw .Port )
70+ script , err = openClawStartupScript (jsonBytes , gw .Port )
71+ if err != nil {
72+ return "" , nil , err
73+ }
5874 return script , containerEnv , nil
5975}
6076
@@ -65,17 +81,13 @@ func openClawControlUIBasePath(ah *v1alpha2.AgentHarness) string {
6581 return "/api/agentharnesses/" + ah .Namespace + "/" + ah .Name + "/gateway"
6682}
6783
68- func openClawStartupScript (jsonBytes []byte , gwPort int ) string {
69- b64 := base64 .StdEncoding .EncodeToString (jsonBytes )
70- return strings .Join ([]string {
71- "set -e" ,
72- `mkdir -p "${HOME}/.openclaw"` ,
73- fmt .Sprintf (`echo '%s' | base64 -d > "${HOME}/.openclaw/openclaw.json"` , b64 ),
74- fmt .Sprintf ("openclaw gateway run --port %d --allow-unconfigured >>/tmp/openclaw-gateway.log 2>&1 &" , gwPort ),
75- `for i in $(seq 1 60); do` ,
76- ` curl -sf http://127.0.0.1:80/ >/dev/null 2>&1 && echo "gateway up" && break` ,
77- " sleep 1" ,
78- "done" ,
79- "tail -f /tmp/openclaw-gateway.log /dev/null" ,
80- }, "\n " )
84+ func openClawStartupScript (jsonBytes []byte , gwPort int ) (string , error ) {
85+ var buf bytes.Buffer
86+ if err := openClawStartupScriptTmpl .Execute (& buf , openClawStartupScriptData {
87+ OpenClawJSONBase64 : base64 .StdEncoding .EncodeToString (jsonBytes ),
88+ GatewayPort : gwPort ,
89+ }); err != nil {
90+ return "" , fmt .Errorf ("render openclaw startup script: %w" , err )
91+ }
92+ return strings .TrimRight (buf .String (), "\n " ), nil
8193}
0 commit comments