fix openclaw artifact workspace resolution
This commit is contained in:
parent
9180e9258d
commit
9de1e70687
@ -323,11 +323,7 @@ func (o *SessionOrchestrator) startOpenClawGatewayTask(
|
||||
}
|
||||
sessionKey := o.openClawSessionKey(params, turnID)
|
||||
params = withOpenClawWritableWorkspace(params, openClawAppThreadKey(params))
|
||||
chatParams, rpcErr := openClawChatSendParamsWithSessionKey(params, turnID, sessionKey)
|
||||
if rpcErr != nil {
|
||||
return nil, rpcErr
|
||||
}
|
||||
artifactContract := openClawArtifactContractForParams(params, chatParams)
|
||||
artifactContract := openClawArtifactContractForParams(params, nil)
|
||||
preparedArtifact, prepareErr := o.openClawArtifactPrepare(
|
||||
gatewayProvider,
|
||||
params,
|
||||
@ -340,6 +336,11 @@ func (o *SessionOrchestrator) startOpenClawGatewayTask(
|
||||
return nil, prepareErr
|
||||
}
|
||||
logOpenClawArtifactSync(gatewayProvider, sessionKey, turnID, "prepare", true, false, false)
|
||||
params = withOpenClawPreparedArtifactWorkspace(params, preparedArtifact)
|
||||
chatParams, rpcErr := openClawChatSendParamsWithSessionKey(params, turnID, sessionKey)
|
||||
if rpcErr != nil {
|
||||
return nil, rpcErr
|
||||
}
|
||||
applyOpenClawPreparedArtifactToChatParams(chatParams, preparedArtifact, sessionKey, turnID, artifactContract)
|
||||
sendStarted := time.Now()
|
||||
sendResult := o.openClawGatewayRequestWithRetry(
|
||||
@ -623,14 +624,14 @@ func openClawSessionPrepareParams(params map[string]any, openClawSessionKey stri
|
||||
}
|
||||
|
||||
func openClawArtifactWorkspaceDir(params map[string]any) string {
|
||||
for _, key := range []string{"workspaceDir", "remoteWorkingDirectoryHint", "remoteWorkingDirectory"} {
|
||||
if value := strings.TrimSpace(shared.StringArg(params, key, "")); value != "" {
|
||||
if value := strings.TrimSpace(shared.StringArg(params, "workspaceDir", "")); value != "" {
|
||||
return value
|
||||
}
|
||||
for _, key := range []string{"remoteWorkingDirectoryHint", "remoteWorkingDirectory", "workingDirectory"} {
|
||||
if value := strings.TrimSpace(shared.StringArg(params, key, "")); isOpenClawWorkspacePath(value) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
if workingDirectory := strings.TrimSpace(shared.StringArg(params, "workingDirectory", "")); isOpenClawWorkspacePath(workingDirectory) {
|
||||
return workingDirectory
|
||||
}
|
||||
if configured := strings.TrimSpace(os.Getenv("OPENCLAW_WORKSPACE_DIR")); configured != "" {
|
||||
return configured
|
||||
}
|
||||
@ -880,6 +881,66 @@ func withOpenClawWritableWorkspace(params map[string]any, appThreadKey string) m
|
||||
return next
|
||||
}
|
||||
|
||||
func withOpenClawPreparedArtifactWorkspace(params map[string]any, prepared *openClawPreparedArtifactScope) map[string]any {
|
||||
if prepared == nil {
|
||||
return params
|
||||
}
|
||||
artifactDirectory := strings.TrimSpace(prepared.ArtifactDirectory)
|
||||
if artifactDirectory == "" {
|
||||
return params
|
||||
}
|
||||
replacements := openClawWorkspacePromptReplacementValues(params)
|
||||
next := make(map[string]any, len(params)+2)
|
||||
for key, value := range params {
|
||||
next[key] = value
|
||||
}
|
||||
next["workingDirectory"] = artifactDirectory
|
||||
next["remoteWorkingDirectoryHint"] = artifactDirectory
|
||||
for _, key := range []string{"taskPrompt", "prompt", "message"} {
|
||||
value, ok := next[key].(string)
|
||||
if !ok || strings.TrimSpace(value) == "" {
|
||||
continue
|
||||
}
|
||||
next[key] = rewriteOpenClawWorkspaceReferences(value, artifactDirectory, replacements)
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
func openClawWorkspacePromptReplacementValues(params map[string]any) []string {
|
||||
values := []string{
|
||||
shared.StringArg(params, "workingDirectory", ""),
|
||||
shared.StringArg(params, "remoteWorkingDirectoryHint", ""),
|
||||
shared.StringArg(params, "remoteWorkingDirectory", ""),
|
||||
}
|
||||
metadata := shared.AsMap(params["metadata"])
|
||||
contract := shared.AsMap(metadata["xworkmateTaskArtifactContract"])
|
||||
values = append(values,
|
||||
shared.StringArg(contract, "currentTaskWorkspace", ""),
|
||||
shared.StringArg(contract, "remoteWorkspaceHint", ""),
|
||||
)
|
||||
result := make([]string, 0, len(values))
|
||||
seen := map[string]bool{}
|
||||
for _, value := range values {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if trimmed == "" || seen[trimmed] {
|
||||
continue
|
||||
}
|
||||
seen[trimmed] = true
|
||||
result = append(result, trimmed)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func rewriteOpenClawWorkspaceReferences(message string, artifactDirectory string, replacements []string) string {
|
||||
result := message
|
||||
for _, value := range replacements {
|
||||
if value != artifactDirectory {
|
||||
result = strings.ReplaceAll(result, value, artifactDirectory)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func firstOwnerScopedWorkspace(values ...string) string {
|
||||
for _, value := range values {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
@ -893,7 +954,7 @@ func firstOwnerScopedWorkspace(values ...string) string {
|
||||
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"
|
||||
return ""
|
||||
}
|
||||
root = strings.TrimRight(filepath.Clean(root), string(os.PathSeparator))
|
||||
if root == "" || root == "." || root == string(os.PathSeparator) {
|
||||
|
||||
@ -2417,8 +2417,79 @@ func TestOpenClawChatSendParamsMapsOwnerScopedWorkspaceToWritableRoot(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenClawWritableWorkspaceDoesNotDefaultToLegacyTaskArtifacts(t *testing.T) {
|
||||
t.Setenv("OPENCLAW_WRITABLE_WORKSPACE_ROOT", "")
|
||||
|
||||
params := withOpenClawWritableWorkspace(map[string]any{
|
||||
"sessionId": "draft-1",
|
||||
"threadId": "draft-1",
|
||||
"taskPrompt": "write into /owners/local/device/demo/threads/draft-1",
|
||||
"workingDirectory": "/owners/local/device/demo/threads/draft-1",
|
||||
"remoteWorkingDirectoryHint": "/owners/local/device/demo/threads/draft-1",
|
||||
}, "draft-1")
|
||||
|
||||
if got := shared.StringArg(params, "workingDirectory", ""); strings.Contains(got, "task_artifacts") {
|
||||
t.Fatalf("must not synthesize legacy task_artifacts workspace, got %q", got)
|
||||
}
|
||||
if got := shared.StringArg(params, "remoteWorkingDirectoryHint", ""); strings.Contains(got, "task_artifacts") {
|
||||
t.Fatalf("must not synthesize legacy task_artifacts remote hint, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenClawArtifactWorkspaceDirIgnoresOwnerScopedRemoteHint(t *testing.T) {
|
||||
t.Setenv("OPENCLAW_WORKSPACE_DIR", "")
|
||||
|
||||
got := openClawArtifactWorkspaceDir(map[string]any{
|
||||
"workingDirectory": "/owners/local/device/demo/threads/draft-1",
|
||||
"remoteWorkingDirectoryHint": "/owners/local/device/demo/threads/draft-1",
|
||||
})
|
||||
|
||||
if got != "~/.openclaw/workspace" {
|
||||
t.Fatalf("expected default OpenClaw workspace root, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenClawPreparedArtifactWorkspaceRewritesOwnerPromptToArtifactDirectory(t *testing.T) {
|
||||
ownerWorkspace := "/owners/local/device/demo/threads/draft-1"
|
||||
artifactDirectory := "/home/ubuntu/.openclaw/workspace/tasks/agent-main-draft-1/turn-1"
|
||||
|
||||
params := withOpenClawPreparedArtifactWorkspace(map[string]any{
|
||||
"taskPrompt": "" +
|
||||
"TaskThread workspace context:\n" +
|
||||
"- remoteWorkspaceHint: " + ownerWorkspace + "\n" +
|
||||
"- currentTaskWorkspace: " + ownerWorkspace + "\n" +
|
||||
"User request:\nwrite a report",
|
||||
"workingDirectory": ownerWorkspace,
|
||||
"remoteWorkingDirectoryHint": ownerWorkspace,
|
||||
"metadata": map[string]any{
|
||||
"xworkmateTaskArtifactContract": map[string]any{
|
||||
"currentTaskWorkspace": ownerWorkspace,
|
||||
"remoteWorkspaceHint": ownerWorkspace,
|
||||
},
|
||||
},
|
||||
}, &openClawPreparedArtifactScope{
|
||||
ArtifactDirectory: artifactDirectory,
|
||||
ArtifactScope: "tasks/agent-main-draft-1/turn-1",
|
||||
})
|
||||
|
||||
if got := shared.StringArg(params, "workingDirectory", ""); got != artifactDirectory {
|
||||
t.Fatalf("expected workingDirectory rewritten to artifact directory, got %q", got)
|
||||
}
|
||||
if got := shared.StringArg(params, "remoteWorkingDirectoryHint", ""); got != artifactDirectory {
|
||||
t.Fatalf("expected remote hint rewritten to artifact directory, got %q", got)
|
||||
}
|
||||
message := shared.StringArg(params, "taskPrompt", "")
|
||||
if strings.Contains(message, ownerWorkspace) {
|
||||
t.Fatalf("prompt must not keep owner-scoped workspace, got %q", message)
|
||||
}
|
||||
if count := strings.Count(message, artifactDirectory); count != 2 {
|
||||
t.Fatalf("expected artifact directory to replace both workspace prompt references, count=%d message=%q", count, message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteSessionTaskGatewayRejectsOversizedInlineAttachmentBeforeChatSend(t *testing.T) {
|
||||
gateway := newAcpFakeOpenClawGateway(t)
|
||||
gateway.artifactWorkspaceRoot = t.TempDir()
|
||||
defer gateway.Close()
|
||||
|
||||
t.Setenv("GATEWAY_RPC_URL", gateway.URL())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user