Skip to content

fix: guard against malformed text blocks in context truncation#51267

Merged
BunsDev merged 4 commits intoopenclaw:mainfrom
cgdusek:claude/practical-wescoff
Apr 25, 2026
Merged

fix: guard against malformed text blocks in context truncation#51267
BunsDev merged 4 commits intoopenclaw:mainfrom
cgdusek:claude/practical-wescoff

Conversation

@cgdusek
Copy link
Copy Markdown
Contributor

@cgdusek cgdusek commented Mar 20, 2026

Summary

  • Guard isTextBlock type guard to require typeof block.text === "string" (not just block.type === "text")
  • Guard 3 additional block.type === "text" sites in pruner.ts (collectTextSegments, collectPrunableToolResultSegments, estimateTextAndImageChars)
  • Add regression tests covering malformed {type: "text"} blocks in both the char estimator and context pruner

A plugin tool handler returning undefined/void produces a malformed content block {type: "text"} (no text property). This block persists to session JSONL and crashes the context truncation pipeline with TypeError: Cannot read properties of undefined (reading 'length') on every subsequent message, locking the session into an unrecoverable crash loop.

Closes #34979

Test plan

  • pnpm test -- src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts passes (4 new tests)
  • pnpm test -- src/agents/pi-extensions/context-pruning/pruner.test.ts passes (2 new + 11 existing tests)
  • CI green

