perf: improve batch status logging
This commit is contained in:
@@ -19,6 +19,7 @@ Docs: https://docs.clawd.bot
|
|||||||
- Memory: add hybrid BM25 + vector search (FTS5) with weighted merging and fallback.
|
- Memory: add hybrid BM25 + vector search (FTS5) with weighted merging and fallback.
|
||||||
- Memory: add SQLite embedding cache to speed up reindexing and frequent updates.
|
- Memory: add SQLite embedding cache to speed up reindexing and frequent updates.
|
||||||
- CLI: surface FTS + embedding cache state in `clawdbot memory status`.
|
- CLI: surface FTS + embedding cache state in `clawdbot memory status`.
|
||||||
|
- Memory: render progress immediately, color batch statuses in verbose logs, and poll OpenAI batch status every 2s by default.
|
||||||
- Plugins: allow optional agent tools with explicit allowlists and add plugin tool authoring guide. https://docs.clawd.bot/plugins/agent-tools
|
- Plugins: allow optional agent tools with explicit allowlists and add plugin tool authoring guide. https://docs.clawd.bot/plugins/agent-tools
|
||||||
- Tools: centralize plugin tool policy helpers.
|
- Tools: centralize plugin tool policy helpers.
|
||||||
- Docs: clarify plugin agent tool configuration. https://docs.clawd.bot/plugins/agent-tools
|
- Docs: clarify plugin agent tool configuration. https://docs.clawd.bot/plugins/agent-tools
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ describe("memory search config", () => {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
wait: true,
|
wait: true,
|
||||||
concurrency: 2,
|
concurrency: 2,
|
||||||
pollIntervalMs: 500,
|
pollIntervalMs: 2000,
|
||||||
timeoutMinutes: 60,
|
timeoutMinutes: 60,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -135,7 +135,7 @@ describe("memory search config", () => {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
wait: true,
|
wait: true,
|
||||||
concurrency: 2,
|
concurrency: 2,
|
||||||
pollIntervalMs: 500,
|
pollIntervalMs: 2000,
|
||||||
timeoutMinutes: 60,
|
timeoutMinutes: 60,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ function mergeConfig(
|
|||||||
overrides?.remote?.batch?.concurrency ?? defaults?.remote?.batch?.concurrency ?? 2,
|
overrides?.remote?.batch?.concurrency ?? defaults?.remote?.batch?.concurrency ?? 2,
|
||||||
),
|
),
|
||||||
pollIntervalMs:
|
pollIntervalMs:
|
||||||
overrides?.remote?.batch?.pollIntervalMs ?? defaults?.remote?.batch?.pollIntervalMs ?? 500,
|
overrides?.remote?.batch?.pollIntervalMs ?? defaults?.remote?.batch?.pollIntervalMs ?? 2000,
|
||||||
timeoutMinutes:
|
timeoutMinutes:
|
||||||
overrides?.remote?.batch?.timeoutMinutes ?? defaults?.remote?.batch?.timeoutMinutes ?? 60,
|
overrides?.remote?.batch?.timeoutMinutes ?? defaults?.remote?.batch?.timeoutMinutes ?? 60,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ const FIELD_HELP: Record<string, string> = {
|
|||||||
"agents.defaults.memorySearch.remote.batch.concurrency":
|
"agents.defaults.memorySearch.remote.batch.concurrency":
|
||||||
"Max concurrent OpenAI batch jobs for memory indexing (default: 2).",
|
"Max concurrent OpenAI batch jobs for memory indexing (default: 2).",
|
||||||
"agents.defaults.memorySearch.remote.batch.pollIntervalMs":
|
"agents.defaults.memorySearch.remote.batch.pollIntervalMs":
|
||||||
"Polling interval in ms for OpenAI batch status (default: 500).",
|
"Polling interval in ms for OpenAI batch status (default: 2000).",
|
||||||
"agents.defaults.memorySearch.remote.batch.timeoutMinutes":
|
"agents.defaults.memorySearch.remote.batch.timeoutMinutes":
|
||||||
"Timeout in minutes for OpenAI batch indexing (default: 60).",
|
"Timeout in minutes for OpenAI batch indexing (default: 60).",
|
||||||
"agents.defaults.memorySearch.local.modelPath":
|
"agents.defaults.memorySearch.local.modelPath":
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { resolveSessionTranscriptsDirForAgent } from "../config/sessions/paths.j
|
|||||||
import { createSubsystemLogger } from "../logging.js";
|
import { createSubsystemLogger } from "../logging.js";
|
||||||
import { onSessionTranscriptUpdate } from "../sessions/transcript-events.js";
|
import { onSessionTranscriptUpdate } from "../sessions/transcript-events.js";
|
||||||
import { resolveUserPath, truncateUtf16Safe } from "../utils.js";
|
import { resolveUserPath, truncateUtf16Safe } from "../utils.js";
|
||||||
|
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||||
import {
|
import {
|
||||||
createEmbeddingProvider,
|
createEmbeddingProvider,
|
||||||
type EmbeddingProvider,
|
type EmbeddingProvider,
|
||||||
@@ -252,7 +253,7 @@ export class MemoryIndexManager {
|
|||||||
enabled: Boolean(batch?.enabled && this.openAi && this.provider.id === "openai"),
|
enabled: Boolean(batch?.enabled && this.openAi && this.provider.id === "openai"),
|
||||||
wait: batch?.wait ?? true,
|
wait: batch?.wait ?? true,
|
||||||
concurrency: Math.max(1, batch?.concurrency ?? 2),
|
concurrency: Math.max(1, batch?.concurrency ?? 2),
|
||||||
pollIntervalMs: batch?.pollIntervalMs ?? 500,
|
pollIntervalMs: batch?.pollIntervalMs ?? 2000,
|
||||||
timeoutMs: (batch?.timeoutMinutes ?? 60) * 60 * 1000,
|
timeoutMs: (batch?.timeoutMinutes ?? 60) * 60 * 1000,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1647,6 +1648,9 @@ export class MemoryIndexManager {
|
|||||||
const status = current ?? (await this.fetchOpenAiBatchStatus(batchId));
|
const status = current ?? (await this.fetchOpenAiBatchStatus(batchId));
|
||||||
const state = status.status ?? "unknown";
|
const state = status.status ?? "unknown";
|
||||||
if (state === "completed") {
|
if (state === "completed") {
|
||||||
|
log.debug(`openai batch ${batchId} ${state}`, {
|
||||||
|
consoleMessage: this.formatOpenAiBatchConsoleMessage({ batchId, state }),
|
||||||
|
});
|
||||||
if (!status.output_file_id) {
|
if (!status.output_file_id) {
|
||||||
throw new Error(`openai batch ${batchId} completed without output file`);
|
throw new Error(`openai batch ${batchId} completed without output file`);
|
||||||
}
|
}
|
||||||
@@ -1668,12 +1672,37 @@ export class MemoryIndexManager {
|
|||||||
if (Date.now() - start > this.batch.timeoutMs) {
|
if (Date.now() - start > this.batch.timeoutMs) {
|
||||||
throw new Error(`openai batch ${batchId} timed out after ${this.batch.timeoutMs}ms`);
|
throw new Error(`openai batch ${batchId} timed out after ${this.batch.timeoutMs}ms`);
|
||||||
}
|
}
|
||||||
log.debug(`openai batch ${batchId} ${state}; waiting ${this.batch.pollIntervalMs}ms`);
|
log.debug(`openai batch ${batchId} ${state}; waiting ${this.batch.pollIntervalMs}ms`, {
|
||||||
|
consoleMessage: this.formatOpenAiBatchConsoleMessage({
|
||||||
|
batchId,
|
||||||
|
state,
|
||||||
|
waitMs: this.batch.pollIntervalMs,
|
||||||
|
}),
|
||||||
|
});
|
||||||
await new Promise((resolve) => setTimeout(resolve, this.batch.pollIntervalMs));
|
await new Promise((resolve) => setTimeout(resolve, this.batch.pollIntervalMs));
|
||||||
current = undefined;
|
current = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private formatOpenAiBatchConsoleMessage(params: {
|
||||||
|
batchId: string;
|
||||||
|
state: string;
|
||||||
|
waitMs?: number;
|
||||||
|
}): string {
|
||||||
|
const rich = isRich();
|
||||||
|
const normalized = params.state.toLowerCase();
|
||||||
|
const successStates = new Set(["completed", "succeeded"]);
|
||||||
|
const errorStates = new Set(["failed", "expired", "cancelled", "canceled"]);
|
||||||
|
const warnStates = new Set(["finalizing", "validating"]);
|
||||||
|
let color = theme.info;
|
||||||
|
if (successStates.has(normalized)) color = theme.success;
|
||||||
|
else if (errorStates.has(normalized)) color = theme.error;
|
||||||
|
else if (warnStates.has(normalized)) color = theme.warn;
|
||||||
|
const status = colorize(rich, color, params.state);
|
||||||
|
const suffix = typeof params.waitMs === "number" ? `; waiting ${params.waitMs}ms` : "";
|
||||||
|
return `openai batch ${params.batchId} ${status}${suffix}`;
|
||||||
|
}
|
||||||
|
|
||||||
private async embedChunksWithBatch(
|
private async embedChunksWithBatch(
|
||||||
chunks: MemoryChunk[],
|
chunks: MemoryChunk[],
|
||||||
entry: MemoryFileEntry | SessionFileEntry,
|
entry: MemoryFileEntry | SessionFileEntry,
|
||||||
|
|||||||
Reference in New Issue
Block a user