
























@@ -20,6 +20,10 @@ import {
2020import { isPathInside } from "./fs-utils.js";
2121import { normalizeLowercaseStringOrEmpty } from "./string-utils.js";
222223+function escapeQmdExactFilePattern(fileName: string): string {
24+return fileName.replace(/[\\*?[\]{}()!+@]/g, "\\$&");
25+}
26+2327export type ResolvedMemoryBackendConfig = {
2428backend: MemoryBackend;
2529citations: MemoryCitationsMode;
@@ -291,26 +295,40 @@ function resolveCustomPaths(
291295return;
292296}
293297let resolved: string;
298+let collectionPath: string;
294299try {
295300resolved = resolvePath(trimmedPath, workspaceDir);
296301} catch {
297302return;
298303}
299-const pattern = entry.pattern?.trim() || "**/*.md";
300-const dedupeKey = `${resolved}\u0000${pattern}`;
304+collectionPath = resolved;
305+let pattern = entry.pattern?.trim() || "**/*.md";
306+try {
307+const stat = fs.statSync(resolved);
308+if (stat.isFile()) {
309+// When the configured path points directly to a file, normalize into a
310+// parent-directory collection with an exact-filename pattern, regardless
311+// of any user-supplied glob (a glob does not apply to a single file).
312+collectionPath = path.dirname(resolved);
313+pattern = escapeQmdExactFilePattern(path.basename(resolved));
314+}
315+} catch {
316+// not a file or can't stat, use as-is
317+}
318+const dedupeKey = `${collectionPath}\u0000${pattern}`;
301319if (seenRoots.has(dedupeKey)) {
302320return;
303321}
304322seenRoots.add(dedupeKey);
305323const explicitName = entry.name?.trim();
306324const baseName =
307-explicitName && !isPathInsideRoot(resolved, workspaceDir)
325+explicitName && !isPathInsideRoot(collectionPath, workspaceDir)
308326 ? explicitName
309327 : scopeCollectionBase(explicitName || `custom-${index + 1}`, agentId);
310328const name = ensureUniqueName(baseName, existing);
311329collections.push({
312330 name,
313-path: resolved,
331+path: collectionPath,
314332 pattern,
315333kind: "custom",
316334});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。