From 8f7eae8b373b38851232d98f6db1b4bfe9633b1e Mon Sep 17 00:00:00 2001 From: k Date: Wed, 8 Apr 2026 14:19:11 +0900 Subject: [PATCH] docs(tool): use provider-agnostic JSON escaping guidance --- pkg/providers/common/common_test.go | 16 ++++++++++++++++ pkg/tools/edit.go | 10 +++++----- pkg/tools/filesystem.go | 4 ++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pkg/providers/common/common_test.go b/pkg/providers/common/common_test.go index 0a4d5f34a..c107bb665 100644 --- a/pkg/providers/common/common_test.go +++ b/pkg/providers/common/common_test.go @@ -254,6 +254,22 @@ func TestDecodeToolCallArguments_ObjectJSON(t *testing.T) { } } +func TestDecodeToolCallArguments_ObjectJSON_NewlineEscape(t *testing.T) { + raw := json.RawMessage(`{"content":"line1\nline2"}`) + args := DecodeToolCallArguments(raw, "write_file") + if args["content"] != "line1\nline2" { + t.Errorf("content = %q, want newline-expanded string", args["content"]) + } +} + +func TestDecodeToolCallArguments_ObjectJSON_LiteralBackslashN(t *testing.T) { + raw := json.RawMessage(`{"content":"line1\\nline2"}`) + args := DecodeToolCallArguments(raw, "write_file") + if args["content"] != `line1\nline2` { + t.Errorf("content = %q, want literal backslash-n", args["content"]) + } +} + func TestDecodeToolCallArguments_StringJSON(t *testing.T) { raw := json.RawMessage(`"{\"city\":\"SF\"}"`) args := DecodeToolCallArguments(raw, "test") diff --git a/pkg/tools/edit.go b/pkg/tools/edit.go index 09d1f545b..c527dab54 100644 --- a/pkg/tools/edit.go +++ b/pkg/tools/edit.go @@ -29,7 +29,7 @@ func (t *EditFileTool) Name() string { } func (t *EditFileTool) Description() string { - return "Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file. In `function.arguments`, use \\n for newline and \\\\n for literal backslash-n." + return "Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file. Standard JSON escaping applies: \\n for newline and \\\\n for literal backslash-n." } func (t *EditFileTool) Parameters() map[string]any { @@ -42,11 +42,11 @@ func (t *EditFileTool) Parameters() map[string]any { }, "old_text": map[string]any{ "type": "string", - "description": "The exact text to find and replace. In `function.arguments`, use \\n for newline and \\\\n for literal backslash-n.", + "description": "The exact text to find and replace. Standard JSON escaping applies: \\n for newline and \\\\n for literal backslash-n.", }, "new_text": map[string]any{ "type": "string", - "description": "The text to replace with. In `function.arguments`, use \\n for newline and \\\\n for literal backslash-n.", + "description": "The text to replace with. Standard JSON escaping applies: \\n for newline and \\\\n for literal backslash-n.", }, }, "required": []string{"path", "old_text", "new_text"}, @@ -92,7 +92,7 @@ func (t *AppendFileTool) Name() string { } func (t *AppendFileTool) Description() string { - return "Append content to the end of a file. In `function.arguments`, use \\n for newline and \\\\n for literal backslash-n." + return "Append content to the end of a file. Standard JSON escaping applies: \\n for newline and \\\\n for literal backslash-n." } func (t *AppendFileTool) Parameters() map[string]any { @@ -105,7 +105,7 @@ func (t *AppendFileTool) Parameters() map[string]any { }, "content": map[string]any{ "type": "string", - "description": "The content to append. In `function.arguments`, use \\n for newline and \\\\n for literal backslash-n.", + "description": "The content to append. Standard JSON escaping applies: \\n for newline and \\\\n for literal backslash-n.", }, }, "required": []string{"path", "content"}, diff --git a/pkg/tools/filesystem.go b/pkg/tools/filesystem.go index 52d77f665..0f6811f33 100644 --- a/pkg/tools/filesystem.go +++ b/pkg/tools/filesystem.go @@ -870,7 +870,7 @@ func (t *WriteFileTool) Name() string { } func (t *WriteFileTool) Description() string { - return "Write content to a file. In `function.arguments`, use \\n for a newline and \\\\n for a literal backslash-n sequence. Content is written byte-for-byte after argument decoding. If the file already exists, you must set overwrite=true to replace it." + return "Write content to a file. Content is written byte-for-byte after argument decoding. Standard JSON escaping applies: \\n for newline and \\\\n for a literal backslash-n sequence. If the file already exists, you must set overwrite=true to replace it." } func (t *WriteFileTool) Parameters() map[string]any { @@ -883,7 +883,7 @@ func (t *WriteFileTool) Parameters() map[string]any { }, "content": map[string]any{ "type": "string", - "description": "Content to write to the file. In `function.arguments`, use \\n for newline and \\\\n for literal backslash-n.", + "description": "Content to write to the file. Standard JSON escaping applies: \\n for newline and \\\\n for literal backslash-n.", }, "overwrite": map[string]any{ "type": "boolean",