fix: harden doctor config cleanup
This commit is contained in:
@@ -85,8 +85,9 @@ async function scanSessionFiles(agentId: string): Promise<SourceScan> {
|
|||||||
const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId);
|
const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId);
|
||||||
try {
|
try {
|
||||||
const entries = await fs.readdir(sessionsDir, { withFileTypes: true });
|
const entries = await fs.readdir(sessionsDir, { withFileTypes: true });
|
||||||
const totalFiles = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl"))
|
const totalFiles = entries.filter(
|
||||||
.length;
|
(entry) => entry.isFile() && entry.name.endsWith(".jsonl"),
|
||||||
|
).length;
|
||||||
return { source: "sessions", totalFiles, issues };
|
return { source: "sessions", totalFiles, issues };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const code = (err as NodeJS.ErrnoException).code;
|
const code = (err as NodeJS.ErrnoException).code;
|
||||||
@@ -246,7 +247,9 @@ export async function runMemoryStatus(opts: MemoryCommandOptions) {
|
|||||||
await manager.probeVectorAvailability();
|
await manager.probeVectorAvailability();
|
||||||
}
|
}
|
||||||
const status = manager.status();
|
const status = manager.status();
|
||||||
const sources = (status.sources?.length ? status.sources : ["memory"]) as MemorySourceName[];
|
const sources = (
|
||||||
|
status.sources?.length ? status.sources : ["memory"]
|
||||||
|
) as MemorySourceName[];
|
||||||
const scan = await scanMemorySources({
|
const scan = await scanMemorySources({
|
||||||
workspaceDir: status.workspaceDir,
|
workspaceDir: status.workspaceDir,
|
||||||
agentId,
|
agentId,
|
||||||
@@ -305,8 +308,9 @@ export async function runMemoryStatus(opts: MemoryCommandOptions) {
|
|||||||
if (status.sourceCounts?.length) {
|
if (status.sourceCounts?.length) {
|
||||||
lines.push(label("By source"));
|
lines.push(label("By source"));
|
||||||
for (const entry of status.sourceCounts) {
|
for (const entry of status.sourceCounts) {
|
||||||
const total = scan?.sources.find((scanEntry) => scanEntry.source === entry.source)
|
const total = scan?.sources.find(
|
||||||
?.totalFiles;
|
(scanEntry) => scanEntry.source === entry.source,
|
||||||
|
)?.totalFiles;
|
||||||
const counts =
|
const counts =
|
||||||
total === null
|
total === null
|
||||||
? `${entry.files}/? files · ${entry.chunks} chunks`
|
? `${entry.files}/? files · ${entry.chunks} chunks`
|
||||||
@@ -373,7 +377,9 @@ export async function runMemoryStatus(opts: MemoryCommandOptions) {
|
|||||||
const batchState = status.batch.enabled ? "enabled" : "disabled";
|
const batchState = status.batch.enabled ? "enabled" : "disabled";
|
||||||
const batchColor = status.batch.enabled ? theme.success : theme.warn;
|
const batchColor = status.batch.enabled ? theme.success : theme.warn;
|
||||||
const batchSuffix = ` (failures ${status.batch.failures}/${status.batch.limit})`;
|
const batchSuffix = ` (failures ${status.batch.failures}/${status.batch.limit})`;
|
||||||
lines.push(`${label("Batch")} ${colorize(rich, batchColor, batchState)}${muted(batchSuffix)}`);
|
lines.push(
|
||||||
|
`${label("Batch")} ${colorize(rich, batchColor, batchState)}${muted(batchSuffix)}`,
|
||||||
|
);
|
||||||
if (status.batch.lastError) {
|
if (status.batch.lastError) {
|
||||||
lines.push(`${label("Batch error")} ${warn(status.batch.lastError)}`);
|
lines.push(`${label("Batch error")} ${warn(status.batch.lastError)}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,13 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|||||||
|
|
||||||
type UnrecognizedKeysIssue = ZodIssue & {
|
type UnrecognizedKeysIssue = ZodIssue & {
|
||||||
code: "unrecognized_keys";
|
code: "unrecognized_keys";
|
||||||
keys: string[];
|
keys: PropertyKey[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function normalizeIssuePath(path: PropertyKey[]): Array<string | number> {
|
||||||
|
return path.filter((part): part is string | number => typeof part !== "symbol");
|
||||||
|
}
|
||||||
|
|
||||||
function isUnrecognizedKeysIssue(issue: ZodIssue): issue is UnrecognizedKeysIssue {
|
function isUnrecognizedKeysIssue(issue: ZodIssue): issue is UnrecognizedKeysIssue {
|
||||||
return issue.code === "unrecognized_keys";
|
return issue.code === "unrecognized_keys";
|
||||||
}
|
}
|
||||||
@@ -55,7 +59,10 @@ function resolvePathTarget(root: unknown, path: Array<string | number>): unknown
|
|||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripUnknownConfigKeys(config: ClawdbotConfig): { config: ClawdbotConfig; removed: string[] } {
|
function stripUnknownConfigKeys(config: ClawdbotConfig): {
|
||||||
|
config: ClawdbotConfig;
|
||||||
|
removed: string[];
|
||||||
|
} {
|
||||||
const parsed = ClawdbotSchema.safeParse(config);
|
const parsed = ClawdbotSchema.safeParse(config);
|
||||||
if (parsed.success) {
|
if (parsed.success) {
|
||||||
return { config, removed: [] };
|
return { config, removed: [] };
|
||||||
@@ -65,13 +72,15 @@ function stripUnknownConfigKeys(config: ClawdbotConfig): { config: ClawdbotConfi
|
|||||||
const removed: string[] = [];
|
const removed: string[] = [];
|
||||||
for (const issue of parsed.error.issues) {
|
for (const issue of parsed.error.issues) {
|
||||||
if (!isUnrecognizedKeysIssue(issue)) continue;
|
if (!isUnrecognizedKeysIssue(issue)) continue;
|
||||||
const target = resolvePathTarget(next, issue.path);
|
const path = normalizeIssuePath(issue.path);
|
||||||
|
const target = resolvePathTarget(next, path);
|
||||||
if (!target || typeof target !== "object" || Array.isArray(target)) continue;
|
if (!target || typeof target !== "object" || Array.isArray(target)) continue;
|
||||||
const record = target as Record<string, unknown>;
|
const record = target as Record<string, unknown>;
|
||||||
for (const key of issue.keys) {
|
for (const key of issue.keys) {
|
||||||
|
if (typeof key !== "string") continue;
|
||||||
if (!(key in record)) continue;
|
if (!(key in record)) continue;
|
||||||
delete record[key];
|
delete record[key];
|
||||||
removed.push(formatPath([...issue.path, key]));
|
removed.push(formatPath([...path, key]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1795,7 +1795,9 @@ export class MemoryIndexManager {
|
|||||||
if (!this.batch.enabled) {
|
if (!this.batch.enabled) {
|
||||||
return { disabled: true, count: this.batchFailureCount };
|
return { disabled: true, count: this.batchFailureCount };
|
||||||
}
|
}
|
||||||
const increment = params.forceDisable ? BATCH_FAILURE_LIMIT : Math.max(1, params.attempts ?? 1);
|
const increment = params.forceDisable
|
||||||
|
? BATCH_FAILURE_LIMIT
|
||||||
|
: Math.max(1, params.attempts ?? 1);
|
||||||
this.batchFailureCount += increment;
|
this.batchFailureCount += increment;
|
||||||
this.batchFailureLastError = params.message;
|
this.batchFailureLastError = params.message;
|
||||||
this.batchFailureLastProvider = params.provider;
|
this.batchFailureLastProvider = params.provider;
|
||||||
|
|||||||
Reference in New Issue
Block a user