agents: reduce prompt token bloat from exec and context (#16539)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 8e1635fa3fdfb199a58bd53e816abc41cd400d44
Co-authored-by: CharlieGreenman <8540141+CharlieGreenman@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Charlie Greenman
2026-02-14 18:32:45 -05:00
committed by GitHub
parent 2547514b47
commit dec6859702
23 changed files with 403 additions and 39 deletions

View File

@@ -84,13 +84,14 @@ export const DEFAULT_MAX_OUTPUT = clampWithDefault(
);
export const DEFAULT_PENDING_MAX_OUTPUT = clampWithDefault(
readEnvInt("OPENCLAW_BASH_PENDING_MAX_OUTPUT_CHARS"),
200_000,
30_000,
1_000,
200_000,
);
export const DEFAULT_PATH =
process.env.PATH ?? "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
export const DEFAULT_NOTIFY_TAIL_CHARS = 400;
const DEFAULT_NOTIFY_SNIPPET_CHARS = 180;
export const DEFAULT_APPROVAL_TIMEOUT_MS = 120_000;
export const DEFAULT_APPROVAL_REQUEST_TIMEOUT_MS = 130_000;
const DEFAULT_APPROVAL_RUNNING_NOTICE_MS = 10_000;
@@ -214,6 +215,18 @@ export function normalizeNotifyOutput(value: string) {
return value.replace(/\s+/g, " ").trim();
}
function compactNotifyOutput(value: string, maxChars = DEFAULT_NOTIFY_SNIPPET_CHARS) {
const normalized = normalizeNotifyOutput(value);
if (!normalized) {
return "";
}
if (normalized.length <= maxChars) {
return normalized;
}
const safe = Math.max(1, maxChars - 1);
return `${normalized.slice(0, safe)}`;
}
export function normalizePathPrepend(entries?: string[]) {
if (!Array.isArray(entries)) {
return [];
@@ -300,9 +313,12 @@ function maybeNotifyOnExit(session: ProcessSession, status: "completed" | "faile
const exitLabel = session.exitSignal
? `signal ${session.exitSignal}`
: `code ${session.exitCode ?? 0}`;
const output = normalizeNotifyOutput(
const output = compactNotifyOutput(
tail(session.tail || session.aggregated || "", DEFAULT_NOTIFY_TAIL_CHARS),
);
if (status === "completed" && !output && session.notifyOnExitEmptySuccess !== true) {
return;
}
const summary = output
? `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel}) :: ${output}`
: `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel})`;
@@ -350,6 +366,7 @@ export async function runExecProcess(opts: {
maxOutput: number;
pendingMaxOutput: number;
notifyOnExit: boolean;
notifyOnExitEmptySuccess?: boolean;
scopeKey?: string;
sessionKey?: string;
timeoutSec: number;
@@ -515,6 +532,7 @@ export async function runExecProcess(opts: {
scopeKey: opts.scopeKey,
sessionKey: opts.sessionKey,
notifyOnExit: opts.notifyOnExit,
notifyOnExitEmptySuccess: opts.notifyOnExitEmptySuccess === true,
exitNotified: false,
child: child ?? undefined,
stdin,