Skip to content

Commit ac72618

Browse files
committed
fix(workspace): store workspace-state.json in workspace root, not .openclaw/ subdir
Moves workspace-state.json from <workspace>/.openclaw/workspace-state.json to <workspace>/workspace-state.json. This removes the requirement to create a dot-prefixed subdirectory inside the workspace, which fails on filesystems that reserve dot-prefixed paths (e.g., TigerFS FUSE mounts). Read falls back to the legacy .openclaw/ path for existing workspaces. Write always uses the new root path. Closes #44783
1 parent f9b1079 commit ac72618

1 file changed

Lines changed: 14 additions & 3 deletions

File tree

src/agents/workspace.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ async function fileExists(filePath: string): Promise<boolean> {
204204
}
205205

206206
function resolveWorkspaceStatePath(dir: string): string {
207+
return path.join(dir, WORKSPACE_STATE_FILENAME);
208+
}
209+
210+
function resolveLegacyWorkspaceStatePath(dir: string): string {
207211
return path.join(dir, WORKSPACE_STATE_DIRNAME, WORKSPACE_STATE_FILENAME);
208212
}
209213

@@ -256,8 +260,13 @@ async function readWorkspaceSetupState(statePath: string): Promise<WorkspaceSetu
256260
}
257261

258262
async function readWorkspaceSetupStateForDir(dir: string): Promise<WorkspaceSetupState> {
259-
const statePath = resolveWorkspaceStatePath(resolveUserPath(dir));
260-
return await readWorkspaceSetupState(statePath);
263+
const resolved = resolveUserPath(dir);
264+
const statePath = resolveWorkspaceStatePath(resolved);
265+
const state = await readWorkspaceSetupState(statePath);
266+
if (state.setupCompletedAt || state.bootstrapSeededAt) {
267+
return state;
268+
}
269+
return await readWorkspaceSetupState(resolveLegacyWorkspaceStatePath(resolved));
261270
}
262271

263272
export async function isWorkspaceSetupCompleted(dir: string): Promise<boolean> {
@@ -269,7 +278,6 @@ async function writeWorkspaceSetupState(
269278
statePath: string,
270279
state: WorkspaceSetupState,
271280
): Promise<void> {
272-
await fs.mkdir(path.dirname(statePath), { recursive: true });
273281
const payload = `${JSON.stringify(state, null, 2)}\n`;
274282
const tmpPath = `${statePath}.tmp-${process.pid}-${Date.now().toString(36)}`;
275283
try {
@@ -389,6 +397,9 @@ export async function ensureAgentWorkspace(params?: {
389397
await writeFileIfMissing(heartbeatPath, heartbeatTemplate);
390398

391399
let state = await readWorkspaceSetupState(statePath);
400+
if (!state.setupCompletedAt && !state.bootstrapSeededAt) {
401+
state = await readWorkspaceSetupState(resolveLegacyWorkspaceStatePath(dir));
402+
}
392403
let stateDirty = false;
393404
const markState = (next: Partial<WorkspaceSetupState>) => {
394405
state = { ...state, ...next };

0 commit comments

Comments
 (0)