Make memory more resilient to failure
This commit is contained in:
committed by
Vignesh
parent
5d3af3bc62
commit
2c30ba400b
@@ -126,7 +126,7 @@ out to QMD for retrieval. Key points:
|
|||||||
- `paths[]`: add extra directories/files (`path`, optional `pattern`, optional
|
- `paths[]`: add extra directories/files (`path`, optional `pattern`, optional
|
||||||
stable `name`).
|
stable `name`).
|
||||||
- `sessions`: opt into session JSONL indexing (`enabled`, `retentionDays`,
|
- `sessions`: opt into session JSONL indexing (`enabled`, `retentionDays`,
|
||||||
`exportDir`, `redactToolOutputs`—defaults to redacting tool payloads).
|
`exportDir`).
|
||||||
- `update`: controls refresh cadence (`interval`, `debounceMs`, `onBoot`).
|
- `update`: controls refresh cadence (`interval`, `debounceMs`, `onBoot`).
|
||||||
- `limits`: clamp recall payload (`maxResults`, `maxSnippetChars`,
|
- `limits`: clamp recall payload (`maxResults`, `maxSnippetChars`,
|
||||||
`maxInjectedChars`, `timeoutMs`).
|
`maxInjectedChars`, `timeoutMs`).
|
||||||
|
|||||||
@@ -266,7 +266,6 @@ const FIELD_LABELS: Record<string, string> = {
|
|||||||
"memory.qmd.sessions.enabled": "QMD Session Indexing",
|
"memory.qmd.sessions.enabled": "QMD Session Indexing",
|
||||||
"memory.qmd.sessions.exportDir": "QMD Session Export Directory",
|
"memory.qmd.sessions.exportDir": "QMD Session Export Directory",
|
||||||
"memory.qmd.sessions.retentionDays": "QMD Session Retention (days)",
|
"memory.qmd.sessions.retentionDays": "QMD Session Retention (days)",
|
||||||
"memory.qmd.sessions.redactToolOutputs": "QMD Session Tool Redaction",
|
|
||||||
"memory.qmd.update.interval": "QMD Update Interval",
|
"memory.qmd.update.interval": "QMD Update Interval",
|
||||||
"memory.qmd.update.debounceMs": "QMD Update Debounce (ms)",
|
"memory.qmd.update.debounceMs": "QMD Update Debounce (ms)",
|
||||||
"memory.qmd.update.onBoot": "QMD Update on Startup",
|
"memory.qmd.update.onBoot": "QMD Update on Startup",
|
||||||
@@ -587,8 +586,6 @@ const FIELD_HELP: Record<string, string> = {
|
|||||||
"Override directory for sanitized session exports before indexing.",
|
"Override directory for sanitized session exports before indexing.",
|
||||||
"memory.qmd.sessions.retentionDays":
|
"memory.qmd.sessions.retentionDays":
|
||||||
"Retention window for exported sessions before pruning (default: unlimited).",
|
"Retention window for exported sessions before pruning (default: unlimited).",
|
||||||
"memory.qmd.sessions.redactToolOutputs":
|
|
||||||
"Strip tool call payloads/results when exporting sessions (default: true).",
|
|
||||||
"memory.qmd.update.interval":
|
"memory.qmd.update.interval":
|
||||||
"How often the QMD sidecar refreshes indexes (duration string, default: 5m).",
|
"How often the QMD sidecar refreshes indexes (duration string, default: 5m).",
|
||||||
"memory.qmd.update.debounceMs":
|
"memory.qmd.update.debounceMs":
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ export type MemoryQmdSessionConfig = {
|
|||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
exportDir?: string;
|
exportDir?: string;
|
||||||
retentionDays?: number;
|
retentionDays?: number;
|
||||||
redactToolOutputs?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MemoryQmdUpdateConfig = {
|
export type MemoryQmdUpdateConfig = {
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ const MemoryQmdSessionSchema = z
|
|||||||
enabled: z.boolean().optional(),
|
enabled: z.boolean().optional(),
|
||||||
exportDir: z.string().optional(),
|
exportDir: z.string().optional(),
|
||||||
retentionDays: z.number().int().nonnegative().optional(),
|
retentionDays: z.number().int().nonnegative().optional(),
|
||||||
redactToolOutputs: z.boolean().optional(),
|
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ export type ResolvedQmdSessionConfig = {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
exportDir?: string;
|
exportDir?: string;
|
||||||
retentionDays?: number;
|
retentionDays?: number;
|
||||||
redactToolOutputs: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ResolvedQmdConfig = {
|
export type ResolvedQmdConfig = {
|
||||||
@@ -147,12 +146,10 @@ function resolveSessionConfig(
|
|||||||
const exportDir = exportDirRaw ? resolvePath(exportDirRaw, workspaceDir) : undefined;
|
const exportDir = exportDirRaw ? resolvePath(exportDirRaw, workspaceDir) : undefined;
|
||||||
const retentionDays =
|
const retentionDays =
|
||||||
cfg?.retentionDays && cfg.retentionDays > 0 ? Math.floor(cfg.retentionDays) : undefined;
|
cfg?.retentionDays && cfg.retentionDays > 0 ? Math.floor(cfg.retentionDays) : undefined;
|
||||||
const redactToolOutputs = cfg?.redactToolOutputs !== false;
|
|
||||||
return {
|
return {
|
||||||
enabled,
|
enabled,
|
||||||
exportDir,
|
exportDir,
|
||||||
retentionDays,
|
retentionDays,
|
||||||
redactToolOutputs,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ export class QmdMemoryManager implements MemorySearchManager {
|
|||||||
source: doc.source,
|
source: doc.source,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return results.slice(0, limit);
|
return this.clampResultsByInjectedChars(results.slice(0, limit));
|
||||||
}
|
}
|
||||||
|
|
||||||
async sync(params?: {
|
async sync(params?: {
|
||||||
@@ -609,4 +609,24 @@ export class QmdMemoryManager implements MemorySearchManager {
|
|||||||
const next = candidate.endsWith(path.sep) ? candidate : `${candidate}${path.sep}`;
|
const next = candidate.endsWith(path.sep) ? candidate : `${candidate}${path.sep}`;
|
||||||
return next.startsWith(normalizedRoot);
|
return next.startsWith(normalizedRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private clampResultsByInjectedChars(results: MemorySearchResult[]): MemorySearchResult[] {
|
||||||
|
const budget = this.qmd.limits.maxInjectedChars;
|
||||||
|
if (!budget || budget <= 0) return results;
|
||||||
|
let remaining = budget;
|
||||||
|
const clamped: MemorySearchResult[] = [];
|
||||||
|
for (const entry of results) {
|
||||||
|
if (remaining <= 0) break;
|
||||||
|
const snippet = entry.snippet ?? "";
|
||||||
|
if (snippet.length <= remaining) {
|
||||||
|
clamped.push(entry);
|
||||||
|
remaining -= snippet.length;
|
||||||
|
} else {
|
||||||
|
const trimmed = snippet.slice(0, Math.max(0, remaining));
|
||||||
|
clamped.push({ ...entry, snippet: trimmed });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clamped;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,10 +111,12 @@ class FallbackMemoryManager implements MemorySearchManager {
|
|||||||
return this.deps.primary.status();
|
return this.deps.primary.status();
|
||||||
}
|
}
|
||||||
const fallbackStatus = this.fallback?.status();
|
const fallbackStatus = this.fallback?.status();
|
||||||
|
const fallbackInfo = { from: "qmd", reason: this.lastError ?? "unknown" };
|
||||||
if (fallbackStatus) {
|
if (fallbackStatus) {
|
||||||
const custom = fallbackStatus.custom ?? {};
|
const custom = fallbackStatus.custom ?? {};
|
||||||
return {
|
return {
|
||||||
...fallbackStatus,
|
...fallbackStatus,
|
||||||
|
fallback: fallbackInfo,
|
||||||
custom: {
|
custom: {
|
||||||
...custom,
|
...custom,
|
||||||
fallback: { disabled: true, reason: this.lastError ?? "unknown" },
|
fallback: { disabled: true, reason: this.lastError ?? "unknown" },
|
||||||
@@ -125,6 +127,7 @@ class FallbackMemoryManager implements MemorySearchManager {
|
|||||||
const custom = primaryStatus.custom ?? {};
|
const custom = primaryStatus.custom ?? {};
|
||||||
return {
|
return {
|
||||||
...primaryStatus,
|
...primaryStatus,
|
||||||
|
fallback: fallbackInfo,
|
||||||
custom: {
|
custom: {
|
||||||
...custom,
|
...custom,
|
||||||
fallback: { disabled: true, reason: this.lastError ?? "unknown" },
|
fallback: { disabled: true, reason: this.lastError ?? "unknown" },
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export type MemoryProviderStatus = {
|
|||||||
workspaceDir?: string;
|
workspaceDir?: string;
|
||||||
dbPath?: string;
|
dbPath?: string;
|
||||||
sources?: MemorySource[];
|
sources?: MemorySource[];
|
||||||
|
sourceCounts?: Array<{ source: MemorySource; files: number; chunks: number }>;
|
||||||
cache?: { enabled: boolean; entries?: number; maxEntries?: number };
|
cache?: { enabled: boolean; entries?: number; maxEntries?: number };
|
||||||
fts?: { enabled: boolean; available: boolean; error?: string };
|
fts?: { enabled: boolean; available: boolean; error?: string };
|
||||||
fallback?: { from: string; reason?: string };
|
fallback?: { from: string; reason?: string };
|
||||||
|
|||||||
Reference in New Issue
Block a user