mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 21:09:34 +00:00
agents: reduce prompt token bloat from exec and context (#16539)
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: 8e1635fa3f
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:
@@ -221,6 +221,28 @@ describe("exec tool backgrounding", () => {
|
||||
expect(status).toBe("completed");
|
||||
});
|
||||
|
||||
it("defaults process log to a bounded tail when no window is provided", async () => {
|
||||
const lines = Array.from({ length: 260 }, (_value, index) => `line-${index + 1}`);
|
||||
const result = await execTool.execute("call1", {
|
||||
command: echoLines(lines),
|
||||
background: true,
|
||||
});
|
||||
const sessionId = (result.details as { sessionId: string }).sessionId;
|
||||
await waitForCompletion(sessionId);
|
||||
|
||||
const log = await processTool.execute("call2", {
|
||||
action: "log",
|
||||
sessionId,
|
||||
});
|
||||
const textBlock = log.content.find((c) => c.type === "text")?.text ?? "";
|
||||
const firstLine = textBlock.split("\n")[0]?.trim();
|
||||
expect(textBlock).toContain("showing last 200 of 260 lines");
|
||||
expect(firstLine).toBe("line-61");
|
||||
expect(textBlock).toContain("line-61");
|
||||
expect(textBlock).toContain("line-260");
|
||||
expect((log.details as { totalLines?: number }).totalLines).toBe(260);
|
||||
});
|
||||
|
||||
it("supports line offsets for log slices", async () => {
|
||||
const result = await execTool.execute("call1", {
|
||||
command: echoLines(["alpha", "beta", "gamma"]),
|
||||
@@ -239,6 +261,29 @@ describe("exec tool backgrounding", () => {
|
||||
expect(normalizeText(textBlock?.text)).toBe("beta");
|
||||
});
|
||||
|
||||
it("keeps offset-only log requests unbounded by default tail mode", async () => {
|
||||
const lines = Array.from({ length: 260 }, (_value, index) => `line-${index + 1}`);
|
||||
const result = await execTool.execute("call1", {
|
||||
command: echoLines(lines),
|
||||
background: true,
|
||||
});
|
||||
const sessionId = (result.details as { sessionId: string }).sessionId;
|
||||
await waitForCompletion(sessionId);
|
||||
|
||||
const log = await processTool.execute("call2", {
|
||||
action: "log",
|
||||
sessionId,
|
||||
offset: 30,
|
||||
});
|
||||
|
||||
const textBlock = log.content.find((c) => c.type === "text")?.text ?? "";
|
||||
const renderedLines = textBlock.split("\n");
|
||||
expect(renderedLines[0]?.trim()).toBe("line-31");
|
||||
expect(renderedLines[renderedLines.length - 1]?.trim()).toBe("line-260");
|
||||
expect(textBlock).not.toContain("showing last 200");
|
||||
expect((log.details as { totalLines?: number }).totalLines).toBe(260);
|
||||
});
|
||||
|
||||
it("scopes process sessions by scopeKey", async () => {
|
||||
const bashA = createExecTool({ backgroundMs: 10, scopeKey: "agent:alpha" });
|
||||
const processA = createProcessTool({ scopeKey: "agent:alpha" });
|
||||
@@ -300,6 +345,49 @@ describe("exec notifyOnExit", () => {
|
||||
expect(finished).toBeTruthy();
|
||||
expect(hasEvent).toBe(true);
|
||||
});
|
||||
|
||||
it("skips no-op completion events when command succeeds without output", async () => {
|
||||
const tool = createExecTool({
|
||||
allowBackground: true,
|
||||
backgroundMs: 0,
|
||||
notifyOnExit: true,
|
||||
sessionKey: "agent:main:main",
|
||||
});
|
||||
|
||||
const result = await tool.execute("call2", {
|
||||
command: shortDelayCmd,
|
||||
background: true,
|
||||
});
|
||||
|
||||
expect(result.details.status).toBe("running");
|
||||
const sessionId = (result.details as { sessionId: string }).sessionId;
|
||||
const status = await waitForCompletion(sessionId);
|
||||
expect(status).toBe("completed");
|
||||
expect(peekSystemEvents("agent:main:main")).toEqual([]);
|
||||
});
|
||||
|
||||
it("can re-enable no-op completion events via notifyOnExitEmptySuccess", async () => {
|
||||
const tool = createExecTool({
|
||||
allowBackground: true,
|
||||
backgroundMs: 0,
|
||||
notifyOnExit: true,
|
||||
notifyOnExitEmptySuccess: true,
|
||||
sessionKey: "agent:main:main",
|
||||
});
|
||||
|
||||
const result = await tool.execute("call3", {
|
||||
command: shortDelayCmd,
|
||||
background: true,
|
||||
});
|
||||
|
||||
expect(result.details.status).toBe("running");
|
||||
const sessionId = (result.details as { sessionId: string }).sessionId;
|
||||
const status = await waitForCompletion(sessionId);
|
||||
expect(status).toBe("completed");
|
||||
const events = peekSystemEvents("agent:main:main");
|
||||
expect(events.length).toBeGreaterThan(0);
|
||||
expect(events.some((event) => event.includes("Exec completed"))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("exec PATH handling", () => {
|
||||
|
||||
Reference in New Issue
Block a user