Skip to content

Commit 656b474

Browse files
authored
Merge pull request #2033 from Kilo-Org/christiaan/simple-read-tool-2
Simple read file tool
2 parents ed44853 + 9798491 commit 656b474

File tree

9 files changed

+404
-4
lines changed

9 files changed

+404
-4
lines changed

.changeset/silent-plums-pay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"kilo-code": patch
3+
---
4+
5+
Thanks @daniel-lxs! - Added a single-file read tool that works better with Sonic than the default multi-file read tool.

packages/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export * from "./message.js"
1212
export * from "./mode.js"
1313
export * from "./model.js"
1414
export * from "./provider-settings.js"
15+
export * from "./single-file-read-models.js"
1516
export * from "./task.js"
1617
export * from "./todo.js"
1718
export * from "./telemetry.js"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Configuration for models that should use simplified single-file read_file tool
3+
* These models will use the simpler <read_file><path>...</path></read_file> format
4+
* instead of the more complex multi-file args format
5+
*/
6+
7+
// List of model IDs (or patterns) that should use single file reads only
8+
export const SINGLE_FILE_READ_MODELS = new Set<string>([
9+
"sonic", // kilocode_change
10+
])
11+
12+
/**
13+
* Check if a model should use single file read format
14+
* @param modelId The model ID to check
15+
* @returns true if the model should use single file reads
16+
*/
17+
export function shouldUseSingleFileRead(modelId: string): boolean {
18+
// Direct match
19+
if (SINGLE_FILE_READ_MODELS.has(modelId)) {
20+
return true
21+
}
22+
23+
// Pattern matching for model families
24+
// Check if model ID starts with any configured pattern
25+
// Using Array.from for compatibility with older TypeScript targets
26+
const patterns = Array.from(SINGLE_FILE_READ_MODELS)
27+
for (const pattern of patterns) {
28+
if (pattern.endsWith("*") && modelId.startsWith(pattern.slice(0, -1))) {
29+
return true
30+
}
31+
}
32+
33+
return false
34+
}

src/core/assistant-message/presentAssistantMessage.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import type { ToolParamName, ToolResponse } from "../../shared/tools"
1010
import { fetchInstructionsTool } from "../tools/fetchInstructionsTool"
1111
import { listFilesTool } from "../tools/listFilesTool"
1212
import { getReadFileToolDescription, readFileTool } from "../tools/readFileTool"
13+
import { getSimpleReadFileToolDescription, simpleReadFileTool } from "../tools/simpleReadFileTool"
14+
import { shouldUseSingleFileRead } from "@roo-code/types"
1315
import { writeToFileTool } from "../tools/writeToFileTool"
1416
import { applyDiffTool } from "../tools/multiApplyDiffTool"
1517
import { insertContentTool } from "../tools/insertContentTool"
@@ -162,7 +164,13 @@ export async function presentAssistantMessage(cline: Task, recursionDepth: numbe
162164
case "execute_command":
163165
return `[${block.name} for '${block.params.command}']`
164166
case "read_file":
165-
return getReadFileToolDescription(block.name, block.params)
167+
// Check if this model should use the simplified description
168+
const modelId = cline.api.getModel().id
169+
if (shouldUseSingleFileRead(modelId)) {
170+
return getSimpleReadFileToolDescription(block.name, block.params)
171+
} else {
172+
return getReadFileToolDescription(block.name, block.params)
173+
}
166174
case "fetch_instructions":
167175
return `[${block.name} for '${block.params.task}']`
168176
case "write_to_file":
@@ -478,8 +486,20 @@ export async function presentAssistantMessage(cline: Task, recursionDepth: numbe
478486
break
479487
// kilocode_change end
480488
case "read_file":
481-
await readFileTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag)
482-
489+
// Check if this model should use the simplified single-file read tool
490+
const modelId = cline.api.getModel().id
491+
if (shouldUseSingleFileRead(modelId)) {
492+
await simpleReadFileTool(
493+
cline,
494+
block,
495+
askApproval,
496+
handleError,
497+
pushToolResult,
498+
removeClosingTag,
499+
)
500+
} else {
501+
await readFileTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag)
502+
}
483503
break
484504
case "fetch_instructions":
485505
await fetchInstructionsTool(cline, block, askApproval, handleError, pushToolResult)

