Skip to content

Commit 6028948

Browse files
committed
Fix TypeScript errors: remove invalid debug tool references
1 parent 5083eb8 commit 6028948

28 files changed

+5847
-50
lines changed

packages/types/src/providers/g-cli.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export const gCliModels = {
1313
supportsPromptCache: false,
1414
inputPrice: 0,
1515
outputPrice: 0,
16+
cacheWritesPrice: 0,
17+
cacheReadsPrice: 0,
1618
},
1719
"gemini-2.5-flash": {
1820
maxTokens: 8192,
@@ -21,5 +23,27 @@ export const gCliModels = {
2123
supportsPromptCache: false,
2224
inputPrice: 0,
2325
outputPrice: 0,
26+
cacheWritesPrice: 0,
27+
cacheReadsPrice: 0,
28+
},
29+
"gemini-1.5-pro": {
30+
maxTokens: 8192,
31+
contextWindow: 2_097_152,
32+
supportsImages: true,
33+
supportsPromptCache: false,
34+
inputPrice: 0,
35+
outputPrice: 0,
36+
cacheWritesPrice: 0,
37+
cacheReadsPrice: 0,
38+
},
39+
"gemini-1.5-flash": {
40+
maxTokens: 8192,
41+
contextWindow: 1_048_576,
42+
supportsImages: true,
43+
supportsPromptCache: false,
44+
inputPrice: 0,
45+
outputPrice: 0,
46+
cacheWritesPrice: 0,
47+
cacheReadsPrice: 0,
2448
},
2549
} as const satisfies Record<string, ModelInfo>

