Skip to content

fix: resolve agent workspaces from openclaw config#261

Open
DrJsPBs wants to merge 2 commits intodaggerhashimoto:masterfrom
DrJLabs:fix/canonical-workspace-resolution
Open

fix: resolve agent workspaces from openclaw config#261
DrJsPBs wants to merge 2 commits intodaggerhashimoto:masterfrom
DrJLabs:fix/canonical-workspace-resolution

Conversation

@DrJsPBs
Copy link
Copy Markdown

@DrJsPBs DrJsPBs commented Apr 11, 2026

Summary

  • resolve non-main agent workspaces from the active OpenClaw config before falling back to workspace-<agentId>
  • use agents.defaults.workspace when choosing the workspace path for newly created root agents
  • expand file-watcher discovery to include configured agent workspaces instead of only scanning workspace-*

Problem

Closes #260.

Nerve was assuming every non-main agent lived at ~/.openclaw/workspace-<agentId>. On setups where OpenClaw stores explicit agents.list[].workspace paths, local agents were misclassified as remote/sandboxed, which disabled memory management and caused workspace watcher drift.

Verification

Targeted checks:

  • npm test -- --run server/lib/agent-workspace.test.ts server/routes/server-info.test.ts src/contexts/SessionContext.test.tsx
  • npm test -- --run server/routes/workspace.test.ts server/routes/file-browser.test.ts server/routes/skills.test.ts

Isolated contributor-style verification (clean copy of the PR branch, no copied repo .env):

  • workspace setup:
    • rsync -a --delete --exclude '.git' --exclude '.env' --exclude 'node_modules' /home/drj/nerve/ /tmp/nerve-upstream-verify/
    • ln -s /home/drj/nerve/node_modules /tmp/nerve-upstream-verify/node_modules
  • checks:
    • env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-xterm}" CI=1 npm run lint
    • env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-xterm}" CI=1 npm run build && env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-xterm}" CI=1 npm run build:server
    • env -i HOME="$HOME" PATH="$PATH" TERM="${TERM:-xterm}" CI=1 npm test
  • results:
    • npm run lint(0 errors, 6 existing warnings)
    • npm run build && npm run build:server
    • npm test
      • 122 passed (122)
      • 1639 passed (1639)

This also confirms the earlier server/lib/config.test.ts failure was local-env contamination from a repo .env, not a branch regression.

Summary by CodeRabbit

  • New Features

    • Support for centrally configured agent workspaces and use of those locations instead of defaults
    • Server exposes a default agent workspace root to clients
    • Runtime now discovers and watches configured agent workspaces (not just defaults)
  • Tests

    • Added tests verifying resolution of configured and default-derived workspaces for non-default agents

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f8db89eb-2f7e-4ec3-822e-ae08271ef05c

📥 Commits

Reviewing files that changed from the base of the PR and between 9f48e7b and 03500f8.

📒 Files selected for processing (1)
  • server/lib/file-watcher.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/lib/file-watcher.ts

📝 Walkthrough

Walkthrough

This PR adds reading of OpenClaw's openclaw.json, exposes configured/default agent workspace roots via server API, uses those values when resolving and creating non-main agent workspaces, and updates file-watcher discovery to include configured agent workspace locations. Tests added for config-driven workspace resolution.

Changes

Cohort / File(s) Summary
Config module
server/lib/openclaw-config.ts
New module that resolves, reads and caches openclaw.json, expands ~, resolves relative workspace paths, and exposes helpers: resolveOpenClawConfigPath, getConfiguredAgentWorkspace, getDefaultAgentWorkspaceRoot, buildDefaultAgentWorkspacePath, and listConfiguredAgentWorkspaces.
Agent workspace logic & tests
server/lib/agent-workspace.ts, server/lib/agent-workspace.test.ts
resolveAgentWorkspace now prefers getConfiguredAgentWorkspace(normalizedAgentId) with fallback to buildDefaultAgentWorkspacePath. Tests added to verify explicit agents.list entries and agents.defaults.workspace behavior for non-main agents.
File watcher
server/lib/file-watcher.ts
Discovery now includes workspaces returned by listConfiguredAgentWorkspaces(); root watcher watches config path when present and broadens refresh triggers to include config and workspace changes.
Server info API & tests
server/routes/server-info.ts, server/routes/server-info.test.ts
GET /api/server-info now includes defaultAgentWorkspaceRoot. Tests mock the config helper and assert the new field is returned.
Client session management & tests
src/contexts/SessionContext.tsx, src/contexts/SessionContext.test.tsx
SessionProvider adds defaultAgentWorkspaceRoot state populated from /api/server-info. Root-agent spawn uses ${defaultAgentWorkspaceRoot}/${agentId} when present (fallback to legacy path). Test verifies agents.create workspace uses server-provided default root.

Sequence Diagram