src/core/prompts/system.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ async function generatePrompt(
6868
partialReadsEnabled?: boolean,
6969
settings?: SystemPromptSettings,
7070
todoList?: TodoItem[],
71+
modelId?: string,
7172
): Promise<string> {
7273
if (!context) {
7374
throw new Error("Extension context is required for generating system prompt")
@@ -113,6 +114,7 @@ ${getToolDescriptionsForMode(
113114
partialReadsEnabled,
114115
settings,
115116
enableMcpServerCreation,
117+
modelId,
116118
)}
117119
118120
${getToolUseGuidelinesSection(codeIndexManager)}
@@ -159,6 +161,7 @@ export const SYSTEM_PROMPT = async (
159161
partialReadsEnabled?: boolean,
160162
settings?: SystemPromptSettings,
161163
todoList?: TodoItem[],
164+
modelId?: string,
162165
): Promise<string> => {
163166
if (!context) {
164167
throw new Error("Extension context is required for generating system prompt")
@@ -233,5 +236,6 @@ ${getMorphInstructions(experiments) /* kilocode_change: Morph fast apply */}${cu
233236
partialReadsEnabled,
234237
settings,
235238
todoList,
239+
modelId,
236240
)
237241
}

src/core/prompts/tools/index.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import { Mode, getModeConfig, isToolAllowedForMode, getGroupName } from "../../.
77
import { ToolArgs } from "./types"
88
import { getExecuteCommandDescription } from "./execute-command"
99
import { getReadFileDescription } from "./read-file"
10+
import { getSimpleReadFileDescription } from "./simple-read-file"
1011
import { getFetchInstructionsDescription } from "./fetch-instructions"
12+
import { shouldUseSingleFileRead } from "@roo-code/types"
1113
import { getWriteToFileDescription } from "./write-to-file"
1214
import { getSearchFilesDescription } from "./search-files"
1315
import { getListFilesDescription } from "./list-files"
@@ -29,7 +31,14 @@ import { CodeIndexManager } from "../../../services/code-index/manager"
2931
// Map of tool names to their description functions
3032
const toolDescriptionMap: Record<string, (args: ToolArgs) => string | undefined> = {
3133
execute_command: (args) => getExecuteCommandDescription(args),
32-
read_file: (args) => getReadFileDescription(args),
34+
read_file: (args) => {
35+
// Check if the current model should use the simplified read_file tool
36+
const modelId = args.settings?.modelId
37+
if (modelId && shouldUseSingleFileRead(modelId)) {
38+
return getSimpleReadFileDescription(args)
39+
}
40+
return getReadFileDescription(args)
41+
},
3342
fetch_instructions: (args) => getFetchInstructionsDescription(args.settings?.enableMcpServerCreation),
3443
write_to_file: (args) => getWriteToFileDescription(args),
3544
search_files: (args) => getSearchFilesDescription(args),
@@ -64,6 +73,7 @@ export function getToolDescriptionsForMode(
6473
partialReadsEnabled?: boolean,
6574
settings?: Record<string, any>,
6675
enableMcpServerCreation?: boolean,
76+
modelId?: string,
6777
): string {
6878
const config = getModeConfig(mode, customModes)
6979
const args: ToolArgs = {
@@ -76,6 +86,7 @@ export function getToolDescriptionsForMode(
7686
settings: {
7787
...settings,
7888
enableMcpServerCreation,
89+
modelId,
7990
},
8091
experiments,
8192
}
@@ -145,6 +156,7 @@ export function getToolDescriptionsForMode(
145156
export {
146157
getExecuteCommandDescription,
147158
getReadFileDescription,
159+
getSimpleReadFileDescription,
148160
getFetchInstructionsDescription,
149161
getWriteToFileDescription,
150162
getSearchFilesDescription,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { ToolArgs } from "./types"
2+
3+
/**
4+
* Generate a simplified read_file tool description for models that only support single file reads
5+
* Uses the simpler format: <read_file><path>file/path.ext</path></read_file>
6+
*/
7+
export function getSimpleReadFileDescription(args: ToolArgs): string {
8+
return `## read_file
9+
Description: Request to read the contents of a file. The tool outputs line-numbered content (e.g. "1 | const x = 1") for easy reference when discussing code.
10+
11+
Parameters:
12+
- path: (required) File path (relative to workspace directory ${args.cwd})
13+
14+
Usage:
15+
<read_file>
16+
<path>path/to/file</path>
17+
</read_file>
18+
19+
Examples:
20+
21+
1. Reading a TypeScript file:
22+
<read_file>
23+
<path>src/app.ts</path>
24+
</read_file>
25+
26+
2. Reading a configuration file:
27+
<read_file>
28+
<path>config.json</path>
29+
</read_file>
30+
31+
3. Reading a markdown file:
32+
<read_file>
33+
<path>README.md</path>
34+
</read_file>`
35+
}

src/core/task/Task.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,8 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
22742274
todoListEnabled: apiConfiguration?.todoListEnabled ?? true,
22752275
useAgentRules: vscode.workspace.getConfiguration("kilo-code").get<boolean>("useAgentRules") ?? true,
22762276
},
2277+
undefined, // todoList
2278+
this.api.getModel().id,
22772279
)
22782280
})()
22792281
}

0 commit comments

Comments
 (0)