feat(memory): add per-agent QMD extra collections for cross-agent session search (#58211)

* feat(memory): add per-agent qmd extra collections

* test(config): cover qmd extra collections schema outputs

* docs(config): refresh qmd extra collections baseline

* docs(config): regenerate qmd extra collections baselines

* docs(config): clarify qmd extra collection naming
This commit is contained in:
Vincent Koc
2026-03-31 17:08:18 +09:00
committed by GitHub
parent 5707038e6c
commit ab4ddff7f1
14 changed files with 1319 additions and 456 deletions

View File

@@ -113,6 +113,55 @@ describe("resolveMemoryBackendConfig", () => {
expect(devNames.has("workspace-dev")).toBe(true);
});
it("merges default and per-agent qmd extra collections", () => {
const cfg = {
agents: {
defaults: {
workspace: "/workspace/root",
memorySearch: {
qmd: {
extraCollections: [
{
path: "/shared/team-notes",
name: "team-notes",
pattern: "**/*.md",
},
],
},
},
},
list: [
{
id: "main",
default: true,
workspace: "/workspace/root",
memorySearch: {
qmd: {
extraCollections: [
{
path: "notes",
name: "notes",
pattern: "**/*.md",
},
],
},
},
},
],
},
memory: {
backend: "qmd",
qmd: {
includeDefaultMemory: false,
},
},
} as OpenClawConfig;
const resolved = resolveMemoryBackendConfig({ cfg, agentId: "main" });
const names = new Set((resolved.qmd?.collections ?? []).map((collection) => collection.name));
expect(names.has("team-notes")).toBe(true);
expect(names.has("notes-main")).toBe(true);
});
it("preserves explicit custom collection names for paths outside the workspace", () => {
const cfg = {
agents: {

View File

@@ -368,9 +368,19 @@ export function resolveMemoryBackendConfig(params: {
const searchExtraPaths = dedupedExtraPaths.map(
(pathValue): { path: string; pattern?: string; name?: string } => ({ path: pathValue }),
);
const mergedExtraCollections = [
...(params.cfg.agents?.defaults?.memorySearch?.qmd?.extraCollections ?? []),
...(agentEntry?.memorySearch?.qmd?.extraCollections ?? []),
].filter((value): value is MemoryQmdIndexPath =>
Boolean(value && typeof value === "object" && typeof value.path === "string"),
);
// Combine QMD-specific paths with memorySearch extraPaths
const allQmdPaths: MemoryQmdIndexPath[] = [...(qmdCfg?.paths ?? []), ...searchExtraPaths];
// Combine QMD-specific paths with extraPaths and per-agent cross-agent collections.
const allQmdPaths: MemoryQmdIndexPath[] = [
...(qmdCfg?.paths ?? []),
...searchExtraPaths,
...mergedExtraCollections,
];
const collections = [
...resolveDefaultCollections(includeDefaultMemory, workspaceDir, nameSet, normalizedAgentId),