mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 01:30:21 +00:00
Merged via squash.
Prepared head SHA: 5d6d4ddfa6
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
102 lines
3.8 KiB
TypeScript
102 lines
3.8 KiB
TypeScript
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
|
import {
|
|
buildBootstrapInjectionStats,
|
|
analyzeBootstrapBudget,
|
|
} from "../agents/bootstrap-budget.js";
|
|
import { resolveBootstrapContextForRun } from "../agents/bootstrap-files.js";
|
|
import {
|
|
resolveBootstrapMaxChars,
|
|
resolveBootstrapTotalMaxChars,
|
|
} from "../agents/pi-embedded-helpers.js";
|
|
import type { OpenClawConfig } from "../config/config.js";
|
|
import { note } from "../terminal/note.js";
|
|
|
|
function formatInt(value: number): string {
|
|
return new Intl.NumberFormat("en-US").format(Math.max(0, Math.floor(value)));
|
|
}
|
|
|
|
function formatPercent(numerator: number, denominator: number): string {
|
|
if (!Number.isFinite(denominator) || denominator <= 0) {
|
|
return "0%";
|
|
}
|
|
const pct = Math.min(100, Math.max(0, Math.round((numerator / denominator) * 100)));
|
|
return `${pct}%`;
|
|
}
|
|
|
|
function formatCauses(causes: Array<"per-file-limit" | "total-limit">): string {
|
|
if (causes.length === 0) {
|
|
return "unknown";
|
|
}
|
|
return causes.map((cause) => (cause === "per-file-limit" ? "max/file" : "max/total")).join(", ");
|
|
}
|
|
|
|
export async function noteBootstrapFileSize(cfg: OpenClawConfig) {
|
|
const workspaceDir = resolveAgentWorkspaceDir(cfg, resolveDefaultAgentId(cfg));
|
|
const bootstrapMaxChars = resolveBootstrapMaxChars(cfg);
|
|
const bootstrapTotalMaxChars = resolveBootstrapTotalMaxChars(cfg);
|
|
const { bootstrapFiles, contextFiles } = await resolveBootstrapContextForRun({
|
|
workspaceDir,
|
|
config: cfg,
|
|
});
|
|
const stats = buildBootstrapInjectionStats({
|
|
bootstrapFiles,
|
|
injectedFiles: contextFiles,
|
|
});
|
|
const analysis = analyzeBootstrapBudget({
|
|
files: stats,
|
|
bootstrapMaxChars,
|
|
bootstrapTotalMaxChars,
|
|
});
|
|
if (!analysis.hasTruncation && analysis.nearLimitFiles.length === 0 && !analysis.totalNearLimit) {
|
|
return analysis;
|
|
}
|
|
|
|
const lines: string[] = [];
|
|
if (analysis.hasTruncation) {
|
|
lines.push("Workspace bootstrap files exceed limits and will be truncated:");
|
|
for (const file of analysis.truncatedFiles) {
|
|
const truncatedChars = Math.max(0, file.rawChars - file.injectedChars);
|
|
lines.push(
|
|
`- ${file.name}: ${formatInt(file.rawChars)} raw / ${formatInt(file.injectedChars)} injected (${formatPercent(truncatedChars, file.rawChars)} truncated; ${formatCauses(file.causes)})`,
|
|
);
|
|
}
|
|
} else {
|
|
lines.push("Workspace bootstrap files are near configured limits:");
|
|
}
|
|
|
|
const nonTruncatedNearLimit = analysis.nearLimitFiles.filter((file) => !file.truncated);
|
|
if (nonTruncatedNearLimit.length > 0) {
|
|
for (const file of nonTruncatedNearLimit) {
|
|
lines.push(
|
|
`- ${file.name}: ${formatInt(file.rawChars)} chars (${formatPercent(file.rawChars, bootstrapMaxChars)} of max/file ${formatInt(bootstrapMaxChars)})`,
|
|
);
|
|
}
|
|
}
|
|
|
|
lines.push(
|
|
`Total bootstrap injected chars: ${formatInt(analysis.totals.injectedChars)} (${formatPercent(analysis.totals.injectedChars, bootstrapTotalMaxChars)} of max/total ${formatInt(bootstrapTotalMaxChars)}).`,
|
|
);
|
|
lines.push(
|
|
`Total bootstrap raw chars (before truncation): ${formatInt(analysis.totals.rawChars)}.`,
|
|
);
|
|
|
|
const needsPerFileTip =
|
|
analysis.truncatedFiles.some((file) => file.causes.includes("per-file-limit")) ||
|
|
analysis.nearLimitFiles.length > 0;
|
|
const needsTotalTip =
|
|
analysis.truncatedFiles.some((file) => file.causes.includes("total-limit")) ||
|
|
analysis.totalNearLimit;
|
|
if (needsPerFileTip || needsTotalTip) {
|
|
lines.push("");
|
|
}
|
|
if (needsPerFileTip) {
|
|
lines.push("- Tip: tune `agents.defaults.bootstrapMaxChars` for per-file limits.");
|
|
}
|
|
if (needsTotalTip) {
|
|
lines.push("- Tip: tune `agents.defaults.bootstrapTotalMaxChars` for total-budget limits.");
|
|
}
|
|
|
|
note(lines.join("\n"), "Bootstrap file size");
|
|
return analysis;
|
|
}
|