MoonshotAI / MoonshotAI/kimi-code
[Bug]: renderToolResultForModel treats a whitespace-only error text part as non-empty output
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
What version of Kimi Code is running?
0.1.1, main@58b74cfeab157483eef8a9e4ed8f4b683eecb34d
Which open platform/subscription were you using?
Not applicable; reproduced by directly invoking deterministic local rendering code.
Which model were you using?
Not applicable; no model request is made.
What platform is your computer?
macOS arm64
What issue are you seeing?
renderToolResultForModel handles empty-equivalent tool-result content inconsistently when isError is true.
A successful tool result with a single whitespace-only text part is normalized as empty output. An error result with an exactly empty text part is also normalized as empty error output.
However, an error result with a single whitespace-only text part is treated as non-empty output:
renderToolResultForModel({
output: [{ type: 'text', text: ' \n ' }],
isError: true,
});
currently returns:
[
{
type: 'text',
text: '<system>ERROR: Tool execution failed.</system>\n \n ',
},
]
The whitespace-only text block is therefore preserved as tool error output instead of being classified as empty-equivalent content.
What steps can reproduce the bug?
-
Check out Kimi Code
mainat commit58b74cfeab157483eef8a9e4ed8f4b683eecb34d. -
Install dependencies:
npm install
- Create
packages/agent-core-v2/test/agent/contextMemory/toolResultRender.test.ts:
import { describe, expect, it } from 'vitest';
import { renderToolResultForModel } from '#/agent/contextMemory/toolResultRender';
const text = (value: string) => ({ type: 'text', text: value }) as const;
const EMPTY_ERROR_STATUS =
'<system>ERROR: Tool execution failed. Tool output is empty.</system>';
describe('renderToolResultForModel', () => {
it('collapses a single whitespace-only error text part to the empty-error status', () => {
expect(
renderToolResultForModel({
output: [text(' \n ')],
isError: true,
}),
).toEqual([text(EMPTY_ERROR_STATUS)]);
});
});
- Run:
npm run test -- \
packages/agent-core-v2/test/agent/contextMemory/toolResultRender.test.ts
- Observe that the test fails because the whitespace-only error text part is rendered as a generic error plus whitespace, not as the empty-error status.
What is the expected behavior?
A whitespace-only text part should be treated as empty-equivalent content when isError is true.
The reproduction above should return:
[
{
type: 'text',
text: '<system>ERROR: Tool execution failed. Tool output is empty.</system>',
},
]
This should match the existing empty-output behavior for:
renderToolResultForModel({
output: [{ type: 'text', text: '' }],
isError: true,
});
and the existing whitespace-only success-output behavior.
Additional information
The current implementation first collapses string output and single-text-part array output into single:
const single =
typeof output === 'string'
? output
: singleTextPart(output);
For error results, it then checks only single.length === 0:
if (result.isError === true) {
if (single.length === 0) {
return [textPart(TOOL_EMPTY_ERROR_STATUS)];
}
return [textPart(`${TOOL_ERROR_STATUS}\n${single}`)];
}
This misses whitespace-only values such as:
' \n '
The same module already has a helper that treats whitespace-only text as empty output:
function isEmptyOutputText(output: string): boolean {
return output.trim().length === 0 || output.trim() === TOOL_OUTPUT_EMPTY_TEXT;
}
It also treats content arrays containing only whitespace-only text blocks as empty-equivalent:
function isEmptyEquivalentContentArray(
output: readonly ContentPart[],
): boolean {
return output.every(
(part) =>
part.type === 'text' &&
part.text.trim().length === 0,
);
}
A possible fix is to use the same empty-text predicate in the error branch:
if (result.isError === true) {
if (isEmptyOutputText(single)) {
return [textPart(TOOL_EMPTY_ERROR_STATUS)];
}
return [textPart(`${TOOL_ERROR_STATUS}\n${single}`)];
}
Regression coverage should include:
- exactly empty string error output;
- whitespace-only string error output;
- exactly empty single text-part error output;
- whitespace-only single text-part error output;
- multi-part arrays containing only whitespace text;
- non-empty error output preserving the current error prefix.
Contribution
- I am willing to submit a PR for this bug fix myself (please wait for maintainer approval in this issue first)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the renderToolResultForModel entry point imported from #/agent/contextMemory/toolResultRender and the existing toolResultRender.test.ts coverage. Run the provided Vitest command to reproduce the failure, then compare the error branch with the module's empty-output helpers. Done means whitespace-only error content produces the empty-error status while non-empty errors retain their prefix and the listed regression cases pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, testing
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100