mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(cli): never create note-only content for an empty OpenCode 2 result
Tool.Result allows content: [], and for it the array branch of appendResult pushed a text part that held only the session note, so the note became the whole content of the tool result. Add a text part only when the array already holds a part; an empty array now falls through to the string output branch, or the result is returned unchanged. Pin it in a new agent_clients test: the part-adding push sits inside the non-empty array branch, ahead of the string output fallback, and no unguarded array branch is left. Refs #2204 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
1 parent
f531be2500
commit
d3d0bc8452
2 files changed
+32
-2
No files matched your search
@@ -491,14 +491,18 @@ char *cbm_client_adapter_opencode(const char *binary_path) {
|
||||
* string/parts surface the model reads, output is the tool's schema-typed
|
||||
* value). Append to content first, then a string output; if neither text
|
||||
* surface exists, leave the result untouched so the tool's own output is
|
||||
* never hidden. The caller assigns the returned result onto event.result. */
|
||||
* never hidden. A parts array gets a new text part only when it already
|
||||
* holds a part: `content: []` is a valid result, and a part added there
|
||||
* would be the note alone, so an empty array falls through to the string
|
||||
* output (or the unchanged result). The caller assigns the returned result
|
||||
* onto event.result. */
|
||||
sb_append(&sb,
|
||||
"function appendResult(result, extra) {\n"
|
||||
" if (!result || typeof result !== 'object') return result;\n"
|
||||
" if (typeof result.content === 'string') {\n"
|
||||
" return { ...result, content: result.content + '\\n' + extra };\n"
|
||||
" }\n"
|
||||
" if (Array.isArray(result.content)) {\n"
|
||||
" if (Array.isArray(result.content) && result.content.length > 0) {\n"
|
||||
" const content = result.content.slice();\n"
|
||||
" for (let i = content.length - 1; i >= 0; i--) {\n"
|
||||
" if (content[i] && content[i].type === 'text') {\n"
|
||||
|
||||
@@ -1432,6 +1432,31 @@ TEST(client_adapter_opencode_v2_compaction_note_goes_into_the_compaction_message
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #2204: Tool.Result allows `content: []`. appendResult adds a text part to a
|
||||
* parts array only when the array already holds a part; an empty array falls
|
||||
* through to the string `output` (or the unchanged result), so the note never
|
||||
* becomes the whole content of a tool result. */
|
||||
TEST(client_adapter_opencode_v2_append_result_never_creates_note_only_content) {
|
||||
char *js = cbm_client_adapter_opencode("/usr/local/bin/codebase-memory-mcp");
|
||||
ASSERT_NOT_NULL(js);
|
||||
const char *parts =
|
||||
strstr(js, "if (Array.isArray(result.content) && result.content.length > 0) {");
|
||||
const char *add_part = strstr(js, "content.push({ type: 'text', text: extra });");
|
||||
const char *output_fallback = strstr(js, "if (typeof result.output === 'string') {");
|
||||
ASSERT_NOT_NULL(parts);
|
||||
ASSERT_NOT_NULL(add_part);
|
||||
ASSERT_NOT_NULL(output_fallback);
|
||||
/* The only part-adding push sits inside the non-empty branch; the string
|
||||
* output fallback, where `content: []` lands, comes after it. */
|
||||
ASSERT_TRUE(parts < add_part);
|
||||
ASSERT_TRUE(add_part < output_fallback);
|
||||
ASSERT_NULL(strstr(add_part + 1, "content.push("));
|
||||
/* No unguarded array branch is left. */
|
||||
ASSERT_NULL(strstr(js, "if (Array.isArray(result.content)) {"));
|
||||
free(js);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* augment() is awaited inline inside 'tool.execute.after', so a hook-augment
|
||||
* that never exits would stall every grep/glob/read completion in the host
|
||||
* session until the agent is restarted. The generated plugin must bound the
|
||||
@@ -1505,6 +1530,7 @@ SUITE(agent_clients) {
|
||||
RUN_TEST(client_adapter_opencode_covers_lifecycle_read_and_compaction);
|
||||
RUN_TEST(client_adapter_opencode_exports_the_v2_default_definition_issue2077);
|
||||
RUN_TEST(client_adapter_opencode_v2_compaction_note_goes_into_the_compaction_messages);
|
||||
RUN_TEST(client_adapter_opencode_v2_append_result_never_creates_note_only_content);
|
||||
RUN_TEST(client_adapter_opencode_bounds_a_hung_hook_augment_child);
|
||||
RUN_TEST(client_adapter_rejects_missing_binary_path);
|
||||
}
|
||||
Reference in new issue
Block a user