Address compaction review feedback

- gate the compaction continuation retry on existing replay side-effect metadata
- type the bundled compaction notifier hook without explicit any
- add an Unreleased changelog entry
This commit is contained in:
simplyclever914
2026-05-03 15:34:35 +03:00
committed by Peter Steinberger
parent e84ceb47f6
commit cb4f4f5f3a
3 changed files with 19 additions and 12 deletions

View File

@@ -71,6 +71,7 @@ Docs: https://docs.openclaw.ai
- Channels/secrets: resolve SecretRef-backed channel credentials through external plugin secret contracts after the plugin split, covering runtime startup, target discovery, webhook auth, disabled-account enumeration, and late-bound web_search config. Fixes #76371. (#76449) Thanks @joshavant and @neeravmakwana.
- Docker/Gateway: pass Docker setup `.env` values into gateway and CLI containers and preserve exec SecretRef `passEnv` keys in managed service plans, so 1Password Connect-backed Discord tokens keep resolving after doctor or plugin repair. Thanks @vincentkoc.
- Control UI/WebChat: explain compaction boundaries in chat history and link directly to session checkpoint controls so pre-compaction turns no longer look silently lost after refresh. Fixes #76415. Thanks @BunsDev.
- Agents/compaction: add an optional bundled compaction notifier hook and retry once from the compacted transcript when automatic compaction leaves a turn without a final visible reply. Thanks @simplyclever914.
- Agents/incomplete-turn: detect and surface a warning when the agent's final text after a tool-call chain is silently dropped because the post-tool assistant response was never produced, instead of completing the turn with only the pre-tool analysis text. Fixes #76477. Thanks @amknight.
- Channels/WhatsApp: attach native outbound mention metadata for group text and media captions by resolving `@+<digits>` and `@<digits>` tokens against WhatsApp participant data, including LID groups. Fixes #39879; carries forward #56863. Thanks @kengi1437, @joe2643, and @fridayck.
- Channels/WhatsApp: require outbound mention tokens to end at a word boundary so phone-number prefixes inside longer strings no longer trigger hidden native mentions.
@@ -79,7 +80,6 @@ Docs: https://docs.openclaw.ai
- Plugins/install: require OpenClaw-owned install provenance before granting official npm plugin scanner trust, so direct npm package names no longer bypass launch-code scanning while catalog, onboarding, and doctor installs stay trusted. Thanks @fede-kamel and @vincentkoc.
- Network proxy: preserve target TLS hostname validation for Node HTTPS requests routed through the managed HTTP proxy, so Discord-style CONNECT traffic no longer validates certificates against the local proxy host. Fixes #74809. (#76442) Thanks @jesse-merhi and @abnershang.
- Gateway/sessions: keep async `sessions.list` title and preview hydration bounded to transcript head/tail reads so Control UI polling cannot full-scan large session transcripts every refresh. Thanks @vincentkoc.
- Gateway/performance: cache per-run verbose-level session reads, skip a redundant `lsof` scan in `gateway --force` when no listener was killed, and make the Gateway startup benchmark print usage for `--help`.
- Gateway/sessions: keep agent runtime metadata on lightweight `sessions.list` rows so model-only session patches do not make Control UI lose runtime identity. Thanks @vincentkoc.
- Gateway/sessions: keep bulk `sessions.list` rows lightweight by skipping per-row transcript usage fallback, display model inference, and plugin projection, avoiding event-loop stalls in large session stores. Thanks @Marvinthebored and @vincentkoc.
- Gateway/models: keep read-only `models.list` fallbacks on persisted/current metadata and configured rows while using static auth checks, so missing `models.json` files no longer runtime-load provider discovery or stall gateway after restart. Fixes #76382; refs #76360 and #75707. Thanks @trojy13, @RayWoo, @AnathemaOfficial, and @vincentkoc.

View File

@@ -2363,7 +2363,7 @@ export async function runEmbeddedPiAgent(
!attempt.yieldDetected &&
!attempt.didSendDeterministicApprovalPrompt &&
!attempt.lastToolError &&
!hasMessagingToolDeliveryEvidence(attempt) &&
!resolveAttemptReplayMetadata(attempt).hadPotentialSideEffects &&
compactionContinuationRetryAttempts < 1
) {
compactionContinuationRetryAttempts += 1;

View File

@@ -1,21 +1,28 @@
const handler = async (event: any) => {
import type { HookHandler } from "../../hooks.js";
function readOptionalNumber(context: Record<string, unknown>, key: string): number | undefined {
const value = context[key];
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
}
const handler: HookHandler = async (event) => {
try {
if (!event || !Array.isArray(event.messages)) return;
const context = event.context ?? {};
const context = event.context;
if (event.type === "session" && event.action === "compact:before") {
const messageCount = typeof context.messageCount === "number" && context.messageCount >= 0
? ` (${context.messageCount} messages)`
const messageCount = readOptionalNumber(context, "messageCount");
const messageSuffix = messageCount !== undefined && messageCount >= 0
? ` (${messageCount} messages)`
: "";
event.messages.push(`🧹 Compacting context${messageCount} so I can continue without losing history…`);
event.messages.push(`🧹 Compacting context${messageSuffix} so I can continue without losing history…`);
return;
}
if (event.type === "session" && event.action === "compact:after") {
const before = typeof context.tokensBefore === "number" ? context.tokensBefore : undefined;
const after = typeof context.tokensAfter === "number" ? context.tokensAfter : undefined;
const tokenDelta = before !== undefined && after !== undefined
? ` (${before.toLocaleString()}${after.toLocaleString()} tokens)`
const tokensBefore = readOptionalNumber(context, "tokensBefore");
const tokensAfter = readOptionalNumber(context, "tokensAfter");
const tokenDelta = tokensBefore !== undefined && tokensAfter !== undefined
? ` (${tokensBefore.toLocaleString()}${tokensAfter.toLocaleString()} tokens)`
: "";
event.messages.push(`✅ Context compacted${tokenDelta}. Continuing from where I left off.`);
}