Map OpenClaw owner workspaces to writable root
This commit is contained in:
parent
66c686bc43
commit
85fe904352
@ -320,6 +320,7 @@ func (o *SessionOrchestrator) runOpenClawGatewayChat(
|
||||
}
|
||||
}
|
||||
sessionKey := openClawSessionKey(params, turnID)
|
||||
params = withOpenClawWritableWorkspace(params, sessionKey)
|
||||
chatParams, rpcErr := openClawChatSendParams(params, turnID)
|
||||
if rpcErr != nil {
|
||||
return nil, rpcErr
|
||||
@ -649,6 +650,61 @@ func openClawChatSendParams(
|
||||
return chatParams, nil
|
||||
}
|
||||
|
||||
func withOpenClawWritableWorkspace(params map[string]any, sessionKey string) map[string]any {
|
||||
workingDirectory := strings.TrimSpace(shared.StringArg(params, "workingDirectory", ""))
|
||||
remoteHint := strings.TrimSpace(shared.StringArg(params, "remoteWorkingDirectoryHint", ""))
|
||||
ownerScoped := firstOwnerScopedWorkspace(workingDirectory, remoteHint)
|
||||
if ownerScoped == "" {
|
||||
return params
|
||||
}
|
||||
writable := openClawWritableWorkspaceForOwnerPath(ownerScoped, sessionKey)
|
||||
if writable == "" || writable == ownerScoped {
|
||||
return params
|
||||
}
|
||||
next := make(map[string]any, len(params)+1)
|
||||
for key, value := range params {
|
||||
next[key] = value
|
||||
}
|
||||
if workingDirectory == ownerScoped {
|
||||
next["workingDirectory"] = writable
|
||||
}
|
||||
if remoteHint == ownerScoped {
|
||||
next["remoteWorkingDirectoryHint"] = writable
|
||||
}
|
||||
for _, key := range []string{"taskPrompt", "prompt", "message"} {
|
||||
if value, ok := next[key].(string); ok && strings.Contains(value, ownerScoped) {
|
||||
next[key] = strings.ReplaceAll(value, ownerScoped, writable)
|
||||
}
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
func firstOwnerScopedWorkspace(values ...string) string {
|
||||
for _, value := range values {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if strings.HasPrefix(filepath.Clean(trimmed), "/owners/") {
|
||||
return trimmed
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func openClawWritableWorkspaceForOwnerPath(ownerPath string, sessionKey string) string {
|
||||
root := strings.TrimSpace(os.Getenv("OPENCLAW_WRITABLE_WORKSPACE_ROOT"))
|
||||
if root == "" {
|
||||
root = "/home/ubuntu/.openclaw/workspace/task_artifacts"
|
||||
}
|
||||
root = strings.TrimRight(filepath.Clean(root), string(os.PathSeparator))
|
||||
if root == "" || root == "." || root == string(os.PathSeparator) {
|
||||
return ""
|
||||
}
|
||||
leaf := safeOpenClawAttachmentPathSegment(sessionKey, "task")
|
||||
if leaf == "task" {
|
||||
leaf = safeOpenClawAttachmentPathSegment(filepath.Base(filepath.Clean(ownerPath)), "task")
|
||||
}
|
||||
return filepath.Join(root, leaf)
|
||||
}
|
||||
|
||||
func openClawNonEmptyPathAttachments(params map[string]any) []any {
|
||||
rawAttachments := shared.ListArg(params, "attachments")
|
||||
if len(rawAttachments) == 0 {
|
||||
|
||||
@ -2066,6 +2066,49 @@ func TestOpenClawChatSendParamsMaterializesInlineAttachmentsInRemoteHint(t *test
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenClawChatSendParamsMapsOwnerScopedWorkspaceToWritableRoot(t *testing.T) {
|
||||
writableRoot := t.TempDir()
|
||||
t.Setenv("OPENCLAW_WRITABLE_WORKSPACE_ROOT", writableRoot)
|
||||
ownerWorkspace := "/owners/local/device/demo/threads/draft-1"
|
||||
params := withOpenClawWritableWorkspace(map[string]any{
|
||||
"sessionId": "draft-1",
|
||||
"threadId": "draft-1",
|
||||
"taskPrompt": "write into currentTaskWorkspace: " + ownerWorkspace,
|
||||
"workingDirectory": ownerWorkspace,
|
||||
"remoteWorkingDirectoryHint": ownerWorkspace,
|
||||
"inlineAttachments": []any{
|
||||
map[string]any{
|
||||
"name": "note.txt",
|
||||
"mimeType": "text/plain",
|
||||
"content": base64.StdEncoding.EncodeToString([]byte("note body")),
|
||||
},
|
||||
},
|
||||
}, "draft-1")
|
||||
|
||||
chatParams, rpcErr := openClawChatSendParams(params, "turn-owner-workspace")
|
||||
if rpcErr != nil {
|
||||
t.Fatalf("expected chat params, got rpc error: %#v", rpcErr)
|
||||
}
|
||||
writableWorkspace := filepath.Join(writableRoot, "draft-1")
|
||||
if got := shared.StringArg(params, "workingDirectory", ""); got != writableWorkspace {
|
||||
t.Fatalf("expected writable working directory %q, got %q", writableWorkspace, got)
|
||||
}
|
||||
if got := shared.StringArg(params, "remoteWorkingDirectoryHint", ""); got != writableWorkspace {
|
||||
t.Fatalf("expected writable remote hint %q, got %q", writableWorkspace, got)
|
||||
}
|
||||
message := shared.StringArg(chatParams, "message", "")
|
||||
if strings.Contains(message, "/owners/") {
|
||||
t.Fatalf("message must not reference owner-scoped workspace, got %q", message)
|
||||
}
|
||||
if !strings.Contains(message, writableWorkspace) {
|
||||
t.Fatalf("message should reference writable workspace %q, got %q", writableWorkspace, message)
|
||||
}
|
||||
path := shared.StringArg(shared.AsMap(shared.ListArg(chatParams, "attachments")[0]), "path", "")
|
||||
if !strings.HasPrefix(path, writableWorkspace) {
|
||||
t.Fatalf("expected materialized attachment under writable workspace %q, got %q", writableWorkspace, path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteSessionTaskGatewayRejectsOversizedInlineAttachmentBeforeChatSend(t *testing.T) {
|
||||
gateway := newAcpFakeOpenClawGateway(t)
|
||||
defer gateway.Close()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user