openclaw/pr3647_comments.json
2026-01-28 22:26:10 -05:00

2 lines
58 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150805","pull_request_review_id":3719783923,"id":2739150805,"node_id":"PRRC_kwDOQb6kR86jRB_V","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"The comment on line 60 is questioning rather than explanatory. Comments with questions like \"Deep clone to avoid mutating the input unless necessary?\" and \"Actually, we can mutate in place effectively or clone messages that need change\" suggest uncertainty or incomplete decision-making. The implementation does create a new array and new message objects when changes are detected (lines 63, 107-110), so the comment should clearly state the approach taken: \"Creates new message objects only when sanitization is needed; otherwise returns the original messages to avoid unnecessary copying.\"\n```suggestion\n // Creates new message objects only when sanitization is needed; otherwise\n // returns the original messages to avoid unnecessary copying, while guarding\n // against corrupt JSON in tool arguments that could break the session.\n```","created_at":"2026-01-29T00:08:39Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150805","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150805"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150805"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150805/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":60,"original_start_line":60,"start_side":"RIGHT","line":62,"original_line":62,"side":"RIGHT","author_association":"NONE","original_position":7,"position":7,"subject_type":"line"},{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150822","pull_request_review_id":3719783923,"id":2739150822,"node_id":"PRRC_kwDOQb6kR86jRB_m","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:\n+ const out: AgentMessage[] = [];\n+ let changed = false;\n+\n+ for (const msg of messages) {\n+ if (msg.role !== \"assistant\" || !Array.isArray(msg.content)) {\n+ out.push(msg);\n+ continue;\n+ }\n+\n+ const content = msg.content;\n+ const nextContent: any[] = [];\n+ let msgChanged = false;\n+\n+ for (const block of content) {\n+ if (\n+ block &&\n+ typeof block === \"object\" &&\n+ (block.type === \"toolUse\" || block.type === \"toolCall\" || block.type === \"functionCall\")\n+ ) {\n+ // Check if input is a string that needs parsing\n+ if (typeof (block as any).input === \"string\") {\n+ try {\n+ JSON.parse((block as any).input);\n+ nextContent.push(block);","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"The function validates and discards valid JSON strings but doesn't parse them. When `input` is a string containing valid JSON (line 85), the code simply pushes the block unchanged. However, if `input` should always be an object (not a string), then valid JSON strings should also be parsed and converted to objects for consistency. Clarify the expected behavior: should valid JSON strings be preserved as-is, or should they also be parsed into objects? The current behavior creates inconsistency where some inputs are objects and some are JSON strings.\n```suggestion\n const parsedInput = JSON.parse((block as any).input);\n nextContent.push({\n ...block,\n input: parsedInput,\n });\n msgChanged = true;\n```","created_at":"2026-01-29T00:08:39Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150822","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150822"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150822"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150822/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":85,"original_start_line":85,"start_side":"RIGHT","line":86,"original_line":86,"side":"RIGHT","author_association":"NONE","original_position":31,"position":31,"subject_type":"line"},{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150828","pull_request_review_id":3719783923,"id":2739150828,"node_id":"PRRC_kwDOQb6kR86jRB_s","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:\n+ const out: AgentMessage[] = [];\n+ let changed = false;\n+\n+ for (const msg of messages) {\n+ if (msg.role !== \"assistant\" || !Array.isArray(msg.content)) {\n+ out.push(msg);\n+ continue;\n+ }\n+\n+ const content = msg.content;\n+ const nextContent: any[] = [];\n+ let msgChanged = false;\n+\n+ for (const block of content) {\n+ if (\n+ block &&\n+ typeof block === \"object\" &&\n+ (block.type === \"toolUse\" || block.type === \"toolCall\" || block.type === \"functionCall\")\n+ ) {\n+ // Check if input is a string that needs parsing\n+ if (typeof (block as any).input === \"string\") {\n+ try {\n+ JSON.parse((block as any).input);\n+ nextContent.push(block);\n+ } catch {\n+ // Invalid JSON found in tool args.\n+ // Replace with empty object to prevent downstream crashes.\n+ nextContent.push({\n+ ...block,\n+ input: {},\n+ _sanitized: true,\n+ _originalInput: (block as any).input,\n+ });\n+ msgChanged = true;\n+ }\n+ } else {\n+ nextContent.push(block);\n+ }\n+ } else {\n+ nextContent.push(block);\n+ }\n+ }\n+\n+ if (msgChanged) {\n+ out.push({\n+ ...msg,\n+ content: nextContent,\n+ } as AgentMessage);\n+ changed = true;\n+ } else {\n+ out.push(msg);\n+ }\n+ }\n+\n+ return changed ? out : messages;\n+}","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"The function doesn't return any report or metadata about what was sanitized, unlike `repairToolUseResultPairing` which returns a `ToolUseRepairReport` with details about changes made. Consider returning a report object that includes information such as the number of sanitized blocks and which tool types were affected. This would help with debugging, monitoring, and understanding the extent of data corruption in sessions. Alternatively, add inline logging to track sanitization events.","created_at":"2026-01-29T00:08:39Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150828","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150828"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150828"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150828/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":59,"original_start_line":59,"start_side":"RIGHT","line":118,"original_line":118,"side":"RIGHT","author_association":"NONE","original_position":63,"position":63,"subject_type":"line"},{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150831","pull_request_review_id":3719783923,"id":2739150831,"node_id":"PRRC_kwDOQb6kR86jRB_v","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:\n+ const out: AgentMessage[] = [];\n+ let changed = false;\n+\n+ for (const msg of messages) {\n+ if (msg.role !== \"assistant\" || !Array.isArray(msg.content)) {\n+ out.push(msg);\n+ continue;\n+ }\n+\n+ const content = msg.content;\n+ const nextContent: any[] = [];\n+ let msgChanged = false;\n+\n+ for (const block of content) {\n+ if (\n+ block &&\n+ typeof block === \"object\" &&\n+ (block.type === \"toolUse\" || block.type === \"toolCall\" || block.type === \"functionCall\")\n+ ) {\n+ // Check if input is a string that needs parsing\n+ if (typeof (block as any).input === \"string\") {\n+ try {\n+ JSON.parse((block as any).input);\n+ nextContent.push(block);\n+ } catch {\n+ // Invalid JSON found in tool args.\n+ // Replace with empty object to prevent downstream crashes.\n+ nextContent.push({\n+ ...block,\n+ input: {},\n+ _sanitized: true,\n+ _originalInput: (block as any).input,\n+ });\n+ msgChanged = true;\n+ }\n+ } else {\n+ nextContent.push(block);\n+ }\n+ } else {\n+ nextContent.push(block);\n+ }\n+ }\n+\n+ if (msgChanged) {\n+ out.push({\n+ ...msg,\n+ content: nextContent,\n+ } as AgentMessage);\n+ changed = true;\n+ } else {\n+ out.push(msg);\n+ }\n+ }\n+\n+ return changed ? out : messages;\n+}","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"The `sanitizeToolUseArgs` function lacks test coverage. The existing test file only tests `sanitizeToolUseResultPairing`, but does not directly test the new `sanitizeToolUseArgs` function. Add tests that verify:\n1. Valid JSON strings in `input` fields are preserved\n2. Invalid JSON strings in `input` fields are replaced with `{}`\n3. Object values in `input` fields are preserved\n4. The `_sanitized` and `_originalInput` metadata fields are correctly set when sanitization occurs\n5. Messages without tool blocks are left unchanged","created_at":"2026-01-29T00:08:40Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150831","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150831"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150831"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150831/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":59,"original_start_line":59,"start_side":"RIGHT","line":118,"original_line":118,"side":"RIGHT","author_association":"NONE","original_position":63,"position":63,"subject_type":"line"},{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150839","pull_request_review_id":3719783923,"id":2739150839,"node_id":"PRRC_kwDOQb6kR86jRB_3","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:\n+ const out: AgentMessage[] = [];\n+ let changed = false;\n+\n+ for (const msg of messages) {\n+ if (msg.role !== \"assistant\" || !Array.isArray(msg.content)) {\n+ out.push(msg);\n+ continue;\n+ }\n+\n+ const content = msg.content;\n+ const nextContent: any[] = [];\n+ let msgChanged = false;\n+\n+ for (const block of content) {\n+ if (\n+ block &&\n+ typeof block === \"object\" &&\n+ (block.type === \"toolUse\" || block.type === \"toolCall\" || block.type === \"functionCall\")\n+ ) {\n+ // Check if input is a string that needs parsing\n+ if (typeof (block as any).input === \"string\") {\n+ try {\n+ JSON.parse((block as any).input);\n+ nextContent.push(block);\n+ } catch {\n+ // Invalid JSON found in tool args.\n+ // Replace with empty object to prevent downstream crashes.\n+ nextContent.push({\n+ ...block,\n+ input: {},\n+ _sanitized: true,\n+ _originalInput: (block as any).input,\n+ });\n+ msgChanged = true;\n+ }","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"Silent data loss occurs when malformed JSON is replaced with an empty object. When the sanitization logic detects and replaces invalid JSON in tool arguments, it stores the original input in `_originalInput` but doesn't log this potentially important information. Consider adding a warning log similar to patterns found elsewhere in the codebase (e.g., in `compaction.ts`, `model-catalog.ts`) to aid debugging when sessions are repaired. The log should include the tool name and a sample of the malformed input to help trace the root cause of the corruption.","created_at":"2026-01-29T00:08:40Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150839","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150839"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150839"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150839/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":87,"original_start_line":87,"start_side":"RIGHT","line":97,"original_line":97,"side":"RIGHT","author_association":"NONE","original_position":42,"position":42,"subject_type":"line"},{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150842","pull_request_review_id":3719783923,"id":2739150842,"node_id":"PRRC_kwDOQb6kR86jRB_6","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:\n+ const out: AgentMessage[] = [];\n+ let changed = false;\n+\n+ for (const msg of messages) {\n+ if (msg.role !== \"assistant\" || !Array.isArray(msg.content)) {\n+ out.push(msg);\n+ continue;\n+ }\n+\n+ const content = msg.content;\n+ const nextContent: any[] = [];\n+ let msgChanged = false;\n+\n+ for (const block of content) {\n+ if (\n+ block &&\n+ typeof block === \"object\" &&\n+ (block.type === \"toolUse\" || block.type === \"toolCall\" || block.type === \"functionCall\")\n+ ) {\n+ // Check if input is a string that needs parsing\n+ if (typeof (block as any).input === \"string\") {\n+ try {\n+ JSON.parse((block as any).input);\n+ nextContent.push(block);\n+ } catch {\n+ // Invalid JSON found in tool args.\n+ // Replace with empty object to prevent downstream crashes.\n+ nextContent.push({\n+ ...block,\n+ input: {},\n+ _sanitized: true,\n+ _originalInput: (block as any).input,\n+ });\n+ msgChanged = true;\n+ }\n+ } else {\n+ nextContent.push(block);\n+ }","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"The function only sanitizes the `input` field for tool use blocks, but the existing tests use `arguments` as the field name (see lines 11-12, 38, 65 in session-transcript-repair.test.ts). This suggests there may be inconsistency in the field naming across different tool block types. Verify whether tool blocks can use both `input` and `arguments` field names, and if so, ensure the sanitization logic handles both. If they are mutually exclusive based on the block type, add a comment explaining this distinction.","created_at":"2026-01-29T00:08:40Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150842","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150842"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150842"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150842/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":83,"original_start_line":83,"start_side":"RIGHT","line":100,"original_line":100,"side":"RIGHT","author_association":"NONE","original_position":45,"position":45,"subject_type":"line"},{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150844","pull_request_review_id":3719783923,"id":2739150844,"node_id":"PRRC_kwDOQb6kR86jRB_8","diff_hunk":"@@ -56,8 +56,70 @@ function makeMissingToolResult(params: {\n \n export { makeMissingToolResult };\n \n+export function sanitizeToolUseArgs(messages: AgentMessage[]): AgentMessage[] {\n+ // Deep clone to avoid mutating the input unless necessary?\n+ // Actually, we can mutate in place effectively or clone messages that need change.\n+ // For safety against corrupt JSON rendering the whole session unusable:\n+ const out: AgentMessage[] = [];\n+ let changed = false;\n+\n+ for (const msg of messages) {\n+ if (msg.role !== \"assistant\" || !Array.isArray(msg.content)) {\n+ out.push(msg);\n+ continue;\n+ }\n+\n+ const content = msg.content;\n+ const nextContent: any[] = [];\n+ let msgChanged = false;\n+\n+ for (const block of content) {\n+ if (\n+ block &&\n+ typeof block === \"object\" &&\n+ (block.type === \"toolUse\" || block.type === \"toolCall\" || block.type === \"functionCall\")\n+ ) {\n+ // Check if input is a string that needs parsing\n+ if (typeof (block as any).input === \"string\") {\n+ try {\n+ JSON.parse((block as any).input);\n+ nextContent.push(block);\n+ } catch {\n+ // Invalid JSON found in tool args.\n+ // Replace with empty object to prevent downstream crashes.\n+ nextContent.push({\n+ ...block,\n+ input: {},\n+ _sanitized: true,\n+ _originalInput: (block as any).input,","path":"src/agents/session-transcript-repair.ts","commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","original_commit_id":"c4b2b359267ba4bf48c9851e5eeed86e037d2c4a","user":{"login":"Copilot","id":175728472,"node_id":"BOT_kgDOCnlnWA","avatar_url":"https://avatars.githubusercontent.com/in/946600?v=4","gravatar_id":"","url":"https://api.github.com/users/Copilot","html_url":"https://github.com/apps/copilot-pull-request-reviewer","followers_url":"https://api.github.com/users/Copilot/followers","following_url":"https://api.github.com/users/Copilot/following{/other_user}","gists_url":"https://api.github.com/users/Copilot/gists{/gist_id}","starred_url":"https://api.github.com/users/Copilot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Copilot/subscriptions","organizations_url":"https://api.github.com/users/Copilot/orgs","repos_url":"https://api.github.com/users/Copilot/repos","events_url":"https://api.github.com/users/Copilot/events{/privacy}","received_events_url":"https://api.github.com/users/Copilot/received_events","type":"Bot","user_view_type":"public","site_admin":false},"body":"Using `(block as any).input` bypasses TypeScript's type checking. The code would be more maintainable and safer with proper type guards or typed access. Consider defining a proper type for tool blocks or using a type guard function to check for the presence of the `input` field before accessing it. This approach would make the code more self-documenting and catch potential issues at compile time.","created_at":"2026-01-29T00:08:40Z","updated_at":"2026-01-29T00:08:41Z","html_url":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150844","pull_request_url":"https://api.github.com/repos/moltbot/moltbot/pulls/3647","_links":{"self":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150844"},"html":{"href":"https://github.com/moltbot/moltbot/pull/3647#discussion_r2739150844"},"pull_request":{"href":"https://api.github.com/repos/moltbot/moltbot/pulls/3647"}},"reactions":{"url":"https://api.github.com/repos/moltbot/moltbot/pulls/comments/2739150844/reactions","total_count":0,"+1":0,"-1":0,"laugh":0,"hooray":0,"confused":0,"heart":0,"rocket":0,"eyes":0},"start_line":83,"original_start_line":83,"start_side":"RIGHT","line":94,"original_line":94,"side":"RIGHT","author_association":"NONE","original_position":39,"position":39,"subject_type":"line"}]