mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 18:44:31 +00:00
ACP: remove maxMetaEventsPerTurn limit
This commit is contained in:
@@ -680,57 +680,6 @@ describe("createAcpReplyProjector", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("enforces maxMetaEventsPerTurn without suppressing assistant text", async () => {
|
|
||||||
const deliveries: Array<{ kind: string; text?: string }> = [];
|
|
||||||
const projector = createAcpReplyProjector({
|
|
||||||
cfg: createCfg({
|
|
||||||
acp: {
|
|
||||||
enabled: true,
|
|
||||||
stream: {
|
|
||||||
coalesceIdleMs: 0,
|
|
||||||
maxChunkChars: 256,
|
|
||||||
deliveryMode: "live",
|
|
||||||
maxMetaEventsPerTurn: 1,
|
|
||||||
tagVisibility: {
|
|
||||||
usage_update: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
shouldSendToolSummaries: true,
|
|
||||||
deliver: async (kind, payload) => {
|
|
||||||
deliveries.push({ kind, text: payload.text });
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
await projector.onEvent({
|
|
||||||
type: "status",
|
|
||||||
text: "usage updated: 10/100",
|
|
||||||
tag: "usage_update",
|
|
||||||
used: 10,
|
|
||||||
size: 100,
|
|
||||||
});
|
|
||||||
await projector.onEvent({
|
|
||||||
type: "status",
|
|
||||||
text: "usage updated: 11/100",
|
|
||||||
tag: "usage_update",
|
|
||||||
used: 11,
|
|
||||||
size: 100,
|
|
||||||
});
|
|
||||||
await projector.onEvent({
|
|
||||||
type: "text_delta",
|
|
||||||
text: "hello",
|
|
||||||
tag: "agent_message_chunk",
|
|
||||||
});
|
|
||||||
await projector.flush(true);
|
|
||||||
|
|
||||||
expect(deliveries).toEqual([
|
|
||||||
{ kind: "tool", text: prefixSystemMessage("usage updated: 10/100") },
|
|
||||||
{ kind: "block", text: "hello" },
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("supports tagVisibility overrides for tool updates", async () => {
|
it("supports tagVisibility overrides for tool updates", async () => {
|
||||||
const deliveries: Array<{ kind: string; text?: string }> = [];
|
const deliveries: Array<{ kind: string; text?: string }> = [];
|
||||||
const projector = createAcpReplyProjector({
|
const projector = createAcpReplyProjector({
|
||||||
|
|||||||
@@ -195,7 +195,6 @@ export function createAcpReplyProjector(params: {
|
|||||||
const liveIdleFlushMs = Math.max(streaming.coalescing.idleMs, ACP_LIVE_IDLE_FLUSH_FLOOR_MS);
|
const liveIdleFlushMs = Math.max(streaming.coalescing.idleMs, ACP_LIVE_IDLE_FLUSH_FLOOR_MS);
|
||||||
|
|
||||||
let emittedTurnChars = 0;
|
let emittedTurnChars = 0;
|
||||||
let emittedMetaEvents = 0;
|
|
||||||
let truncationNoticeEmitted = false;
|
let truncationNoticeEmitted = false;
|
||||||
let lastStatusHash: string | undefined;
|
let lastStatusHash: string | undefined;
|
||||||
let lastToolHash: string | undefined;
|
let lastToolHash: string | undefined;
|
||||||
@@ -264,7 +263,6 @@ export function createAcpReplyProjector(params: {
|
|||||||
blockReplyPipeline.stop();
|
blockReplyPipeline.stop();
|
||||||
blockReplyPipeline = createTurnBlockReplyPipeline();
|
blockReplyPipeline = createTurnBlockReplyPipeline();
|
||||||
emittedTurnChars = 0;
|
emittedTurnChars = 0;
|
||||||
emittedMetaEvents = 0;
|
|
||||||
truncationNoticeEmitted = false;
|
truncationNoticeEmitted = false;
|
||||||
lastStatusHash = undefined;
|
lastStatusHash = undefined;
|
||||||
lastToolHash = undefined;
|
lastToolHash = undefined;
|
||||||
@@ -295,21 +293,10 @@ export function createAcpReplyProjector(params: {
|
|||||||
await blockReplyPipeline.flush({ force });
|
await blockReplyPipeline.flush({ force });
|
||||||
};
|
};
|
||||||
|
|
||||||
const consumeMetaQuota = (force: boolean): boolean => {
|
|
||||||
if (force) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (emittedMetaEvents >= settings.maxMetaEventsPerTurn) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
emittedMetaEvents += 1;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const emitSystemStatus = async (
|
const emitSystemStatus = async (
|
||||||
text: string,
|
text: string,
|
||||||
meta?: AcpProjectedDeliveryMeta,
|
meta?: AcpProjectedDeliveryMeta,
|
||||||
opts?: { force?: boolean; dedupe?: boolean },
|
opts?: { dedupe?: boolean },
|
||||||
) => {
|
) => {
|
||||||
if (!params.shouldSendToolSummaries) {
|
if (!params.shouldSendToolSummaries) {
|
||||||
return;
|
return;
|
||||||
@@ -324,9 +311,6 @@ export function createAcpReplyProjector(params: {
|
|||||||
if (shouldDedupe && lastStatusHash === hash) {
|
if (shouldDedupe && lastStatusHash === hash) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!consumeMetaQuota(opts?.force === true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (settings.deliveryMode === "final_only") {
|
if (settings.deliveryMode === "final_only") {
|
||||||
pendingToolDeliveries.push({
|
pendingToolDeliveries.push({
|
||||||
payload: { text: formatted },
|
payload: { text: formatted },
|
||||||
@@ -339,10 +323,7 @@ export function createAcpReplyProjector(params: {
|
|||||||
lastStatusHash = hash;
|
lastStatusHash = hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
const emitToolSummary = async (
|
const emitToolSummary = async (event: Extract<AcpRuntimeEvent, { type: "tool_call" }>) => {
|
||||||
event: Extract<AcpRuntimeEvent, { type: "tool_call" }>,
|
|
||||||
opts?: { force?: boolean },
|
|
||||||
) => {
|
|
||||||
if (!params.shouldSendToolSummaries) {
|
if (!params.shouldSendToolSummaries) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -386,9 +367,6 @@ export function createAcpReplyProjector(params: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!consumeMetaQuota(opts?.force === true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const deliveryMeta: AcpProjectedDeliveryMeta = {
|
const deliveryMeta: AcpProjectedDeliveryMeta = {
|
||||||
...(event.tag ? { tag: event.tag } : {}),
|
...(event.tag ? { tag: event.tag } : {}),
|
||||||
...(toolCallId ? { toolCallId } : {}),
|
...(toolCallId ? { toolCallId } : {}),
|
||||||
@@ -418,7 +396,6 @@ export function createAcpReplyProjector(params: {
|
|||||||
tag: "session_info_update",
|
tag: "session_info_update",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
force: true,
|
|
||||||
dedupe: false,
|
dedupe: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ describe("acp stream settings", () => {
|
|||||||
expect(settings.hiddenBoundarySeparator).toBe("paragraph");
|
expect(settings.hiddenBoundarySeparator).toBe("paragraph");
|
||||||
expect(settings.repeatSuppression).toBe(true);
|
expect(settings.repeatSuppression).toBe(true);
|
||||||
expect(settings.maxTurnChars).toBe(24_000);
|
expect(settings.maxTurnChars).toBe(24_000);
|
||||||
expect(settings.maxMetaEventsPerTurn).toBe(64);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("applies explicit stream overrides", () => {
|
it("applies explicit stream overrides", () => {
|
||||||
@@ -26,7 +25,6 @@ describe("acp stream settings", () => {
|
|||||||
hiddenBoundarySeparator: "space",
|
hiddenBoundarySeparator: "space",
|
||||||
repeatSuppression: false,
|
repeatSuppression: false,
|
||||||
maxTurnChars: 500,
|
maxTurnChars: 500,
|
||||||
maxMetaEventsPerTurn: 7,
|
|
||||||
tagVisibility: {
|
tagVisibility: {
|
||||||
usage_update: true,
|
usage_update: true,
|
||||||
},
|
},
|
||||||
@@ -38,7 +36,6 @@ describe("acp stream settings", () => {
|
|||||||
expect(settings.hiddenBoundarySeparator).toBe("space");
|
expect(settings.hiddenBoundarySeparator).toBe("space");
|
||||||
expect(settings.repeatSuppression).toBe(false);
|
expect(settings.repeatSuppression).toBe(false);
|
||||||
expect(settings.maxTurnChars).toBe(500);
|
expect(settings.maxTurnChars).toBe(500);
|
||||||
expect(settings.maxMetaEventsPerTurn).toBe(7);
|
|
||||||
expect(settings.tagVisibility.usage_update).toBe(true);
|
expect(settings.tagVisibility.usage_update).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ const DEFAULT_ACP_HIDDEN_BOUNDARY_SEPARATOR_LIVE = "space";
|
|||||||
const DEFAULT_ACP_MAX_TURN_CHARS = 24_000;
|
const DEFAULT_ACP_MAX_TURN_CHARS = 24_000;
|
||||||
const DEFAULT_ACP_MAX_TOOL_SUMMARY_CHARS = 320;
|
const DEFAULT_ACP_MAX_TOOL_SUMMARY_CHARS = 320;
|
||||||
const DEFAULT_ACP_MAX_STATUS_CHARS = 320;
|
const DEFAULT_ACP_MAX_STATUS_CHARS = 320;
|
||||||
const DEFAULT_ACP_MAX_META_EVENTS_PER_TURN = 64;
|
|
||||||
|
|
||||||
export const ACP_TAG_VISIBILITY_DEFAULTS: Record<AcpSessionUpdateTag, boolean> = {
|
export const ACP_TAG_VISIBILITY_DEFAULTS: Record<AcpSessionUpdateTag, boolean> = {
|
||||||
agent_message_chunk: true,
|
agent_message_chunk: true,
|
||||||
@@ -36,7 +35,6 @@ export type AcpProjectionSettings = {
|
|||||||
maxTurnChars: number;
|
maxTurnChars: number;
|
||||||
maxToolSummaryChars: number;
|
maxToolSummaryChars: number;
|
||||||
maxStatusChars: number;
|
maxStatusChars: number;
|
||||||
maxMetaEventsPerTurn: number;
|
|
||||||
tagVisibility: Partial<Record<AcpSessionUpdateTag, boolean>>;
|
tagVisibility: Partial<Record<AcpSessionUpdateTag, boolean>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -127,14 +125,6 @@ export function resolveAcpProjectionSettings(cfg: OpenClawConfig): AcpProjection
|
|||||||
min: 64,
|
min: 64,
|
||||||
max: 8_000,
|
max: 8_000,
|
||||||
}),
|
}),
|
||||||
maxMetaEventsPerTurn: clampPositiveInteger(
|
|
||||||
stream?.maxMetaEventsPerTurn,
|
|
||||||
DEFAULT_ACP_MAX_META_EVENTS_PER_TURN,
|
|
||||||
{
|
|
||||||
min: 1,
|
|
||||||
max: 2_000,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
tagVisibility: stream?.tagVisibility ?? {},
|
tagVisibility: stream?.tagVisibility ?? {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,8 +183,6 @@ export const FIELD_HELP: Record<string, string> = {
|
|||||||
"acp.stream.maxToolSummaryChars":
|
"acp.stream.maxToolSummaryChars":
|
||||||
"Maximum characters for projected ACP tool lifecycle/progress summary lines.",
|
"Maximum characters for projected ACP tool lifecycle/progress summary lines.",
|
||||||
"acp.stream.maxStatusChars": "Maximum characters for projected ACP status/meta lines.",
|
"acp.stream.maxStatusChars": "Maximum characters for projected ACP status/meta lines.",
|
||||||
"acp.stream.maxMetaEventsPerTurn":
|
|
||||||
"Maximum ACP meta events projected per turn (text deltas continue unaffected).",
|
|
||||||
"acp.stream.tagVisibility":
|
"acp.stream.tagVisibility":
|
||||||
"Per-sessionUpdate visibility overrides for ACP projection (for example usage_update, available_commands_update).",
|
"Per-sessionUpdate visibility overrides for ACP projection (for example usage_update, available_commands_update).",
|
||||||
"acp.runtime.ttlMinutes":
|
"acp.runtime.ttlMinutes":
|
||||||
|
|||||||
@@ -375,7 +375,6 @@ export const FIELD_LABELS: Record<string, string> = {
|
|||||||
"acp.stream.maxTurnChars": "ACP Stream Max Turn Chars",
|
"acp.stream.maxTurnChars": "ACP Stream Max Turn Chars",
|
||||||
"acp.stream.maxToolSummaryChars": "ACP Stream Max Tool Summary Chars",
|
"acp.stream.maxToolSummaryChars": "ACP Stream Max Tool Summary Chars",
|
||||||
"acp.stream.maxStatusChars": "ACP Stream Max Status Chars",
|
"acp.stream.maxStatusChars": "ACP Stream Max Status Chars",
|
||||||
"acp.stream.maxMetaEventsPerTurn": "ACP Stream Max Meta Events Per Turn",
|
|
||||||
"acp.stream.tagVisibility": "ACP Stream Tag Visibility",
|
"acp.stream.tagVisibility": "ACP Stream Tag Visibility",
|
||||||
"acp.runtime.ttlMinutes": "ACP Runtime TTL (minutes)",
|
"acp.runtime.ttlMinutes": "ACP Runtime TTL (minutes)",
|
||||||
"acp.runtime.installCommand": "ACP Runtime Install Command",
|
"acp.runtime.installCommand": "ACP Runtime Install Command",
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ export type AcpStreamConfig = {
|
|||||||
maxToolSummaryChars?: number;
|
maxToolSummaryChars?: number;
|
||||||
/** Maximum visible characters for status lines. */
|
/** Maximum visible characters for status lines. */
|
||||||
maxStatusChars?: number;
|
maxStatusChars?: number;
|
||||||
/** Maximum number of meta events projected per turn. */
|
|
||||||
maxMetaEventsPerTurn?: number;
|
|
||||||
/**
|
/**
|
||||||
* Per-sessionUpdate visibility overrides.
|
* Per-sessionUpdate visibility overrides.
|
||||||
* Keys not listed here fall back to OpenClaw defaults.
|
* Keys not listed here fall back to OpenClaw defaults.
|
||||||
|
|||||||
@@ -352,7 +352,6 @@ export const OpenClawSchema = z
|
|||||||
maxTurnChars: z.number().int().positive().optional(),
|
maxTurnChars: z.number().int().positive().optional(),
|
||||||
maxToolSummaryChars: z.number().int().positive().optional(),
|
maxToolSummaryChars: z.number().int().positive().optional(),
|
||||||
maxStatusChars: z.number().int().positive().optional(),
|
maxStatusChars: z.number().int().positive().optional(),
|
||||||
maxMetaEventsPerTurn: z.number().int().positive().optional(),
|
|
||||||
tagVisibility: z.record(z.string(), z.boolean()).optional(),
|
tagVisibility: z.record(z.string(), z.boolean()).optional(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ Use only these ACP stream controls for this behavior:
|
|||||||
- `maxTurnChars`
|
- `maxTurnChars`
|
||||||
- `maxToolSummaryChars`
|
- `maxToolSummaryChars`
|
||||||
- `maxStatusChars`
|
- `maxStatusChars`
|
||||||
- `maxMetaEventsPerTurn`
|
|
||||||
|
|
||||||
Removed from plan/config:
|
Removed from plan/config:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user