|
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | 5 |
|
6 | 6 | import vscode from 'vscode'; |
| 7 | +import { parseSessionLogs, parseToolCallDetails } from '../../common/sessionParsing'; |
7 | 8 | import { Repository } from '../api/api'; |
8 | 9 | import { COPILOT_LOGINS, CopilotPRStatus } from '../common/copilot'; |
9 | 10 | import { commands } from '../common/executeCommands'; |
@@ -900,49 +901,32 @@ export class CopilotRemoteAgentManager extends Disposable { |
900 | 901 | toolPart.isError = false; |
901 | 902 | toolPart.isConfirmed = true; |
902 | 903 |
|
903 | | - // Parse tool arguments and set tool-specific metadata following sessionView.tsx patterns |
| 904 | + // Parse tool arguments and set tool-specific metadata using shared utility |
904 | 905 | const name = toolCall.function.name; |
905 | 906 | const content = delta.content || ''; |
906 | 907 |
|
907 | 908 | try { |
908 | | - const args = toolCall.function.arguments ? JSON.parse(toolCall.function.arguments) : {}; |
909 | | - |
910 | | - if (name === 'str_replace_editor') { |
911 | | - if (args.command === 'view') { |
912 | | - toolPart.toolName = args.path ? `View ${this.toFileLabel(args.path)}` : 'View repository'; |
913 | | - toolPart.invocationMessage = `View ${args.path}`; |
914 | | - toolPart.pastTenseMessage = `View ${args.path}`; |
915 | | - } else { |
916 | | - toolPart.toolName = 'Edit'; |
917 | | - toolPart.invocationMessage = `Edit: ${args.path}`; |
918 | | - toolPart.pastTenseMessage = `Edit: ${args.path}`; |
919 | | - } |
920 | | - } else if (name === 'think') { |
921 | | - toolPart.toolName = 'Thought'; |
922 | | - toolPart.invocationMessage = content; |
923 | | - } else if (name === 'report_progress') { |
924 | | - toolPart.toolName = 'Progress Update'; |
925 | | - toolPart.invocationMessage = args.prDescription || content; |
926 | | - if (args.commitMessage) { |
927 | | - toolPart.originMessage = `Commit: ${args.commitMessage}`; |
928 | | - } |
929 | | - } else if (name === 'bash') { |
930 | | - toolPart.toolName = 'Run Bash command'; |
931 | | - const command = args.command ? `$ ${args.command}` : undefined; |
932 | | - const bashContent = [command, content].filter(Boolean).join('\n'); |
933 | | - toolPart.invocationMessage = new vscode.MarkdownString(`\`\`\`bash\n${bashContent}\n\`\`\``); |
934 | | - |
935 | | - // Use the terminal-specific data for bash commands |
936 | | - if (args.command) { |
937 | | - toolPart.toolSpecificData = { |
938 | | - command: args.command, |
939 | | - language: 'bash' |
940 | | - }; |
941 | | - } |
| 909 | + const toolDetails = parseToolCallDetails(toolCall, content); |
| 910 | + |
| 911 | + toolPart.toolName = toolDetails.toolName; |
| 912 | + |
| 913 | + // Handle different invocation message types |
| 914 | + if (name === 'bash') { |
| 915 | + toolPart.invocationMessage = new vscode.MarkdownString(`\`\`\`bash\n${toolDetails.invocationMessage}\n\`\`\``); |
942 | 916 | } else { |
943 | | - // Unknown tool type |
944 | | - toolPart.toolName = name || 'unknown'; |
945 | | - toolPart.invocationMessage = new vscode.MarkdownString(`\`\`\`plaintext\n${content}\n\`\`\``); |
| 917 | + toolPart.invocationMessage = toolDetails.invocationMessage; |
| 918 | + } |
| 919 | + |
| 920 | + if (toolDetails.pastTenseMessage) { |
| 921 | + toolPart.pastTenseMessage = toolDetails.pastTenseMessage; |
| 922 | + } |
| 923 | + |
| 924 | + if (toolDetails.originMessage) { |
| 925 | + toolPart.originMessage = toolDetails.originMessage; |
| 926 | + } |
| 927 | + |
| 928 | + if (toolDetails.toolSpecificData) { |
| 929 | + toolPart.toolSpecificData = toolDetails.toolSpecificData; |
946 | 930 | } |
947 | 931 | } catch (error) { |
948 | 932 | // Fallback for parsing errors |
@@ -987,111 +971,4 @@ export class CopilotRemoteAgentManager extends Disposable { |
987 | 971 | return []; |
988 | 972 | } |
989 | 973 | } |
990 | | - |
991 | | - /** |
992 | | - * Helper method to convert absolute file paths to relative labels |
993 | | - * Following the pattern from sessionView.tsx |
994 | | - */ |
995 | | - private toFileLabel(file: string): string { |
996 | | - // File paths are absolute and look like: `/home/runner/work/repo/repo/<path>` |
997 | | - const parts = file.split('/'); |
998 | | - return parts.slice(6).join('/'); |
999 | | - } |
1000 | | - |
1001 | | - /** |
1002 | | - * Helper method to get language for a file based on its extension |
1003 | | - * Following the pattern from sessionView.tsx |
1004 | | - */ |
1005 | | - private getLanguageForFile(filePath: string): string { |
1006 | | - const extension = filePath.split('.').pop()?.toLowerCase(); |
1007 | | - |
1008 | | - // Common language mappings |
1009 | | - const languageMap: { [ext: string]: string } = { |
1010 | | - 'ts': 'typescript', |
1011 | | - 'tsx': 'tsx', |
1012 | | - 'js': 'javascript', |
1013 | | - 'jsx': 'jsx', |
1014 | | - 'py': 'python', |
1015 | | - 'json': 'json', |
1016 | | - 'md': 'markdown', |
1017 | | - 'yml': 'yaml', |
1018 | | - 'yaml': 'yaml', |
1019 | | - 'xml': 'xml', |
1020 | | - 'html': 'html', |
1021 | | - 'css': 'css', |
1022 | | - 'scss': 'scss', |
1023 | | - 'less': 'less', |
1024 | | - 'sh': 'bash', |
1025 | | - 'bash': 'bash', |
1026 | | - 'zsh': 'bash', |
1027 | | - 'fish': 'bash', |
1028 | | - 'ps1': 'powershell', |
1029 | | - 'sql': 'sql', |
1030 | | - 'go': 'go', |
1031 | | - 'rs': 'rust', |
1032 | | - 'cpp': 'cpp', |
1033 | | - 'c': 'c', |
1034 | | - 'h': 'c', |
1035 | | - 'hpp': 'cpp', |
1036 | | - 'java': 'java', |
1037 | | - 'kt': 'kotlin', |
1038 | | - 'swift': 'swift', |
1039 | | - 'rb': 'ruby', |
1040 | | - 'php': 'php', |
1041 | | - 'cs': 'csharp', |
1042 | | - 'fs': 'fsharp', |
1043 | | - 'vb': 'vb', |
1044 | | - 'r': 'r', |
1045 | | - 'scala': 'scala', |
1046 | | - 'clj': 'clojure', |
1047 | | - 'elm': 'elm', |
1048 | | - 'dart': 'dart', |
1049 | | - 'lua': 'lua', |
1050 | | - 'perl': 'perl', |
1051 | | - 'vim': 'vim' |
1052 | | - }; |
1053 | | - |
1054 | | - return extension ? languageMap[extension] || 'plaintext' : 'plaintext'; |
1055 | | - } |
1056 | | -} |
1057 | | - |
1058 | | -function parseSessionLogs(rawText: string): SessionResponseLogChunk[] { |
1059 | | - const parts = rawText |
1060 | | - .split(/\r?\n/) |
1061 | | - .filter(part => part.startsWith('data: ')) |
1062 | | - .map(part => part.slice('data: '.length).trim()) |
1063 | | - .map(part => JSON.parse(part)); |
1064 | | - |
1065 | | - return parts as SessionResponseLogChunk[]; |
1066 | | -} |
1067 | | - |
1068 | | -export interface SessionResponseLogChunk { |
1069 | | - choices: Array<{ |
1070 | | - finish_reason: string; |
1071 | | - delta: { |
1072 | | - content?: string; |
1073 | | - role: string; |
1074 | | - tool_calls?: Array<{ |
1075 | | - function: { |
1076 | | - arguments: string; |
1077 | | - name: string; |
1078 | | - }; |
1079 | | - id: string; |
1080 | | - type: string; |
1081 | | - index: number; |
1082 | | - }>; |
1083 | | - }; |
1084 | | - }>; |
1085 | | - created: number; |
1086 | | - id: string; |
1087 | | - usage: { |
1088 | | - completion_tokens: number; |
1089 | | - prompt_tokens: number; |
1090 | | - prompt_tokens_details: { |
1091 | | - cached_tokens: number; |
1092 | | - }; |
1093 | | - total_tokens: number; |
1094 | | - }; |
1095 | | - model: string; |
1096 | | - object: string; |
1097 | 974 | } |
0 commit comments