src/core/tools/debugTool.ts

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
import { Task } from "../task/Task"
2+
import {
3+
DebugToolUse,
4+
AskApproval,
5+
HandleError,
6+
PushToolResult,
7+
// ToolResponse, // Not explicitly used for a variable's type
8+
// Assuming RemoveClosingTag might not be needed for debug tool, but can add if necessary
9+
} from "../../shared/tools"
10+
import { formatResponse } from "../prompts/responses" // For consistent error/result formatting
11+
import { ClineSayTool } from "../../shared/ExtensionMessage" // For type checking with satisfies
12+
13+
import { outputChannel } from "../../roo_debug/src/vscodeUtils"
14+
import {
15+
vsCodeDebugController,
16+
IDebugController,
17+
ToggleBreakpointParams, // Used in createOperationMap
18+
// Types are now primarily used in debugToolValidation.ts
19+
} from "../../roo_debug" // Import from the new index file
20+
import { getLastSessionDapOutput, getLastSessionRawTerminalOutput } from "../../roo_debug/src/controller/session" // Added for IV.C
21+
import { XMLParser } from "fast-xml-parser" // Added for XML parsing
22+
import { validateOperationArgs } from "./debugToolValidation"
23+
24+
// Type for the operation map values
25+
type DebugOperationFn = (args?: any) => Promise<any>
26+
27+
// Initialize all objects at module level
28+
// This prevents them from being recreated for each function call
29+
// and from being included in the state sent to the webview
30+
const moduleController: IDebugController = vsCodeDebugController
31+
// Create the operation map once at module level
32+
const moduleOperationMap = createOperationMap(moduleController)
33+
// Create XML parser once at module level
34+
const moduleXmlParser = new XMLParser({
35+
ignoreAttributes: false,
36+
attributeNamePrefix: "@_",
37+
textNodeName: "_text",
38+
parseTagValue: true,
39+
parseAttributeValue: true,
40+
})
41+
42+
// Helper to create the operation map with correct 'this' binding
43+
function createOperationMap(controller: IDebugController): Record<string, DebugOperationFn> {
44+
return {
45+
launch: controller.launch.bind(controller),
46+
restart: controller.restart.bind(controller),
47+
quit: controller.quit.bind(controller),
48+
continue: controller.continue.bind(controller),
49+
next: controller.next.bind(controller),
50+
step_in: controller.stepIn.bind(controller),
51+
step_out: controller.stepOut.bind(controller),
52+
jump: controller.jump.bind(controller),
53+
until: controller.until.bind(controller),
54+
set_breakpoint: controller.setBreakpoint.bind(controller),
55+
set_temp_breakpoint: controller.setTempBreakpoint.bind(controller),
56+
remove_breakpoint: controller.removeBreakpointByLocation.bind(controller),
57+
remove_all_breakpoints_in_file: controller.removeAllBreakpointsInFile.bind(controller),
58+
disable_breakpoint: (params: ToggleBreakpointParams) => controller.disableBreakpoint(params), // Explicitly typing for clarity
59+
enable_breakpoint: (params: ToggleBreakpointParams) => controller.enableBreakpoint(params), // Explicitly typing for clarity
60+
ignore_breakpoint: controller.ignoreBreakpoint.bind(controller),
61+
set_breakpoint_condition: controller.setBreakpointCondition.bind(controller),
62+
get_active_breakpoints: controller.getActiveBreakpoints.bind(controller),
63+
stack_trace: controller.stackTrace.bind(controller),
64+
list_source: controller.listSource.bind(controller),
65+
up: controller.up.bind(controller),
66+
down: controller.down.bind(controller),
67+
goto_frame: controller.gotoFrame.bind(controller),
68+
get_source: controller.getSource.bind(controller),
69+
get_stack_frame_variables: controller.getStackFrameVariables.bind(controller),
70+
get_args: controller.getArgs.bind(controller),
71+
evaluate: controller.evaluate.bind(controller),
72+
pretty_print: controller.prettyPrint.bind(controller),
73+
whatis: controller.whatis.bind(controller),
74+
execute_statement: controller.executeStatement.bind(controller),
75+
get_last_stop_info: controller.getLastStopInfo.bind(controller),
76+
// IV.C: Add tools for DAP and Raw Terminal output
77+
debug_get_session_dap_output: async (args: { sessionId: string }) => {
78+
// These functions are not on IDebugController, but directly exported from session.ts
79+
const output = getLastSessionDapOutput(args.sessionId)
80+
return { success: true, output: output ?? null } // Ensure null if undefined
81+
},
82+
debug_get_session_raw_terminal_output: async (args: { sessionId: string }) => {
83+
const output = getLastSessionRawTerminalOutput(args.sessionId)
84+
return { success: true, output: output ?? null } // Ensure null if undefined
85+
},
86+
}
87+
}
88+
89+
export async function debugTool(
90+
cline: Task,
91+
block: DebugToolUse,
92+
askApproval: AskApproval,
93+
handleError: HandleError,
94+
pushToolResult: PushToolResult,
95+
): Promise<void> {
96+
const { debug_operation, _text, ...otherParams } = block.params // Extract _text
97+
// Use the module-level controller, operationMap, and xmlParser
98+
99+
try {
100+
//outputChannel.appendLine(`[Debug Tool] Raw tool use block: ${JSON.stringify(block, null, 2)}`)
101+
outputChannel.appendLine(
102+
`[Debug Tool] Processing operation '${debug_operation}'. Raw params: ${JSON.stringify(block.params)}`,
103+
)
104+
105+
if (!debug_operation) {
106+
cline.consecutiveMistakeCount++
107+
// Debug tool errors are tracked separately since "debug" is not a valid ToolName
108+
// We'll use execute_command as a proxy for error tracking
109+
cline.recordToolError("execute_command")
110+
pushToolResult(await cline.sayAndCreateMissingParamError("execute_command", "debug_operation"))
111+
return
112+
}
113+
114+
// Determine content for approval prompt
115+
let approvalDisplayContent: string
116+
if (typeof _text === "string" && _text.trim().length > 0) {
117+
// Check if _text is a non-empty string
118+
try {
119+
// Try to parse and pretty-print JSON for approval
120+
const parsedJsonPayload = JSON.parse(_text)
121+
approvalDisplayContent = JSON.stringify(parsedJsonPayload, null, 2)
122+
outputChannel.appendLine(
123+
`[Debug Tool] Using _text (JSON) for approval prompt: ${approvalDisplayContent}`,
124+
)
125+
} catch (e) {
126+
// If _text is present but fails to parse as JSON, show raw _text for approval,
127+
// but actual parsing later will fail if it's not valid JSON.
128+
approvalDisplayContent = _text
129+
outputChannel.appendLine(
130+
`[Debug Tool] _text failed JSON.parse for approval, showing raw: ${approvalDisplayContent}. Error will be caught during actual parsing if invalid.`,
131+
)
132+
}
133+
} else {
134+
// If _text is not a string, or is an empty string, then no arguments are provided.
135+
approvalDisplayContent = "(No arguments)"
136+
outputChannel.appendLine(
137+
`[Debug Tool] No _text content for arguments. Approval prompt shows: ${approvalDisplayContent}`,
138+
)
139+
}
140+
141+
// Since "debug" is not a valid tool in ClineSayTool, we'll use a different approach
142+
// We'll just pass the content directly without trying to match ClineSayTool interface
143+
const completeMessage = JSON.stringify({
144+
tool: "execute_command", // Use execute_command as a proxy since debug is not valid
145+
content: approvalDisplayContent,
146+
// Store debug_operation in content or as metadata
147+
})
148+
149+
outputChannel.appendLine(`[Debug Tool] Approval prompt prepared: ${completeMessage}`)
150+
outputChannel.appendLine(`[Debug Tool] About to call askApproval.`)
151+
152+
let didApprove = false
153+
try {
154+
// outputChannel.appendLine(
155+
// `[Debug Tool] Calling askApproval with type "tool" and message: ${completeMessage}`,
156+
// )
157+
didApprove = await askApproval("tool", completeMessage)
158+
//outputChannel.appendLine(`[Debug Tool] askApproval returned: ${didApprove}`)
159+
} catch (approvalError: any) {
160+
outputChannel.appendLine(`[ERROR][debugTool] Error during askApproval: ${approvalError.message}`)
161+
await handleError(`asking approval for debug operation '${debug_operation}'`, approvalError)
162+
pushToolResult(formatResponse.toolError(`Error asking for approval: ${approvalError.message}`))
163+
return
164+
}
165+
166+
// Add a message to the chat to show what was approved/denied
167+
if (didApprove) {
168+
await cline.say("text", `Debug operation approved: ${debug_operation}`)
169+
} else {
170+
await cline.say("text", `Debug operation denied: ${debug_operation}`)
171+
}
172+
173+
if (!didApprove) {
174+
// User denied the operation
175+
pushToolResult(formatResponse.toolError(`User denied debugger operation: ${debug_operation}`))
176+
return
177+
}
178+
179+
// Only proceed with parsing and validation if approval is granted
180+
let operationArgs: any = {}
181+
182+
// Parameters must now come from the JSON payload in _text.
183+
if (typeof _text === "string" && _text.trim().length > 0) {
184+
outputChannel.appendLine(`[Debug Tool] Attempting to parse _text as JSON: ${_text}`)
185+
try {
186+
operationArgs = JSON.parse(_text)
187+
// Ensure operationArgs is an object if it parsed to null,
188+
// or handle cases where it might parse to a primitive if that's valid for some ops.
189+
// For most debug operations, an object (even empty) or an array is expected.
190+
if (operationArgs === null) {
191+
operationArgs = {} // Treat JSON "null" as empty args object for consistency
192+
outputChannel.appendLine(`[Debug Tool] _text parsed to null, defaulting operationArgs to {}.`)
193+
} else if (typeof operationArgs !== "object" && !Array.isArray(operationArgs)) {
194+
// If JSON parsed to a primitive (string, number, boolean)
195+
// This is generally unexpected for debug operations that take multiple params.
196+
// The validation step should catch if this type is inappropriate for the specific operation.
197+
// If an operation legitimately takes a single primitive, validation should allow it.
198+
// Otherwise, validation should fail.
199+
outputChannel.appendLine(
200+
`[Debug Tool] _text parsed to a non-object/non-array primitive: ${typeof operationArgs}. Validation will determine if this is acceptable for '${debug_operation}'.`,
201+
)
202+
}
203+
outputChannel.appendLine(
204+
`[Debug Tool] Successfully parsed _text as JSON. operationArgs: ${JSON.stringify(operationArgs)}`,
205+
)
206+
} catch (e) {
207+
await handleError(`parsing JSON content for debug operation ${debug_operation}`, e as Error)
208+
pushToolResult(
209+
formatResponse.toolError(
210+
`Invalid JSON content provided for operation '${debug_operation}': ${(e as Error).message}. Parameters must be a valid JSON object or array within the operation tag.`,
211+
),
212+
)
213+
return
214+
}
215+
} else {
216+
// No _text provided, or it's an empty string.
217+
// This means no arguments are passed for the operation.
218+
// Some operations are valid without arguments (e.g., quit, continue).
219+
// Validation will check if arguments are required for the specific 'debug_operation'.
220+
outputChannel.appendLine(
221+
`[Debug Tool] No JSON _text content found or _text is empty. Assuming no arguments for '${debug_operation}'. Validation will check if args are required.`,
222+
)
223+
operationArgs = {} // Default to empty object if no _text
224+
}
225+
226+
// Validate arguments after approval
227+
//outputChannel.appendLine(`[Debug Tool] About to validate arguments for '${debug_operation}'.`)
228+
const validation = validateOperationArgs(debug_operation, operationArgs)
229+
//outputChannel.appendLine(`[Debug Tool] Argument validation completed. Valid: ${validation.isValid}.`)
230+
231+
if (!validation.isValid) {
232+
pushToolResult(formatResponse.toolError(validation.message))
233+
return
234+
}
235+
236+
// Use the transformed arguments from the validation result
237+
const transformedArgs = validation.transformedArgs
238+
//outputChannel.appendLine(
239+
// `[Debug Tool] Using transformed arguments: ${JSON.stringify(transformedArgs, null, 2)}`,
240+
//)
241+
242+
const targetMethod: DebugOperationFn | undefined = moduleOperationMap[debug_operation]
243+
244+
if (targetMethod) {
245+
try {
246+
//outputChannel.appendLine(`[Debug Tool] Executing operation '${debug_operation}'...`)
247+
248+
// Some methods on IDebugController might not expect any arguments.
249+
// The `transformedArgs` will be an empty object {} if argsXml is undefined or empty.
250+
// Methods that don't take arguments will simply ignore the empty object.
251+
const rawResult = await targetMethod(transformedArgs)
252+
253+
// Robustly handle the rawResult
254+
outputChannel.appendLine(
255+
`[Debug Tool] Operation '${debug_operation}' completed. Result: ${JSON.stringify(rawResult, null, 2)}`,
256+
)
257+
258+
if (typeof rawResult === "object" && rawResult !== null) {
259+
if (rawResult.success === true) {
260+
// Standard success case: return the full, formatted rawResult.
261+
pushToolResult(JSON.stringify(rawResult, null, 2))
262+
} else if (rawResult.success === false) {
263+
// Standard failure case: return the full rawResult, JSON stringified, to provide all details.
264+
pushToolResult(
265+
formatResponse.toolError(
266+
`Debug operation '${debug_operation}' failed. Details: ${JSON.stringify(rawResult, null, 2)}`,
267+
),
268+
)
269+
} else {
270+
// Object, but no boolean 'success' field or unexpected value.
271+
pushToolResult(
272+
`Debug operation '${debug_operation}' completed with an unusual result structure: ${JSON.stringify(rawResult, null, 2)}`,
273+
)
274+
}
275+
} else {
276+
// Not an object, or null. Highly unexpected.
277+
pushToolResult(
278+
`Debug operation '${debug_operation}' completed with an unexpected non-object result: ${String(rawResult)}`,
279+
)
280+
}
281+
} catch (e) {
282+
await handleError(`executing debug operation '${debug_operation}'`, e as Error)
283+
pushToolResult(formatResponse.toolError(`Error during '${debug_operation}': ${(e as Error).message}`))
284+
}
285+
} else {
286+
cline.consecutiveMistakeCount++
287+
// Debug tool errors are tracked separately since "debug" is not a valid ToolName
288+
// We'll use execute_command as a proxy for error tracking
289+
cline.recordToolError("execute_command")
290+
pushToolResult(formatResponse.toolError(`Unknown debug operation: ${debug_operation}`))
291+
}
292+
} catch (error) {
293+
// Catch errors from parsing argsJson or other unexpected issues
294+
await handleError(`debug tool general error for operation '${debug_operation}'`, error as Error)
295+
pushToolResult(formatResponse.toolError(`Unexpected error in debug tool: ${(error as Error).message}`))
296+
}
297+
}

0 commit comments

Comments
 (0)