From 8292401719e7d4f3d107e2cbec607e3b9e8a43f5 Mon Sep 17 00:00:00 2001 From: Onur <2453968+osolmaz@users.noreply.github.com> Date: Sun, 1 Mar 2026 18:11:20 +0100 Subject: [PATCH] ACP: rename stream char limits to output/sessionUpdate --- src/auto-reply/reply/acp-projector.test.ts | 4 ++-- src/auto-reply/reply/acp-projector.ts | 14 ++++++------ .../reply/acp-stream-settings.test.ts | 9 +++++--- src/auto-reply/reply/acp-stream-settings.ts | 22 +++++++------------ src/config/schema.help.ts | 9 ++++---- src/config/schema.labels.ts | 5 ++--- src/config/types.acp.ts | 10 ++++----- src/config/zod-schema.ts | 5 ++--- 8 files changed, 35 insertions(+), 43 deletions(-) diff --git a/src/auto-reply/reply/acp-projector.test.ts b/src/auto-reply/reply/acp-projector.test.ts index 7d5d398f32f..7432f3c7a50 100644 --- a/src/auto-reply/reply/acp-projector.test.ts +++ b/src/auto-reply/reply/acp-projector.test.ts @@ -450,7 +450,7 @@ describe("createAcpReplyProjector", () => { enabled: true, stream: { deliveryMode: "live", - maxToolSummaryChars: 48, + maxSessionUpdateChars: 48, tagVisibility: { tool_call: true, tool_call_update: true, @@ -649,7 +649,7 @@ describe("createAcpReplyProjector", () => { coalesceIdleMs: 0, maxChunkChars: 256, deliveryMode: "live", - maxTurnChars: 5, + maxOutputChars: 5, }, }, }), diff --git a/src/auto-reply/reply/acp-projector.ts b/src/auto-reply/reply/acp-projector.ts index b8dccf3e0af..53edd2094c4 100644 --- a/src/auto-reply/reply/acp-projector.ts +++ b/src/auto-reply/reply/acp-projector.ts @@ -194,7 +194,7 @@ export function createAcpReplyProjector(params: { const chunker = new EmbeddedBlockChunker(streaming.chunking); const liveIdleFlushMs = Math.max(streaming.coalescing.idleMs, ACP_LIVE_IDLE_FLUSH_FLOOR_MS); - let emittedTurnChars = 0; + let emittedOutputChars = 0; let truncationNoticeEmitted = false; let lastStatusHash: string | undefined; let lastToolHash: string | undefined; @@ -262,7 +262,7 @@ export function createAcpReplyProjector(params: { clearLiveIdleTimer(); blockReplyPipeline.stop(); blockReplyPipeline = createTurnBlockReplyPipeline(); - emittedTurnChars = 0; + emittedOutputChars = 0; truncationNoticeEmitted = false; lastStatusHash = undefined; lastToolHash = undefined; @@ -301,7 +301,7 @@ export function createAcpReplyProjector(params: { if (!params.shouldSendToolSummaries) { return; } - const bounded = truncateText(text.trim(), settings.maxStatusChars); + const bounded = truncateText(text.trim(), settings.maxSessionUpdateChars); if (!bounded) { return; } @@ -332,7 +332,7 @@ export function createAcpReplyProjector(params: { } const renderedToolSummary = renderToolSummaryText(event); - const toolSummary = truncateText(renderedToolSummary, settings.maxToolSummaryChars); + const toolSummary = truncateText(renderedToolSummary, settings.maxSessionUpdateChars); const hash = hashText(renderedToolSummary); const toolCallId = event.toolCallId?.trim() || undefined; const status = normalizeToolStatus(event.status); @@ -424,14 +424,14 @@ export function createAcpReplyProjector(params: { text = `${resolveHiddenBoundarySeparatorText(settings.hiddenBoundarySeparator)}${text}`; } pendingHiddenBoundary = false; - if (emittedTurnChars >= settings.maxTurnChars) { + if (emittedOutputChars >= settings.maxOutputChars) { await emitTruncationNotice(); return; } - const remaining = settings.maxTurnChars - emittedTurnChars; + const remaining = settings.maxOutputChars - emittedOutputChars; const accepted = remaining < text.length ? text.slice(0, remaining) : text; if (accepted.length > 0) { - emittedTurnChars += accepted.length; + emittedOutputChars += accepted.length; lastVisibleOutputTail = accepted.slice(-1); if (settings.deliveryMode === "live") { liveBufferText += accepted; diff --git a/src/auto-reply/reply/acp-stream-settings.test.ts b/src/auto-reply/reply/acp-stream-settings.test.ts index ee2c4b9e52e..b520b29affc 100644 --- a/src/auto-reply/reply/acp-stream-settings.test.ts +++ b/src/auto-reply/reply/acp-stream-settings.test.ts @@ -12,7 +12,8 @@ describe("acp stream settings", () => { expect(settings.deliveryMode).toBe("final_only"); expect(settings.hiddenBoundarySeparator).toBe("paragraph"); expect(settings.repeatSuppression).toBe(true); - expect(settings.maxTurnChars).toBe(24_000); + expect(settings.maxOutputChars).toBe(24_000); + expect(settings.maxSessionUpdateChars).toBe(320); }); it("applies explicit stream overrides", () => { @@ -24,7 +25,8 @@ describe("acp stream settings", () => { deliveryMode: "final_only", hiddenBoundarySeparator: "space", repeatSuppression: false, - maxTurnChars: 500, + maxOutputChars: 500, + maxSessionUpdateChars: 123, tagVisibility: { usage_update: true, }, @@ -35,7 +37,8 @@ describe("acp stream settings", () => { expect(settings.deliveryMode).toBe("final_only"); expect(settings.hiddenBoundarySeparator).toBe("space"); expect(settings.repeatSuppression).toBe(false); - expect(settings.maxTurnChars).toBe(500); + expect(settings.maxOutputChars).toBe(500); + expect(settings.maxSessionUpdateChars).toBe(123); expect(settings.tagVisibility.usage_update).toBe(true); }); diff --git a/src/auto-reply/reply/acp-stream-settings.ts b/src/auto-reply/reply/acp-stream-settings.ts index 42720d04fe1..fd06c420336 100644 --- a/src/auto-reply/reply/acp-stream-settings.ts +++ b/src/auto-reply/reply/acp-stream-settings.ts @@ -8,9 +8,8 @@ const DEFAULT_ACP_REPEAT_SUPPRESSION = true; const DEFAULT_ACP_DELIVERY_MODE = "final_only"; const DEFAULT_ACP_HIDDEN_BOUNDARY_SEPARATOR = "paragraph"; const DEFAULT_ACP_HIDDEN_BOUNDARY_SEPARATOR_LIVE = "space"; -const DEFAULT_ACP_MAX_TURN_CHARS = 24_000; -const DEFAULT_ACP_MAX_TOOL_SUMMARY_CHARS = 320; -const DEFAULT_ACP_MAX_STATUS_CHARS = 320; +const DEFAULT_ACP_MAX_OUTPUT_CHARS = 24_000; +const DEFAULT_ACP_MAX_SESSION_UPDATE_CHARS = 320; export const ACP_TAG_VISIBILITY_DEFAULTS: Record = { agent_message_chunk: true, @@ -32,9 +31,8 @@ export type AcpProjectionSettings = { deliveryMode: AcpDeliveryMode; hiddenBoundarySeparator: AcpHiddenBoundarySeparator; repeatSuppression: boolean; - maxTurnChars: number; - maxToolSummaryChars: number; - maxStatusChars: number; + maxOutputChars: number; + maxSessionUpdateChars: number; tagVisibility: Partial>; }; @@ -109,22 +107,18 @@ export function resolveAcpProjectionSettings(cfg: OpenClawConfig): AcpProjection hiddenBoundaryFallback, ), repeatSuppression: clampBoolean(stream?.repeatSuppression, DEFAULT_ACP_REPEAT_SUPPRESSION), - maxTurnChars: clampPositiveInteger(stream?.maxTurnChars, DEFAULT_ACP_MAX_TURN_CHARS, { + maxOutputChars: clampPositiveInteger(stream?.maxOutputChars, DEFAULT_ACP_MAX_OUTPUT_CHARS, { min: 1, max: 500_000, }), - maxToolSummaryChars: clampPositiveInteger( - stream?.maxToolSummaryChars, - DEFAULT_ACP_MAX_TOOL_SUMMARY_CHARS, + maxSessionUpdateChars: clampPositiveInteger( + stream?.maxSessionUpdateChars, + DEFAULT_ACP_MAX_SESSION_UPDATE_CHARS, { min: 64, max: 8_000, }, ), - maxStatusChars: clampPositiveInteger(stream?.maxStatusChars, DEFAULT_ACP_MAX_STATUS_CHARS, { - min: 64, - max: 8_000, - }), tagVisibility: stream?.tagVisibility ?? {}, }; } diff --git a/src/config/schema.help.ts b/src/config/schema.help.ts index de38702b556..61eb12c6dc6 100644 --- a/src/config/schema.help.ts +++ b/src/config/schema.help.ts @@ -178,11 +178,10 @@ export const FIELD_HELP: Record = { "ACP delivery style: live streams projected output incrementally, final_only buffers all projected ACP output until terminal turn events.", "acp.stream.hiddenBoundarySeparator": "Separator inserted before next visible assistant text when hidden ACP tool lifecycle events occurred (none|space|newline|paragraph). Default: paragraph.", - "acp.stream.maxTurnChars": - "Maximum assistant text characters projected per ACP turn before truncation notice is emitted.", - "acp.stream.maxToolSummaryChars": - "Maximum characters for projected ACP tool lifecycle/progress summary lines.", - "acp.stream.maxStatusChars": "Maximum characters for projected ACP status/meta lines.", + "acp.stream.maxOutputChars": + "Maximum assistant output characters projected per ACP turn before truncation notice is emitted.", + "acp.stream.maxSessionUpdateChars": + "Maximum characters for projected ACP session/update lines (tool/status updates).", "acp.stream.tagVisibility": "Per-sessionUpdate visibility overrides for ACP projection (for example usage_update, available_commands_update).", "acp.runtime.ttlMinutes": diff --git a/src/config/schema.labels.ts b/src/config/schema.labels.ts index a282303027b..d5a6170c330 100644 --- a/src/config/schema.labels.ts +++ b/src/config/schema.labels.ts @@ -372,9 +372,8 @@ export const FIELD_LABELS: Record = { "acp.stream.repeatSuppression": "ACP Stream Repeat Suppression", "acp.stream.deliveryMode": "ACP Stream Delivery Mode", "acp.stream.hiddenBoundarySeparator": "ACP Stream Hidden Boundary Separator", - "acp.stream.maxTurnChars": "ACP Stream Max Turn Chars", - "acp.stream.maxToolSummaryChars": "ACP Stream Max Tool Summary Chars", - "acp.stream.maxStatusChars": "ACP Stream Max Status Chars", + "acp.stream.maxOutputChars": "ACP Stream Max Output Chars", + "acp.stream.maxSessionUpdateChars": "ACP Stream Max Session Update Chars", "acp.stream.tagVisibility": "ACP Stream Tag Visibility", "acp.runtime.ttlMinutes": "ACP Runtime TTL (minutes)", "acp.runtime.installCommand": "ACP Runtime Install Command", diff --git a/src/config/types.acp.ts b/src/config/types.acp.ts index 7f0549393e9..06a1beb9717 100644 --- a/src/config/types.acp.ts +++ b/src/config/types.acp.ts @@ -16,12 +16,10 @@ export type AcpStreamConfig = { deliveryMode?: "live" | "final_only"; /** Separator inserted before visible text when hidden tool events occurred. */ hiddenBoundarySeparator?: "none" | "space" | "newline" | "paragraph"; - /** Maximum assistant text characters forwarded per turn. */ - maxTurnChars?: number; - /** Maximum visible characters for tool summary/meta lines. */ - maxToolSummaryChars?: number; - /** Maximum visible characters for status lines. */ - maxStatusChars?: number; + /** Maximum assistant output characters forwarded per turn. */ + maxOutputChars?: number; + /** Maximum visible characters for projected session/update lines. */ + maxSessionUpdateChars?: number; /** * Per-sessionUpdate visibility overrides. * Keys not listed here fall back to OpenClaw defaults. diff --git a/src/config/zod-schema.ts b/src/config/zod-schema.ts index f9907d1b057..73677c8bf34 100644 --- a/src/config/zod-schema.ts +++ b/src/config/zod-schema.ts @@ -349,9 +349,8 @@ export const OpenClawSchema = z z.literal("paragraph"), ]) .optional(), - maxTurnChars: z.number().int().positive().optional(), - maxToolSummaryChars: z.number().int().positive().optional(), - maxStatusChars: z.number().int().positive().optional(), + maxOutputChars: z.number().int().positive().optional(), + maxSessionUpdateChars: z.number().int().positive().optional(), tagVisibility: z.record(z.string(), z.boolean()).optional(), }) .strict()