sequenceDiagram
    participant Client as Browser Client
    participant Server as Nerve Server
    participant Config as openclaw.json
    participant FileWatcher as File Watcher
    participant FS as Filesystem

    Note over Server: Startup / runtime
    Server->>Config: resolveOpenClawConfigPath() & read (cached)
    Config-->>Server: agents.list & agents.defaults
    Server->>Server: getConfiguredAgentWorkspace(agentId)
    alt configured workspace exists
        Server-->>Server: return configured workspaceRoot
    else fallback
        Server-->>Server: buildDefaultAgentWorkspacePath(agentId)
    end
    Server->>FileWatcher: listConfiguredAgentWorkspaces()
    FileWatcher->>FS: add watchers for configured workspace roots
    Note over Client,Server: API & agent creation
    Client->>Server: GET /api/server-info
    Server-->>Client: defaultAgentWorkspaceRoot
    Client->>Client: compute workspace = defaultAgentWorkspaceRoot/agentId
    Client->>Server: agents.create RPC (workspace)
    Server->>FS: resolveAgentWorkspace and probe MEMORY.md / memory/
    FS-->>Server: existence results
    Server-->>Client: agent created
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • PR #123: Modifies resolveAgentWorkspace and file-watcher discovery; closely overlaps with this PR's workspace-resolution and discovery changes.
  • PR #192: Updates root-agent spawn flow in SessionContext, overlapping client-side workspace creation logic changed here.
  • PR #111: Refactors spawnSession/root creation flow; relevant to how default workspace root is consumed when creating root agents.

Poem

🐰
A little hop to config lands,
I sniff the paths with tiny hands.
From openclaw.json I read the chart,
Workspaces found — no guesswork art.
Memory and watcher sing, hop, restart!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix: resolve agent workspaces from openclaw config' directly and specifically describes the main change in the changeset—updating how non-main agent workspaces are resolved by reading from the OpenClaw config.
Description check ✅ Passed The PR description covers all key template sections: Summary/What (three bullet points), Why/Problem (closes #260), How/Implementation (mentions new files and config-based resolution), and detailed Verification with test results, though Type of Change checkbox is not explicitly marked.
Linked Issues check ✅ Passed The PR fully addresses all coding objectives from #260: resolves agent workspaces from openclaw.json [#260], uses agents.defaults.workspace for new agents [#260], treats local workspaces as local [#260], retains legacy fallback [#260], and updates file-watcher discovery [#260].
Out of Scope Changes check ✅ Passed All changes in the PR are directly scoped to #260: new openclaw-config.ts module, updates to agent-workspace/file-watcher resolution logic, server-info endpoint changes, and SessionContext workspace computation—no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/contexts/SessionContext.tsx (1)

160-164: Store the trimmed workspace root value after validation.

Line 161 checks .trim() but Line 162 stores the original string; leading/trailing whitespace can still propagate into workspace path construction.

♻️ Suggested refinement
         setDefaultAgentWorkspaceRoot(
-          typeof data.defaultAgentWorkspaceRoot === 'string' && data.defaultAgentWorkspaceRoot.trim()
-            ? data.defaultAgentWorkspaceRoot
+          typeof data.defaultAgentWorkspaceRoot === 'string' && data.defaultAgentWorkspaceRoot.trim()
+            ? data.defaultAgentWorkspaceRoot.trim()
             : null,
         );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/contexts/SessionContext.tsx` around lines 160 - 164, The current
validation uses data.defaultAgentWorkspaceRoot.trim() to check for non-empty but
then stores the original string, which allows leading/trailing whitespace to
persist; update the setDefaultAgentWorkspaceRoot call so it stores the trimmed
value (or null) by computing a trimmed variable from
data.defaultAgentWorkspaceRoot and passing that trimmed string when non-empty,
otherwise null—refer to setDefaultAgentWorkspaceRoot and
data.defaultAgentWorkspaceRoot to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/lib/file-watcher.ts`:
- Around line 213-217: The watcher currently checks for the hardcoded string
'openclaw.json' so custom config filenames set via OPENCLAW_CONFIG_PATH won't
trigger refreshWorkspaceWatchers(); compute the actual config basename once
(e.g., const configFileName = path.basename(resolveOpenClawConfigPath())) and
update the rootDirWatcher callback condition to check file === configFileName
(and keep the existing watchingConfigFile && !file branch) so
getWatchFilename(...) comparisons correctly detect custom-config changes and
call refreshWorkspaceWatchers(); update imports/use of path.basename where
needed and keep references to watchingConfigFile, resolveOpenClawConfigPath,
getWatchFilename, refreshWorkspaceWatchers, and WORKSPACE_PREFIX.

---

Nitpick comments:
In `@src/contexts/SessionContext.tsx`:
- Around line 160-164: The current validation uses
data.defaultAgentWorkspaceRoot.trim() to check for non-empty but then stores the
original string, which allows leading/trailing whitespace to persist; update the
setDefaultAgentWorkspaceRoot call so it stores the trimmed value (or null) by
computing a trimmed variable from data.defaultAgentWorkspaceRoot and passing
that trimmed string when non-empty, otherwise null—refer to
setDefaultAgentWorkspaceRoot and data.defaultAgentWorkspaceRoot to locate the
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee09025c-3534-44bd-958a-947dda4211f0

📥 Commits

Reviewing files that changed from the base of the PR and between a5f7973 and 9f48e7b.

📒 Files selected for processing (8)
  • server/lib/agent-workspace.test.ts
  • server/lib/agent-workspace.ts
  • server/lib/file-watcher.ts
  • server/lib/openclaw-config.ts
  • server/routes/server-info.test.ts
  • server/routes/server-info.ts
  • src/contexts/SessionContext.test.tsx
  • src/contexts/SessionContext.tsx

Comment thread server/lib/file-watcher.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-main agents are marked remote when Nerve assumes workspace-<agentId> paths

1 participant