Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cli-max-concurrent-file-reads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kilocode/cli": patch
---

Add maxConcurrentFileReads configuration support to CLI with documentation
14 changes: 14 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,20 @@ Autonomous mode respects your auto-approval configuration. Edit your config file
- `retry`: Auto-approve API retry requests
- `todo`: Auto-approve todo list updates

#### Context Management Configuration

You can also configure context management settings:

```json
{
"maxConcurrentFileReads": 5
}
```

**Configuration Options:**

- `maxConcurrentFileReads`: Maximum number of files that can be read in a single `read_file` request (default: 5, minimum: 1). The AI will be instructed about this limit and requests exceeding it will be rejected. Set to `1` to disable multi-file reads.

#### Command Approval Patterns

The `execute.allowed` and `execute.denied` lists support hierarchical pattern matching:
Expand Down
34 changes: 34 additions & 0 deletions cli/src/config/__tests__/mapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,38 @@ describe("mapConfigToExtensionState", () => {
expect(state.mode).toBe("architect")
})
})

describe("context management settings mapping", () => {
it("should use default maxConcurrentFileReads of 5 when not specified", () => {
const config: CLIConfig = {
...baseConfig,
}

const state = mapConfigToExtensionState(config)

expect(state.maxConcurrentFileReads).toBe(5)
})

it("should map custom maxConcurrentFileReads value", () => {
const config: CLIConfig = {
...baseConfig,
maxConcurrentFileReads: 10,
}

const state = mapConfigToExtensionState(config)

expect(state.maxConcurrentFileReads).toBe(10)
})

it("should map maxConcurrentFileReads of 1 for single file reads only", () => {
const config: CLIConfig = {
...baseConfig,
maxConcurrentFileReads: 1,
}

const state = mapConfigToExtensionState(config)

expect(state.maxConcurrentFileReads).toBe(1)
})
})
})
3 changes: 3 additions & 0 deletions cli/src/config/mapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CLIConfig, ProviderConfig } from "./types.js"
import type { ExtensionState, ProviderSettings, ProviderSettingsEntry } from "../types/messages.js"
import { logs } from "../services/logs.js"
import { DEFAULT_MAX_CONCURRENT_FILE_READS } from "@kilocode/core-schemas"

export function mapConfigToExtensionState(
config: CLIConfig,
Expand Down Expand Up @@ -69,6 +70,8 @@ export function mapConfigToExtensionState(
alwaysAllowFollowupQuestions: autoApprovalEnabled && (autoApproval?.question?.enabled ?? false),
followupAutoApproveTimeoutMs: (autoApproval?.question?.timeout ?? 60) * 1000,
alwaysAllowUpdateTodoList: autoApprovalEnabled && (autoApproval?.todo?.enabled ?? false),
// Context management settings
maxConcurrentFileReads: config.maxConcurrentFileReads ?? DEFAULT_MAX_CONCURRENT_FILE_READS,
}
} catch (error) {
logs.error("Failed to map config to extension state", "ConfigMapper", { error })
Expand Down
6 changes: 6 additions & 0 deletions cli/src/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@
}
}
}
},
"maxConcurrentFileReads": {
"type": "number",
"minimum": 1,
"default": 5,
"description": "Maximum number of files that can be read in a single read_file request. The AI will be instructed about this limit and requests exceeding it will be rejected."
}
},
"definitions": {
Expand Down
17 changes: 17 additions & 0 deletions cli/src/host/ExtensionHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,23 @@ export class ExtensionHost extends EventEmitter {
autoApprovalSettings.alwaysAllowUpdateTodoList = configState.alwaysAllowUpdateTodoList
}

// Context management settings
const contextSettings: Record<string, unknown> = {}
if (configState.maxConcurrentFileReads !== undefined) {
contextSettings.maxConcurrentFileReads = configState.maxConcurrentFileReads
}

// Send context management settings if any are present
if (Object.keys(contextSettings).length > 0) {
await this.sendWebviewMessage({
type: "updateSettings",
updatedSettings: contextSettings,
})
logs.debug("Context management settings synchronized to extension", "ExtensionHost", {
settings: Object.keys(contextSettings),
})
}

// Send auto-approval settings if any are present
if (Object.keys(autoApprovalSettings).length > 0) {
await this.sendWebviewMessage({
Expand Down
7 changes: 7 additions & 0 deletions packages/core-schemas/src/config/cli-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { providerConfigSchema } from "./provider.js"
import { autoApprovalConfigSchema } from "./auto-approval.js"
import { themeSchema, themeIdSchema } from "../theme/theme.js"

/**
* Default maximum number of files that can be read in a single read_file request.
* This is a CLI-specific constant that matches the extension's default value.
*/
export const DEFAULT_MAX_CONCURRENT_FILE_READS = 5

/**
* CLI configuration schema
*/
Expand All @@ -15,6 +21,7 @@ export const cliConfigSchema = z.object({
autoApproval: autoApprovalConfigSchema.optional(),
theme: themeIdSchema.optional(),
customThemes: z.record(themeSchema).optional(),
maxConcurrentFileReads: z.number().min(1).default(DEFAULT_MAX_CONCURRENT_FILE_READS).optional(),
})

// Inferred type
Expand Down