mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 15:30:39 +00:00
refactor(agents): share log windowing and UTF-16 budget clamping
This commit is contained in:
@@ -32,6 +32,24 @@ type WritableStdin = {
|
||||
};
|
||||
const DEFAULT_LOG_TAIL_LINES = 200;
|
||||
|
||||
function resolveLogSliceWindow(offset?: number, limit?: number) {
|
||||
const usingDefaultTail = offset === undefined && limit === undefined;
|
||||
const effectiveLimit =
|
||||
typeof limit === "number" && Number.isFinite(limit)
|
||||
? limit
|
||||
: usingDefaultTail
|
||||
? DEFAULT_LOG_TAIL_LINES
|
||||
: undefined;
|
||||
return { effectiveOffset: offset, effectiveLimit, usingDefaultTail };
|
||||
}
|
||||
|
||||
function defaultTailNote(totalLines: number, usingDefaultTail: boolean) {
|
||||
if (!usingDefaultTail || totalLines <= DEFAULT_LOG_TAIL_LINES) {
|
||||
return "";
|
||||
}
|
||||
return `\n\n[showing last ${DEFAULT_LOG_TAIL_LINES} of ${totalLines} lines; pass offset/limit to page]`;
|
||||
}
|
||||
|
||||
const processSchema = Type.Object({
|
||||
action: Type.String({ description: "Process action" }),
|
||||
sessionId: Type.Optional(Type.String({ description: "Session id for actions other than list" })),
|
||||
@@ -295,25 +313,15 @@ export function createProcessTool(
|
||||
details: { status: "failed" },
|
||||
};
|
||||
}
|
||||
const effectiveOffset = params.offset;
|
||||
const usingDefaultTail = params.offset === undefined && params.limit === undefined;
|
||||
const effectiveLimit =
|
||||
typeof params.limit === "number" && Number.isFinite(params.limit)
|
||||
? params.limit
|
||||
: usingDefaultTail
|
||||
? DEFAULT_LOG_TAIL_LINES
|
||||
: undefined;
|
||||
const window = resolveLogSliceWindow(params.offset, params.limit);
|
||||
const { slice, totalLines, totalChars } = sliceLogLines(
|
||||
scopedSession.aggregated,
|
||||
effectiveOffset,
|
||||
effectiveLimit,
|
||||
window.effectiveOffset,
|
||||
window.effectiveLimit,
|
||||
);
|
||||
const defaultTailNote =
|
||||
usingDefaultTail && totalLines > DEFAULT_LOG_TAIL_LINES
|
||||
? `\n\n[showing last ${DEFAULT_LOG_TAIL_LINES} of ${totalLines} lines; pass offset/limit to page]`
|
||||
: "";
|
||||
const logDefaultTailNote = defaultTailNote(totalLines, window.usingDefaultTail);
|
||||
return {
|
||||
content: [{ type: "text", text: (slice || "(no output yet)") + defaultTailNote }],
|
||||
content: [{ type: "text", text: (slice || "(no output yet)") + logDefaultTailNote }],
|
||||
details: {
|
||||
status: scopedSession.exited ? "completed" : "running",
|
||||
sessionId: params.sessionId,
|
||||
@@ -326,27 +334,17 @@ export function createProcessTool(
|
||||
};
|
||||
}
|
||||
if (scopedFinished) {
|
||||
const effectiveOffset = params.offset;
|
||||
const usingDefaultTail = params.offset === undefined && params.limit === undefined;
|
||||
const effectiveLimit =
|
||||
typeof params.limit === "number" && Number.isFinite(params.limit)
|
||||
? params.limit
|
||||
: usingDefaultTail
|
||||
? DEFAULT_LOG_TAIL_LINES
|
||||
: undefined;
|
||||
const window = resolveLogSliceWindow(params.offset, params.limit);
|
||||
const { slice, totalLines, totalChars } = sliceLogLines(
|
||||
scopedFinished.aggregated,
|
||||
effectiveOffset,
|
||||
effectiveLimit,
|
||||
window.effectiveOffset,
|
||||
window.effectiveLimit,
|
||||
);
|
||||
const status = scopedFinished.status === "completed" ? "completed" : "failed";
|
||||
const defaultTailNote =
|
||||
usingDefaultTail && totalLines > DEFAULT_LOG_TAIL_LINES
|
||||
? `\n\n[showing last ${DEFAULT_LOG_TAIL_LINES} of ${totalLines} lines; pass offset/limit to page]`
|
||||
: "";
|
||||
const logDefaultTailNote = defaultTailNote(totalLines, window.usingDefaultTail);
|
||||
return {
|
||||
content: [
|
||||
{ type: "text", text: (slice || "(no output recorded)") + defaultTailNote },
|
||||
{ type: "text", text: (slice || "(no output recorded)") + logDefaultTailNote },
|
||||
],
|
||||
details: {
|
||||
status,
|
||||
|
||||
@@ -4,6 +4,7 @@ import path from "node:path";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { WorkspaceBootstrapFile } from "../workspace.js";
|
||||
import type { EmbeddedContextFile } from "./types.js";
|
||||
import { truncateUtf16Safe } from "../../utils.js";
|
||||
|
||||
type ContentBlockWithSignature = {
|
||||
thought_signature?: unknown;
|
||||
@@ -153,10 +154,10 @@ function clampToBudget(content: string, budget: number): string {
|
||||
return content;
|
||||
}
|
||||
if (budget <= 3) {
|
||||
return content.slice(0, budget);
|
||||
return truncateUtf16Safe(content, budget);
|
||||
}
|
||||
const safe = Math.max(1, budget - 1);
|
||||
return `${content.slice(0, safe)}…`;
|
||||
return `${truncateUtf16Safe(content, safe)}…`;
|
||||
}
|
||||
|
||||
export async function ensureSessionHeader(params: {
|
||||
|
||||
Reference in New Issue
Block a user