Based on prior work by @alvinttang (#39331) and @coffeexcoin (#34980).

🤖 Generated with Claude Code

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 20, 2026

Greptile Summary

This PR hardens the context-truncation pipeline against a class of malformed content blocks produced when a plugin tool handler returns undefined/void. Those handlers write {type: "text"} (no text property) to the session JSONL, which previously caused TypeError: Cannot read properties of undefined (reading 'length') on every subsequent message — creating an unrecoverable crash loop.

Key changes:

  • isTextBlock type guard in tool-result-char-estimator.ts now requires typeof block.text === "string" in addition to type === "text", correctly routing malformed blocks to the estimateUnknownChars fallback.
  • Three additional guard sites in pruner.ts (collectTextSegments, collectPrunableToolResultSegments, estimateTextAndImageChars) add the same typeof block.text === "string" check, silently skipping malformed blocks rather than crashing.
  • Regression tests are added for both files, covering the crash paths described in issue [Bug]: Malformed tool result content block crashes context truncation in a session-permanent loop #34979.

The logic changes are minimal, consistent, and defensive without altering any behavior for well-formed blocks. One minor test assertion in tool-result-char-estimator.test.ts is weaker than its comment intends (toBeGreaterThanOrEqual(0) instead of toBeGreaterThan(0)).

Confidence Score: 5/5

  • This PR is safe to merge — it adds narrowly-scoped defensive guards with no behavioral change for well-formed blocks.
  • The fix is minimal and surgical: three one-line guard additions in pruner.ts and one condition added to an existing type guard in tool-result-char-estimator.ts. All existing tests continue to pass, and new regression tests confirm the crash is resolved. There is no change to control flow for valid data.
  • No files require special attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts
Line: 30

Comment:
**Test assertion doesn't match comment intent**

The comment says the malformed block should be estimated "not zero" (i.e. the `estimateUnknownChars` fallback should fire), but `toBeGreaterThanOrEqual(0)` allows a result of `0` — which would silently pass even if the fallback were broken and returned nothing. The assertion should be `toBeGreaterThan(0)` to actually enforce the stated invariant.

For reference, `estimateUnknownChars({type:"text"})` will `JSON.stringify` the object to `'{"type":"text"}'` (15 chars), so the expected result is already well above zero.

```suggestion
    expect(estimateMessageCharsCached(malformed, cache)).toBeGreaterThan(0);
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "fix: guard against m..."

Comment thread src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0a2700b2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/pi-extensions/context-pruning/pruner.ts Outdated
@cgdusek
Copy link
Copy Markdown
Contributor Author

cgdusek commented Mar 20, 2026

Addressed both review comments in b5cd499:

Greptile (P2) — test assertion: Tightened from toBeGreaterThanOrEqual(0) to toBeGreaterThan(0). The fallback estimateUnknownChars JSON-stringifies {type:"text"} to 15 chars, so this now actually enforces the invariant.

Codex (P1) — null content entries: Added if (!block) continue; guards to all four content block loops in pruner.ts (collectTextSegments, collectPrunableToolResultSegments, hasImageBlocks, estimateTextAndImageChars). Added a regression test for toolResult with null content entries.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Mar 20, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: adca2808f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/pi-extensions/context-pruning/pruner.ts Outdated
@cgdusek
Copy link
Copy Markdown
Contributor Author

cgdusek commented Mar 20, 2026

Re: Codex P1 — Preserve size accounting for malformed text blocks

Valid defense-in-depth observation, but out of scope for this crash fix:

Before this PR: {type: "text"} crashes block.text.length → session permanently locked in a crash loop (the reported bug).

After this PR: malformed block is silently skipped in the pruner's size estimate → minor undercount, but the session is functional and recoverable.

The char estimator (tool-result-char-estimator.ts:54-66) already handles this correctly via its estimateUnknownChars fallback (JSON.stringify). Adding equivalent fallback logic to the pruner's estimateTextAndImageChars would require broadening the pruner's type contract (ReadonlyArray<TextContent | ImageContent>unknown[]). The crash → silent-skip is a strict improvement for the reported issue. Happy to do that as a follow-up if desired.

@cgdusek
Copy link
Copy Markdown
Contributor Author

cgdusek commented Mar 20, 2026

CI status — remaining failures are pre-existing / unrelated

All PR-scoped checks pass (lint, build, unit tests). The 3 remaining red jobs are unrelated to this change:

Job Failing tests Touched by this PR? On main?
checks-windows (node, test, 2, 6) src/node-host/invoke.sanitize-env.test.ts — Windows env key handling No Yes — confirmed failing on main (run 23362337869)
checks (node, channels) extensions/telegram/src/send.proxy.test.ts, extensions/whatsapp/src/inbound.media.test.ts No Flaky on main
checks (node, extensions) extensions/tavily/index.test.ts, extensions/matrix/index.test.ts, extensions/bluebubbles/src/send.test.ts No Flaky on main

This PR only modifies:

  • src/agents/pi-embedded-runner/tool-result-char-estimator.ts
  • src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts (new)
  • src/agents/pi-extensions/context-pruning/pruner.ts
  • src/agents/pi-extensions/context-pruning/pruner.test.ts

None of the failing tests are in these files or import from them.

@alberthild
Copy link
Copy Markdown
Contributor

We audited this comprehensively on our end. The type guards are placed exactly where they need to be, handling both malformed objects and null entries correctly across both the estimator and pruner pipelines. The regression tests cover the crash edge cases perfectly. Fully support merging this to kill the crash loop! ✅

@cgdusek cgdusek force-pushed the claude/practical-wescoff branch from adca280 to 87d6b79 Compare March 23, 2026 22:17
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87d6b79b55

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agents/pi-embedded-runner/tool-result-char-estimator.ts
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot Bot commented Mar 23, 2026

🔒 Aisle Security Analysis

We found 2 potential security issue(s) in this PR:

# Severity Title
1 🟠 High Potential DoS via unbounded JSON.stringify of malformed tool-result text blocks
2 🟡 Medium Malformed toolResult text blocks are JSON-stringified and injected into pruned LLM context
1. 🟠 Potential DoS via unbounded JSON.stringify of malformed tool-result text blocks
Property Value
Severity High
CWE CWE-400
Location src/agents/pi-hooks/context-pruning/pruner.ts:16-34

Description

pruneContextMessages() now attempts to handle malformed {type:"text"} blocks by serializing the entire block with JSON.stringify() when text is not a string.

  • Input/control: tool results can originate from tools/plugins (potentially 3rd-party or remote) and are stored in the session transcript.
  • Issue: if a tool returns a text block where text is an object/array (possibly huge or deeply nested), serializeMalformedTextBlock() will call JSON.stringify(block) with no size/depth limits.
  • Impact: JSON.stringify() on large/deep inputs can cause high CPU usage and memory pressure, and the resulting large string is then further processed by character estimation and trimming logic (amplifying work). Because context pruning runs during context assembly, this can be triggered repeatedly, leading to request-time resource exhaustion.

Vulnerable code:

function serializeMalformedTextBlock(block: unknown): string {
  try {
    const serialized = JSON.stringify(block);
    return typeof serialized === "string" ? serialized : "[malformed text block]";
  } catch {
    return "[malformed text block]";
  }
}

function coerceTextBlock(block: unknown): string | null {
  ...
  return typeof text === "string" ? text : serializeMalformedTextBlock(block);
}

Recommendation

Avoid serializing arbitrary malformed blocks without bounds.

Recommended options (prefer 1 or 2):

  1. Do not stringify malformed blocks at all; replace with a constant marker.
function coerceTextBlock(block: unknown): string | null {
  if (!block || typeof block !== "object") return null;
  if ((block as any).type !== "text") return null;
  const text = (block as any).text;
  return typeof text === "string" ? text : "[malformed text block]";
}
  1. If you need some diagnostics, use a bounded safe stringify (max depth / max output length), and never stringify the whole block if it may contain large fields.
import { safeStringify } from "./safe-stringify"; // implement depth/length caps

function serializeMalformedTextBlock(block: unknown): string {
  return safeStringify(block, { maxDepth: 4, maxLength: 2048 }) ?? "[malformed text block]";
}
  1. Additionally, consider caching the coerced text per block/message during a single pruning run to avoid repeated serialization across estimate* and collect* passes.
2. 🟡 Malformed toolResult text blocks are JSON-stringified and injected into pruned LLM context
Property Value
Severity Medium
CWE CWE-201
Location src/agents/pi-hooks/context-pruning/pruner.ts:16-34

Description

The context pruner now attempts to recover from malformed {type:"text"} blocks by serializing the entire block with JSON.stringify() and treating that serialization as user-visible text.

This can lead to unintended disclosure and prompt-injection amplification:

  • Input: toolResult.content[] blocks can originate from plugins/tools and may be malformed or attacker-influenced.
  • Transformation: when block.type === "text" but block.text is not a string, coerceTextBlock() falls back to serializeMalformedTextBlock(block).
  • Sink: the resulting JSON string is included in collectTextSegments() / collectPrunableToolResultSegments() and may be embedded into the pruned context sent to the LLM (e.g., during image-path normalization or trimming).
  • Impact: JSON serialization can expose extra fields that were not intended to be model-visible (e.g., internal metadata, tokens, file contents embedded in structured objects) and can carry structured prompt-injection payloads verbatim.

Vulnerable code:

function serializeMalformedTextBlock(block: unknown): string {
  try {
    const serialized = JSON.stringify(block);
    return typeof serialized === "string" ? serialized : "[malformed text block]";
  } catch {
    return "[malformed text block]";
  }
}

function coerceTextBlock(block: unknown): string | null {
  ...
  const text = (block as { text?: unknown }).text;
  return typeof text === "string" ? text : serializeMalformedTextBlock(block);
}

Recommendation

Avoid serializing arbitrary malformed blocks into LLM-visible context.

Recommended approaches:

  1. Replace with a fixed placeholder (safe-by-default) and optionally include only minimal diagnostics:
function coerceTextBlock(block: unknown): string | null {
  if (!block || typeof block !== "object") return null;
  if ((block as any).type !== "text") return null;
  const text = (block as any).text;
  return typeof text === "string" ? text : "[malformed text block removed]";
}
  1. If you must preserve some information, allowlist specific fields and cap length:
const safe = { type: (block as any).type };
return JSON.stringify(safe).slice(0, 256);

Additionally, consider applying existing secret-redaction logic (if any) to any fallback text before inserting it into the model context.


Analyzed PR: #51267 at commit ca7d630

Last updated on: 2026-04-25T06:32:29Z

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cfeebbcbc3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1160 to +1164
dirName: "google-gemini-cli-auth",
idHint: "google-gemini-cli-auth",
source: {
source: "./index.ts",
built: "index.js",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove nonexistent auth plugins from bundled metadata

collectBundledPluginMetadata() in scripts/generate-bundled-plugin-metadata.mjs only serializes extensions/* directories that still have both package.json and openclaw.plugin.json, and this commit contains neither extensions/google-gemini-cli-auth nor extensions/minimax-portal-auth. Because these snapshot entries were added anyway, regenerating src/plugins/bundled-plugin-metadata.generated.ts drops them again (I verified the collector returns 75 entries while the checked-in snapshot now has 77), so the matches the generated metadata snapshot check in src/plugins/bundled-plugin-metadata.test.ts will fail and CI will keep reporting the generated file as stale.

Useful? React with 👍 / 👎.

cgdusek and others added 4 commits April 25, 2026 01:26
…ar estimation

A plugin tool handler returning undefined produces {type: "text"} (no text
property) in the session JSONL. This crashes the context truncation pipeline
with TypeError on every subsequent message, locking the session into an
unrecoverable crash loop.

Guard all four crash sites:
- isTextBlock type guard in tool-result-char-estimator.ts
- collectTextSegments in pruner.ts
- collectPrunableToolResultSegments in pruner.ts
- estimateTextAndImageChars in pruner.ts

Add regression tests for both the char estimator and the context pruner
covering malformed toolResult content blocks.

Closes openclaw#34979

Based on prior work by @alvinttang (openclaw#39331) and @coffeexcoin (openclaw#34980).

Co-Authored-By: alvinttang <alvinttang@users.noreply.github.com>
Co-Authored-By: coffeexcoin <coffeexcoin@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tighten test assertion from toBeGreaterThanOrEqual(0) to toBeGreaterThan(0)
  so the unknown-block fallback is actually enforced (greptile review).
- Add null/undefined guards to all content block loops in pruner.ts to prevent
  TypeError on block.type when sessions contain null entries (codex review).
- Add regression test for toolResult with null content entries in pruner.test.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BunsDev BunsDev force-pushed the claude/practical-wescoff branch from 60af534 to ca7d630 Compare April 25, 2026 06:30
@BunsDev
Copy link
Copy Markdown
Member

BunsDev commented Apr 25, 2026

Maintainer update before landing:

  • Rebased onto current main after the context-pruning path moved from pi-extensions to pi-hooks.
  • Dropped the obsolete generated plugin metadata churn from the old branch.
  • Addressed the Aisle undercount finding: malformed non-string text blocks are now serialized for pruning/size accounting instead of being treated as zero-sized.
  • Added a regression test proving malformed non-string text blocks trigger tool-result trimming.

Local verification:

  • pnpm test src/agents/pi-embedded-runner/tool-result-char-estimator.test.ts src/agents/pi-hooks/context-pruning/pruner.test.ts
  • pnpm check:changed

Waiting for the fresh GitHub checks before merge.

@BunsDev BunsDev merged commit 6b38714 into openclaw:main Apr 25, 2026
66 checks passed
vincentkoc added a commit that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for #66884 that
restated alexlomt's already-formatted entry one line above.
vincentkoc added a commit that referenced this pull request Apr 25, 2026
… tool-result pruning entries

Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (#71451): @vincentkoc implemented,
  but @jlapenna's #70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (#51267): @cgdusek's PR explicitly built
  on prior work in #39331 by @alvinttang and #34980 by @coffeexcoin.
  Now credits all three.
steipete pushed a commit to MonkeyLeeT/openclaw that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
steipete pushed a commit to MonkeyLeeT/openclaw that referenced this pull request Apr 25, 2026
… tool-result pruning entries

Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented,
  but @jlapenna's openclaw#70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built
  on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin.
  Now credits all three.
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
Angfr95 pushed a commit to Angfr95/openclaw that referenced this pull request Apr 25, 2026
… tool-result pruning entries

Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented,
  but @jlapenna's openclaw#70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built
  on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin.
  Now credits all three.
ayesha-aziz123 pushed a commit to ayesha-aziz123/openclaw that referenced this pull request Apr 26, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
ayesha-aziz123 pushed a commit to ayesha-aziz123/openclaw that referenced this pull request Apr 26, 2026
… tool-result pruning entries

Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented,
  but @jlapenna's openclaw#70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built
  on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin.
  Now credits all three.
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
… tool-result pruning entries

Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented,
  but @jlapenna's openclaw#70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built
  on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin.
  Now credits all three.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Three external-contributor commits from the last day landed without
CHANGELOG entries:

- Alex Fries (openclaw#68286, @ajfonthemove): hybrid memory search component
  scores. Added under Unreleased > Changes (feat).
- Charles Dusek (openclaw#51267, @cgdusek): malformed tool-result text-block
  guard. Added under Unreleased > Fixes.
- Jerome Benoit (openclaw#59935, @jerome-benoit): Nix Home Manager daemon PATH
  support. Added under Unreleased > Fixes.

Also drop a duplicate raw-subject changelog line for openclaw#66884 that
restated alexlomt's already-formatted entry one line above.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
… tool-result pruning entries

Three entries were missing co-credits I should have preserved:

- Diagnostics/OTEL exec-process spans (openclaw#71451): @vincentkoc implemented,
  but @jlapenna's openclaw#70424 proposed the broader tracing work this entry
  builds on. Now credits both.
- Diagnostics/OTEL preloaded SDK (openclaw#71450): same pattern — credits
  @vincentkoc and @jlapenna.
- Agents/tool-result pruning (openclaw#51267): @cgdusek's PR explicitly built
  on prior work in openclaw#39331 by @alvinttang and openclaw#34980 by @coffeexcoin.
  Now credits all three.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Malformed tool result content block crashes context truncation in a session-permanent loop

3 participants