Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
21 changes: 21 additions & 0 deletions .changeset/agent-manager-yolo-toggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"kilo-code": minor
---

Agent Manager: Add YOLO mode toggle and session rename features

**New Features:**

- Add YOLO mode toggle button in session header to enable/disable auto-approval of operations
- Add YOLO mode indicator (⚡) in session list for sessions running in YOLO mode
- Add inline session rename functionality - click on session title to edit

**Bug Fixes:**

- Fix messages not loading when reopening Agent Manager panel (pre-existing bug)
- Fix race condition where pending session timeout could fire after provisional session was already created

**Improvements:**

- Add TypeScript types for `respondToApproval` message
- Add translations for YOLO mode and rename features in all 21 supported locales
14 changes: 14 additions & 0 deletions src/core/kilocode/agent-manager/AgentManagerProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ export class AgentManagerProvider implements vscode.Disposable {
case "agentManager.webviewReady":
this.postStateToWebview()
void this.fetchAndPostRemoteSessions()
// Load messages for the currently selected session if any
if (this.registry.selectedId) {
this.selectSession(this.registry.selectedId)
}
break
case "agentManager.startSession":
void this.handleStartSession(message)
Expand Down Expand Up @@ -299,6 +303,10 @@ export class AgentManagerProvider implements vscode.Disposable {
case "agentManager.showTerminal":
this.terminalManager.showTerminal(message.sessionId as string)
break
case "agentManager.renameSession":
this.registry.updateSessionLabel(message.sessionId as string, message.label as string)
this.postStateToWebview()
break
case "agentManager.sessionShare":
SessionManager.init()
?.shareSession(message.sessionId as string)
Expand Down Expand Up @@ -338,6 +346,7 @@ export class AgentManagerProvider implements vscode.Disposable {
const rawLabels = message.labels as string[] | undefined
const labels = rawLabels?.length === versions ? rawLabels : undefined
const parallelMode = (message.parallelMode as boolean) ?? false
const yoloMode = (message.yoloMode as boolean) ?? true // Default true for backward compat
const existingBranch = (message.existingBranch as string) ?? undefined

// Extract session configurations
Expand All @@ -348,6 +357,7 @@ export class AgentManagerProvider implements vscode.Disposable {
const config = configs[0]
await this.startAgentSession(config.prompt, {
parallelMode: config.parallelMode,
yoloMode,
labelOverride: config.label,
existingBranch: config.existingBranch,
})
Expand All @@ -364,6 +374,7 @@ export class AgentManagerProvider implements vscode.Disposable {

await this.startAgentSession(config.prompt, {
parallelMode: config.parallelMode,
yoloMode,
labelOverride: config.label,
existingBranch: config.existingBranch,
})
Expand Down Expand Up @@ -454,6 +465,7 @@ export class AgentManagerProvider implements vscode.Disposable {
prompt: string,
options?: {
parallelMode?: boolean
yoloMode?: boolean
labelOverride?: string
existingBranch?: string
},
Expand Down Expand Up @@ -509,6 +521,7 @@ export class AgentManagerProvider implements vscode.Disposable {
prompt,
{
parallelMode: options?.parallelMode,
yoloMode: options?.yoloMode,
label: options?.labelOverride,
gitUrl,
existingBranch: options?.existingBranch,
Expand Down Expand Up @@ -560,6 +573,7 @@ export class AgentManagerProvider implements vscode.Disposable {
prompt: string,
options: {
parallelMode?: boolean
yoloMode?: boolean
label?: string
gitUrl?: string
existingBranch?: string
Expand Down
21 changes: 19 additions & 2 deletions src/core/kilocode/agent-manager/AgentRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ export class AgentRegistry {
/**
* Set a pending session while waiting for CLI's session_created event
*/
public setPendingSession(prompt: string, options?: CreateSessionOptions & { gitUrl?: string }): PendingSession {
public setPendingSession(
prompt: string,
options?: CreateSessionOptions & { gitUrl?: string; yoloMode?: boolean },
): PendingSession {
const label = this.truncatePrompt(prompt)
this._pendingSession = {
prompt,
label,
startTime: Date.now(),
parallelMode: options?.parallelMode,
gitUrl: options?.gitUrl,
yoloMode: options?.yoloMode,
}
return this._pendingSession
}
Expand All @@ -53,7 +57,7 @@ export class AgentRegistry {
sessionId: string,
prompt: string,
startTime?: number,
options?: CreateSessionOptions & { labelOverride?: string; gitUrl?: string },
options?: CreateSessionOptions & { labelOverride?: string; gitUrl?: string; yoloMode?: boolean },
): AgentSession {
const label = options?.labelOverride ?? this.truncatePrompt(prompt)

Expand All @@ -67,6 +71,7 @@ export class AgentRegistry {
source: "local",
...(options?.parallelMode && { parallelMode: { enabled: true } }),
gitUrl: options?.gitUrl,
yoloMode: options?.yoloMode,
}

this.sessions.set(sessionId, session)
Expand Down Expand Up @@ -212,6 +217,18 @@ export class AgentRegistry {
return this.sessions.delete(sessionId)
}

/**
* Update a session's display label
*/
public updateSessionLabel(sessionId: string, label: string): boolean {
const session = this.sessions.get(sessionId)
if (!session) {
return false
}
session.label = label
return true
}

/**
* Rename a session from one ID to another.
* Used when upgrading a provisional session to a real session ID.
Expand Down
14 changes: 13 additions & 1 deletion src/core/kilocode/agent-manager/CliArgsBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
export interface BuildCliArgsOptions {
sessionId?: string
/**
* When true (default), adds --yolo flag to auto-approve all tool operations.
* When false, CLI will send ask messages requiring user approval via JSON-IO.
*/
yoloMode?: boolean
}

/**
Expand All @@ -10,8 +15,15 @@ export interface BuildCliArgsOptions {
export function buildCliArgs(workspace: string, prompt: string, options?: BuildCliArgsOptions): string[] {
// --json-io: enables bidirectional JSON communication via stdin/stdout
// Note: --json (without -io) exists for CI/CD read-only mode but isn't used here
const args = ["--json-io"]

// --yolo: auto-approve tool uses (file reads, writes, commands, etc.)
const args = ["--json-io", "--yolo", `--workspace=${workspace}`]
// Default to true for backward compatibility - only omit when explicitly false
if (options?.yoloMode !== false) {
args.push("--yolo")
}

args.push(`--workspace=${workspace}`)

if (options?.sessionId) {
args.push(`--session=${options.sessionId}`)
Expand Down
23 changes: 21 additions & 2 deletions src/core/kilocode/agent-manager/CliProcessHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface PendingProcessInfo {
prompt: string
startTime: number
parallelMode?: boolean
yoloMode?: boolean
desiredSessionId?: string
desiredLabel?: string
worktreeBranch?: string // Captured from welcome event before session_created
Expand Down Expand Up @@ -142,6 +143,7 @@ export class CliProcessHandler {
options:
| {
parallelMode?: boolean
yoloMode?: boolean
sessionId?: string
label?: string
gitUrl?: string
Expand Down Expand Up @@ -179,6 +181,7 @@ export class CliProcessHandler {
const pendingSession = this.registry.setPendingSession(prompt, {
parallelMode: options?.parallelMode,
gitUrl: options?.gitUrl,
yoloMode: options?.yoloMode,
})
this.debugLog(`Pending session created, waiting for CLI session_created event`)
this.callbacks.onPendingSessionChanged(pendingSession)
Expand All @@ -189,6 +192,7 @@ export class CliProcessHandler {
// and passing the worktree path as the workspace. CLI is unaware of worktrees.
const cliArgs = buildCliArgs(workspace, prompt, {
sessionId: options?.sessionId,
yoloMode: options?.yoloMode,
})
const env = this.buildEnvWithApiConfiguration(options?.apiConfiguration, options?.shellPath)

Expand Down Expand Up @@ -243,6 +247,7 @@ export class CliProcessHandler {
prompt,
startTime: Date.now(),
parallelMode: options?.parallelMode,
yoloMode: options?.yoloMode,
desiredSessionId: options?.sessionId,
desiredLabel: options?.label,
gitUrl: options?.gitUrl,
Expand Down Expand Up @@ -513,13 +518,23 @@ export class CliProcessHandler {
const provisionalId = `provisional-${Date.now()}`
this.pendingProcess.provisionalSessionId = provisionalId

const { prompt, startTime, parallelMode, desiredLabel, gitUrl, parser, worktreeBranch, worktreePath } =
this.pendingProcess
const {
prompt,
startTime,
parallelMode,
yoloMode,
desiredLabel,
gitUrl,
parser,
worktreeBranch,
worktreePath,
} = this.pendingProcess

this.registry.createSession(provisionalId, prompt, startTime, {
parallelMode,
labelOverride: desiredLabel,
gitUrl,
yoloMode,
})

if (parallelMode && (worktreeBranch || worktreePath)) {
Expand All @@ -535,6 +550,8 @@ export class CliProcessHandler {
this.registry.setSessionPid(provisionalId, proc.pid)
}

// Clear the timeout BEFORE clearing the pending session to prevent race conditions
this.clearPendingTimeout()
this.registry.clearPendingSession()
this.callbacks.onPendingSessionChanged(null)
this.callbacks.onSessionCreated(this.pendingProcess?.sawApiReqStarted ?? false)
Expand Down Expand Up @@ -634,6 +651,7 @@ export class CliProcessHandler {
startTime,
parser,
parallelMode,
yoloMode,
worktreeBranch,
worktreePath,
worktreeInfo,
Expand Down Expand Up @@ -682,6 +700,7 @@ export class CliProcessHandler {
parallelMode,
labelOverride: desiredLabel,
gitUrl,
yoloMode,
})
this.debugLog(`Created new session: ${sessionId}`)
}
Expand Down
37 changes: 37 additions & 0 deletions src/core/kilocode/agent-manager/__tests__/CliArgsBuilder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,41 @@ describe("buildCliArgs", () => {
expect(args).toContain("--yolo")
expect(args).not.toContain("--auto")
})

// YOLO mode tests
describe("yoloMode option", () => {
it("includes --yolo by default (undefined)", () => {
const args = buildCliArgs("/workspace", "prompt")

expect(args).toContain("--yolo")
})

it("includes --yolo when yoloMode is true", () => {
const args = buildCliArgs("/workspace", "prompt", { yoloMode: true })

expect(args).toContain("--yolo")
})

it("excludes --yolo when yoloMode is false", () => {
const args = buildCliArgs("/workspace", "prompt", { yoloMode: false })

expect(args).not.toContain("--yolo")
})

it("excludes --yolo when yoloMode is false with session", () => {
const args = buildCliArgs("/workspace", "prompt", { yoloMode: false, sessionId: "abc123" })

expect(args).not.toContain("--yolo")
expect(args).toContain("--session=abc123")
expect(args).toEqual(["--json-io", "--workspace=/workspace", "--session=abc123", "prompt"])
})

it("includes --yolo when yoloMode is true with session", () => {
const args = buildCliArgs("/workspace", "prompt", { yoloMode: true, sessionId: "abc123" })

expect(args).toContain("--yolo")
expect(args).toContain("--session=abc123")
expect(args).toEqual(["--json-io", "--yolo", "--workspace=/workspace", "--session=abc123", "prompt"])
})
})
})
14 changes: 13 additions & 1 deletion src/core/kilocode/agent-manager/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface AgentSession {
source: SessionSource
parallelMode?: ParallelModeInfo
gitUrl?: string
yoloMode?: boolean // True if session was started with --yolo flag (auto-approve operations)
}

/**
Expand All @@ -43,6 +44,7 @@ export interface PendingSession {
startTime: number
parallelMode?: boolean
gitUrl?: string
yoloMode?: boolean // True if session will be started with --yolo flag
}

// Re-export remote session shape from shared session client for consistency
Expand All @@ -58,11 +60,21 @@ export interface AgentManagerState {
*/
export type AgentManagerMessage =
| { type: "agentManager.webviewReady" }
| { type: "agentManager.startSession"; prompt: string; parallelMode?: boolean; existingBranch?: string }
| {
type: "agentManager.startSession"
prompt: string
parallelMode?: boolean
yoloMode?: boolean
existingBranch?: string
versions?: number
labels?: string[]
}
| { type: "agentManager.stopSession"; sessionId: string }
| { type: "agentManager.selectSession"; sessionId: string }
| { type: "agentManager.refreshRemoteSessions" }
| { type: "agentManager.listBranches" }
| { type: "agentManager.respondToApproval"; sessionId: string; approved: boolean; text?: string; messageTs: number }
| { type: "agentManager.renameSession"; sessionId: string; label: string }

/**
* Messages from Extension to Webview
Expand Down
15 changes: 12 additions & 3 deletions webview-ui/src/i18n/locales/ar/agentManager.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading