Materialize OpenClaw attachments in remote workspace

This commit is contained in:
Haitao Pan 2026-05-26 13:42:33 +08:00
parent 22d4154597
commit 66c686bc43
2 changed files with 58 additions and 0 deletions

View File

@ -681,6 +681,7 @@ func materializeOpenClawInlineAttachments(params map[string]any, turnID string)
if workingDirectory == "" {
return nil, &shared.RPCError{Code: -32602, Message: "OPENCLAW_ATTACHMENT_WORKING_DIRECTORY_REQUIRED"}
}
workingDirectory = openClawAttachmentWorkingDirectory(params, workingDirectory)
attachmentDirectory := filepath.Join(
workingDirectory,
".xworkmate",
@ -731,6 +732,24 @@ func materializeOpenClawInlineAttachments(params map[string]any, turnID string)
return attachments, nil
}
func openClawAttachmentWorkingDirectory(params map[string]any, workingDirectory string) string {
candidate := strings.TrimSpace(workingDirectory)
remoteHint := strings.TrimSpace(shared.StringArg(params, "remoteWorkingDirectoryHint", ""))
if remoteHint == "" || remoteHint == candidate {
return candidate
}
if isDesktopLocalWorkspacePath(candidate) {
return remoteHint
}
return candidate
}
func isDesktopLocalWorkspacePath(path string) bool {
cleaned := filepath.Clean(strings.TrimSpace(path))
return strings.HasPrefix(cleaned, "/Users/") ||
strings.HasPrefix(cleaned, "/Volumes/")
}
func decodeOpenClawInlineAttachmentContent(content string) ([]byte, error) {
normalized := strings.TrimSpace(content)
if comma := strings.LastIndex(normalized, ","); comma >= 0 {

View File

@ -2027,6 +2027,45 @@ func TestOpenClawChatSendParamsMaterializesInlineAttachments(t *testing.T) {
}
}
func TestOpenClawChatSendParamsMaterializesInlineAttachmentsInRemoteHint(t *testing.T) {
remoteWorkspace := t.TempDir()
chatParams, rpcErr := openClawChatSendParams(map[string]any{
"threadId": "thread-remote-attachments",
"taskPrompt": "inspect uploaded file",
"workingDirectory": "/Users/local/.xworkmate/threads/thread-remote-attachments",
"remoteWorkingDirectoryHint": remoteWorkspace,
"inlineAttachments": []any{
map[string]any{
"name": "note.txt",
"mimeType": "text/plain",
"content": base64.StdEncoding.EncodeToString([]byte("note body")),
},
},
}, "turn-remote-attachments")
if rpcErr != nil {
t.Fatalf("expected chat params, got rpc error: %#v", rpcErr)
}
attachments := shared.ListArg(chatParams, "attachments")
if len(attachments) != 1 {
t.Fatalf("expected one materialized attachment, got %#v", attachments)
}
path := shared.StringArg(shared.AsMap(attachments[0]), "path", "")
if !strings.HasPrefix(path, remoteWorkspace) {
t.Fatalf("expected attachment under remote workspace %q, got %q", remoteWorkspace, path)
}
if strings.Contains(path, "/Users/local/") {
t.Fatalf("attachment path must not use desktop local workspace, got %q", path)
}
content, err := os.ReadFile(path)
if err != nil {
t.Fatalf("expected materialized file to exist: %v", err)
}
if string(content) != "note body" {
t.Fatalf("expected materialized content, got %q", string(content))
}
}
func TestExecuteSessionTaskGatewayRejectsOversizedInlineAttachmentBeforeChatSend(t *testing.T) {
gateway := newAcpFakeOpenClawGateway(t)
defer gateway.Close()