Skip to content

fix: derive default owner from workspaceDir instead of hardcoding agent:main#1374

Open
zerone0x wants to merge 1 commit intoMemTensor:mainfrom
zerone0x:fix/memory-search-default-owner-from-workspace
Open

fix: derive default owner from workspaceDir instead of hardcoding agent:main#1374
zerone0x wants to merge 1 commit intoMemTensor:mainfrom
zerone0x:fix/memory-search-default-owner-from-workspace

Conversation

@zerone0x
Copy link
Copy Markdown
Contributor

Summary

  • Fixes the hardcoded owner="agent:main" default in memory_search, memory_get, and memory_timeline tools
  • Default owner is now derived from the workspace directory name using the convention workspace-<name>agent:<name>, with agent:main as fallback
  • Extracts shared owner resolution logic into a new resolve-owner.ts helper module

Closes #1318

Test plan

  • TypeScript compilation passes (tsc --noEmit)
  • Verify with workspace-dev directory → owner defaults to agent:dev
  • Verify with workspace-javis directory → owner defaults to agent:javis
  • Verify non-matching directory names fall back to agent:main
  • Verify explicit owner parameter still takes precedence over the default

🤖 Generated with Claude Code

…ent:main"

The memory_search, memory_get, and memory_timeline tools all hardcoded
owner="agent:main" when no explicit owner parameter was provided. This
broke multi-agent isolation since all agents would query as "agent:main"
regardless of their actual identity.

Now the default owner is derived from the workspace directory name using
the convention workspace-<name> → agent:<name>, falling back to
"agent:main" only when the directory doesn't follow that pattern. The
shared logic lives in a new resolve-owner.ts helper module.

Closes MemTensor#1318

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 27, 2026 16:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR removes the hardcoded owner="agent:main" default from the memory_search, memory_get, and memory_timeline tools by deriving the default owner from the workspace directory name (e.g., workspace-devagent:dev) and centralizing the logic in a shared helper.

Changes:

  • Added resolve-owner.ts to derive defaultOwner from workspaceDir and build the owner filter array.
  • Updated memory_search, memory_get, and memory_timeline to use the shared owner-resolution helper instead of hardcoding agent:main.
  • Wired workspaceDir into memory_get and memory_timeline tool creation via src/index.ts.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
apps/memos-local-openclaw/src/tools/resolve-owner.ts New helper for deriving defaultOwner from workspaceDir and producing owner filters.
apps/memos-local-openclaw/src/tools/memory-search.ts Switches to shared default owner + owner filter resolution.
apps/memos-local-openclaw/src/tools/memory-get.ts Accepts workspaceDir to derive default owner; uses shared owner filter logic.
apps/memos-local-openclaw/src/tools/memory-timeline.ts Accepts workspaceDir to derive default owner; uses shared owner filter logic.
apps/memos-local-openclaw/src/index.ts Passes workspaceDir into memory_get/memory_timeline tool factories.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const base = path.basename(workspaceDir);
const match = base.match(/^workspace-(.+)$/);
if (match) {
return `agent:${match[1]}`;
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

resolveDefaultOwner returns agent:${match[1]} directly from the directory name capture. If the workspace directory name has leading/trailing whitespace (or other unexpected characters), this can create an owner value that will never match DB rows. Consider trimming/sanitizing the captured agent name (and optionally constraining it to an allowed character set) before building the owner string.

Suggested change
return `agent:${match[1]}`;
const agentName = match[1].trim();
if (agentName.length > 0) {
return `agent:${agentName}`;
}

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +19
/**
* Derive the default owner from the workspace directory name.
*
* Convention: a workspace directory named "workspace-<agentName>" maps to
* "agent:<agentName>". If the directory name does not follow that pattern
* (or no workspaceDir is provided) the fallback is "agent:main".
*/
export function resolveDefaultOwner(workspaceDir?: string): string {
if (workspaceDir) {
const base = path.basename(workspaceDir);
const match = base.match(/^workspace-(.+)$/);
if (match) {
return `agent:${match[1]}`;
}
}
return "agent:main";
}
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

Owner default resolution is now central to multi-agent isolation behavior, but there are no tests covering the new workspace-<name>agent:<name> mapping (including fallback to agent:main and explicit owner precedence). Adding a small unit test for resolveDefaultOwner/resolveOwnerFilter would prevent regressions.

Copilot uses AI. Check for mistakes.
* otherwise the `defaultOwner` (derived from workspace context) is used.
*/
export function resolveOwnerFilter(owner: unknown, defaultOwner: string = "agent:main"): string[] {
const resolvedOwner = typeof owner === "string" && owner.trim().length > 0 ? owner : defaultOwner;
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

resolveOwnerFilter checks owner.trim().length > 0 but then uses the untrimmed owner value. This means inputs like "public " or "agent:dev\n" will produce an ownerFilter that won’t match stored owners (and "public " won’t be treated as the special public case). Consider normalizing to the trimmed string before comparisons/returning the filter.

Suggested change
const resolvedOwner = typeof owner === "string" && owner.trim().length > 0 ? owner : defaultOwner;
const trimmedOwner = typeof owner === "string" ? owner.trim() : "";
const resolvedOwner = trimmedOwner.length > 0 ? trimmedOwner : defaultOwner;

Copilot uses AI. Check for mistakes.
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.

memory_search tool hardcoded owner defaults to "agent:main" instead of current agent

2 participants