Files
kilocode/packages/kilo-vscode/webview-ui/agent-manager/apply-conflicts.ts
T
Marius 22624ea22c feat: add apply-to-local button in Agent Manager (#6515)
* feat: add apply-to-local button in Agent Manager

* fix: address PR review - path traversal guard, safer regex, stdin null check

- Reject selectedFiles with absolute paths or .. components
- Narrow conflict regex to known git error patterns (avoids Windows colon misparse)
- Fail early if child.stdin is null instead of silently dropping patch data

* fix: address PR review round 2

- Add ApplyDialog.tsx to CSS consistency test TSX_FILES
- Clear applyTarget when worktree is deleted (avoids stale dialog)
- Add integration tests for checkApplyPatch and applyPatch

* fix: add missing vscode.Uri mock in KiloProvider session refresh test

The mock was missing the Uri namespace, causing TypeError on CI where
Bun resolves the type annotation at runtime. Locally it worked because
the constructor param was cast via 'as never'.

* fix: harden KiloProvider test mock with full Uri class and Disposable

The previous fix only added static methods to Uri. CI Bun resolves
vscode.Uri as a runtime class reference in the constructor parameter
type position. Provide a proper MockUri class, Disposable, and
EventEmitter stubs so the mock satisfies all runtime lookups.
2026-03-03 08:47:35 +00:00

32 lines
1.1 KiB
TypeScript

import type { AgentManagerApplyWorktreeDiffConflict } from "../src/types/messages"
export interface ApplyConflictRow {
file?: string
reasons: string[]
}
export function groupApplyConflicts(conflicts: AgentManagerApplyWorktreeDiffConflict[]): ApplyConflictRow[] {
const map = new Map<string, { file?: string; reasons: Set<string> }>()
for (const conflict of conflicts) {
const file = conflict.file?.trim()
const key = file && file.length > 0 ? file : "__unknown__"
const row = map.get(key)
if (!row) {
map.set(key, { file, reasons: new Set([conflict.reason]) })
continue
}
row.reasons.add(conflict.reason)
}
return Array.from(map.values()).map((row) => ({ file: row.file, reasons: Array.from(row.reasons) }))
}
export function mapApplyConflictReason(reason: string): "index" | "patch" | "contents" | undefined {
const text = reason.toLowerCase()
if (text.includes("does not match index")) return "index"
if (text.includes("patch does not apply") || text.includes("patch failed")) return "patch"
if (text.includes("cannot read the current contents")) return "contents"
return undefined
}