Merge pull request #11241 from Kilo-Org/stone-mind

feat(agent-manager): track feature button usage
This commit is contained in:
Marius
2026-06-16 11:14:38 +02:00
committed by GitHub
7 changed files with 236 additions and 35 deletions
@@ -67,6 +67,7 @@ export enum TelemetryEventName {
// Kilo-specific
COMMIT_MSG_GENERATED = "Commit Message Generated",
AGENT_MANAGER_OPENED = "Agent Manager Opened",
AGENT_MANAGER_BUTTON_CLICKED = "Agent Manager Button Clicked",
AGENT_MANAGER_SESSION_STARTED = "Agent Manager Session Started",
AGENT_MANAGER_SESSION_COMPLETED = "Agent Manager Session Completed",
AGENT_MANAGER_SESSION_STOPPED = "Agent Manager Session Stopped",
@@ -0,0 +1,69 @@
import { describe, expect, it } from "bun:test"
import type { TelemetryRequest } from "../../webview-ui/src/types/messages/webview-messages"
import { capture, tracker } from "../../webview-ui/agent-manager/telemetry"
import { TelemetryEventName } from "../../src/services/telemetry/types"
describe("Agent Manager telemetry", () => {
it("uses one stable event with low-cardinality button metadata", () => {
const messages: TelemetryRequest[] = []
capture({ postMessage: (message) => messages.push(message) }, "fullscreen_review", "tab_toolbar", {
action: "open",
fileCount: 3,
})
expect(messages).toEqual([
{
type: "telemetry",
event: TelemetryEventName.AGENT_MANAGER_BUTTON_CLICKED,
properties: {
action: "open",
fileCount: 3,
source: "agent-manager",
button: "fullscreen_review",
surface: "tab_toolbar",
},
},
])
})
it("does not allow callers to override event dimensions", () => {
const messages: TelemetryRequest[] = []
capture({ postMessage: (message) => messages.push(message) }, "apply_to_local", "apply_dialog", {
source: "other",
button: "other",
surface: "other",
})
expect(messages[0]?.properties).toMatchObject({
source: "agent-manager",
button: "apply_to_local",
surface: "apply_dialog",
})
})
it("resolves current properties before running wrapped actions", () => {
const messages: TelemetryRequest[] = []
const order: string[] = []
const metrics = tracker({
postMessage: (message) => {
messages.push(message)
order.push("telemetry")
},
})
const state = { action: "run" }
const click = metrics.click(
"run_script",
"tab_toolbar",
() => order.push("action"),
() => state,
)
state.action = "stop"
click()
expect(messages[0]?.properties?.action).toBe("stop")
expect(order).toEqual(["telemetry", "action"])
})
})
@@ -134,6 +134,7 @@ import { createSidebarCollapse } from "./sidebar-collapse"
import { SidebarToggleButton } from "./SidebarToggleButton"
import { setTabWidths } from "./tab-widths"
import { buildShortcutCategories } from "./shortcuts"
import { tracker } from "./telemetry"
import "./agent-manager.css"
import "./agent-manager-review.css"
const REVIEW_TAB_ID = "review"
@@ -203,6 +204,7 @@ const AgentManagerContent: Component = () => {
const [worktrees, setWorktrees] = createSignal<WorktreeState[]>([])
const [managedSessions, setManagedSessions] = createSignal<ManagedSessionState[]>([])
const [selection, setSelection] = createSignal<SidebarSelection>(LOCAL)
const metrics = tracker(vscode)
const [repoBranch, setRepoBranch] = createSignal<string | undefined>()
const [busyWorktrees, setBusyWorktrees] = createSignal<Map<string, WorktreeBusyState>>(new Map())
const [staleWorktreeIds, setStaleWorktreeIds] = createSignal<Set<string>>(new Set())
@@ -447,6 +449,7 @@ const AgentManagerContent: Component = () => {
if (!target) return
if (!applyHasSelection()) return
if (applyBusyForTarget()) return
metrics.track("apply_to_local", "apply_dialog", { fileCount: applySelectedFiles().length })
applyToLocal(target, applySelectedFiles())
}
@@ -497,6 +500,7 @@ const AgentManagerContent: Component = () => {
if (!sel || sel === LOCAL) return
vscode.postMessage({ type: "agentManager.openWorktree", worktreeId: sel })
}
const openWindow = metrics.click("open_worktree_window", "tab_toolbar", openWorktreeDirectory)
const runWorktree = (id: string) => {
const state = runStatuses()[id]?.state ?? "idle"
@@ -1600,6 +1604,7 @@ const AgentManagerContent: Component = () => {
const handleConfigureSetupScript = () => {
vscode.postMessage({ type: "agentManager.configureSetupScript" })
}
const setupScript = metrics.click("configure_setup_script", "worktree_settings", handleConfigureSetupScript)
const handleChangeDefaultBaseBranch = () => {
const [search, setSearch] = createSignal("")
@@ -1735,6 +1740,7 @@ const AgentManagerContent: Component = () => {
expandSidebar()
vscode.postMessage({ type: "agentManager.createWorktree" })
}
const createWorktree = metrics.click("new_worktree", "worktrees", handleCreateWorktree)
// Advanced worktree dialog — opens a full dialog with prompt, versions, model, mode
const showAdvancedWorktreeDialog = () => {
@@ -1829,6 +1835,7 @@ const AgentManagerContent: Component = () => {
const handlePromote = (sessionId: string, e: MouseEvent) => {
e.stopPropagation()
if (!loaded()) return
metrics.track("promote_session", "unassigned_session")
vscode.postMessage({ type: "agentManager.promoteSession", sessionId })
}
@@ -2204,7 +2211,7 @@ const AgentManagerContent: Component = () => {
size="small"
variant="ghost"
label={t("agentManager.worktree.new")}
onClick={handleCreateWorktree}
onClick={createWorktree}
disabled={!loaded()}
/>
<DropdownMenu gutter={4} placement="bottom-end">
@@ -2217,7 +2224,7 @@ const AgentManagerContent: Component = () => {
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content class="am-split-menu">
<DropdownMenu.Item onSelect={handleCreateWorktree}>
<DropdownMenu.Item onSelect={createWorktree}>
<span class="am-worktree-menu-gap" aria-hidden="true" />
<DropdownMenu.ItemLabel class="am-worktree-menu-label">
<span>{t("sidebar.session.newWorktree.from")}</span>
@@ -2260,7 +2267,7 @@ const AgentManagerContent: Component = () => {
size="small"
variant="ghost"
label={t("agentManager.shortcuts.title")}
onClick={handleShowKeyboardShortcuts}
onClick={metrics.click("keyboard_shortcuts", "worktrees_header", handleShowKeyboardShortcuts)}
/>
</TooltipKeybind>
<DropdownMenu gutter={4} placement="bottom-end">
@@ -2273,7 +2280,7 @@ const AgentManagerContent: Component = () => {
/>
<DropdownMenu.Portal>
<DropdownMenu.Content class="am-split-menu">
<DropdownMenu.Item onSelect={handleConfigureSetupScript}>
<DropdownMenu.Item onSelect={setupScript}>
<DropdownMenu.ItemLabel>{t("agentManager.worktree.setupScript")}</DropdownMenu.ItemLabel>
</DropdownMenu.Item>
<DropdownMenu.Separator />
@@ -2427,13 +2434,13 @@ const AgentManagerContent: Component = () => {
prStatuses()[wt.id] !== undefined ? (prStatuses()[wt.id] ?? undefined) : undefined
}
runStatus={runStatuses()[wt.id]}
onOpenPR={() =>
vscode.postMessage({ type: "agentManager.openPR", worktreeId: wt.id })
}
onOpenPR={metrics.click("open_pull_request", "worktree_menu", () =>
vscode.postMessage({ type: "agentManager.openPR", worktreeId: wt.id }),
)}
sections={sections()}
currentSectionId={wt.sectionId}
onMoveToSection={(secId) => moveToSection([wt.id], secId)}
onMoveToNewSection={() => newSection()}
onMoveToNewSection={metrics.click("new_section", "worktree_menu", () => newSection())}
onClick={() => {
if (pendingDelete() === wt.id) {
confirmDeleteWorktree(wt.id)
@@ -2448,9 +2455,9 @@ const AgentManagerContent: Component = () => {
onCancelRename={cancelRename}
onRemoveStale={() => confirmRemoveStaleWorktree(wt.id)}
onCopyPath={() => navigator.clipboard.writeText(wt.path)}
onOpen={() =>
vscode.postMessage({ type: "agentManager.openWorktree", worktreeId: wt.id })
}
onOpen={metrics.click("open_worktree_window", "worktree_menu", () =>
vscode.postMessage({ type: "agentManager.openWorktree", worktreeId: wt.id }),
)}
/>
</div>
)
@@ -2518,7 +2525,7 @@ const AgentManagerContent: Component = () => {
)
})()}
<Show when={worktrees().length === 0}>
<button class="am-worktree-create" onClick={handleCreateWorktree}>
<button class="am-worktree-create" onClick={createWorktree}>
<Icon name="plus" size="small" />
<span>{t("agentManager.worktree.new")}</span>
</button>
@@ -2607,7 +2614,11 @@ const AgentManagerContent: Component = () => {
<Icon name="branch" size="small" />
<ContextMenu.ItemLabel>{t("agentManager.session.openInWorktree")}</ContextMenu.ItemLabel>
</ContextMenu.Item>
<ContextMenu.Item onSelect={() => openLocally(s.id)}>
<ContextMenu.Item
onSelect={metrics.click("open_session_locally", "unassigned_session_menu", () =>
openLocally(s.id),
)}
>
<Icon name="folder" size="small" />
<ContextMenu.ItemLabel>{t("agentManager.session.openLocally")}</ContextMenu.ItemLabel>
</ContextMenu.Item>
@@ -2711,8 +2722,8 @@ const AgentManagerContent: Component = () => {
newTerminalLabel: t("agentManager.terminal.new"),
newSessionMenuLabel: t("agentManager.session.newSession"),
moreOptionsLabel: t("agentManager.tab.newOptions"),
onNewSession: handleAddSession,
onNewTerminal: () => termHandlers.requestNew(),
onNewSession: metrics.click("new_session", "tab_bar", handleAddSession),
onNewTerminal: metrics.click("embedded_terminal", "new_tab_menu", () => termHandlers.requestNew()),
})}
</div>
</Show>
@@ -2738,7 +2749,7 @@ const AgentManagerContent: Component = () => {
<Show when={isWorktree()}>
<>
<Tooltip value={t("agentManager.open.tooltip")} placement="bottom">
<Button size="small" variant="ghost" icon="folder" onClick={openWorktreeDirectory}>
<Button size="small" variant="ghost" icon="folder" onClick={openWindow}>
{t("agentManager.open.button")}
</Button>
</Tooltip>
@@ -2774,7 +2785,14 @@ const AgentManagerContent: Component = () => {
variant="ghost"
icon={active() ? "stop" : "play"}
disabled={rs()?.state === "stopping"}
onClick={() => runWorktree(rid())}
onClick={metrics.click(
"run_script",
"tab_toolbar",
() => runWorktree(rid()),
() => ({
action: active() ? "stop" : configured() ? "run" : "configure",
}),
)}
>
{active() ? "Stop" : "Run"}
</Button>
@@ -2794,7 +2812,9 @@ const AgentManagerContent: Component = () => {
/>
<DropdownMenu.Portal>
<DropdownMenu.Content class="am-split-menu">
<DropdownMenu.Item onSelect={configureRunScript}>
<DropdownMenu.Item
onSelect={metrics.click("configure_run_script", "run_menu", configureRunScript)}
>
<Icon name="settings-gear" size="small" />
<DropdownMenu.ItemLabel>{t("agentManager.run.configure")}</DropdownMenu.ItemLabel>
</DropdownMenu.Item>
@@ -2813,6 +2833,9 @@ const AgentManagerContent: Component = () => {
<button
class={`am-diff-toggle-btn ${diffOpen() && !reviewActive() ? "am-tab-diff-btn-active" : ""} ${hasChanges() ? "am-diff-toggle-has-changes" : ""}`}
onClick={() => {
metrics.track("side_review", "tab_toolbar", {
action: diffOpen() && !reviewActive() ? "close" : "open",
})
if (reviewActive()) {
closeReviewTab()
setSidePanel("diff")
@@ -2845,7 +2868,7 @@ const AgentManagerContent: Component = () => {
variant="ghost"
label={t("command.review.toggle")}
class={reviewActive() ? "am-tab-diff-btn-active" : ""}
onClick={toggleReviewTab}
onClick={metrics.click("fullscreen_review", "tab_toolbar", toggleReviewTab)}
/>
</Tooltip>
</Show>
@@ -2864,6 +2887,7 @@ const AgentManagerContent: Component = () => {
variant="ghost"
label={t("agentManager.tab.openTerminal")}
onClick={() => {
metrics.track("vscode_terminal", "tab_toolbar")
const id = session.currentSessionID()
if (id) vscode.postMessage({ type: "agentManager.showTerminal", sessionId: id })
else if (selection() === LOCAL) vscode.postMessage({ type: "agentManager.showLocalTerminal" })
@@ -3020,6 +3044,7 @@ const AgentManagerContent: Component = () => {
if (!loaded()) return
const sid = session.currentSessionID()
if (!sid) return
metrics.track("open_session_locally", "readonly_banner")
openLocally(sid)
}}
>
@@ -3031,7 +3056,9 @@ const AgentManagerContent: Component = () => {
onClick={() => {
if (!loaded()) return
const sid = session.currentSessionID()
if (sid) vscode.postMessage({ type: "agentManager.promoteSession", sessionId: sid })
if (!sid) return
metrics.track("promote_session", "readonly_banner")
vscode.postMessage({ type: "agentManager.promoteSession", sessionId: sid })
}}
>
{t("agentManager.session.openInWorktree")}
@@ -3073,8 +3100,13 @@ const AgentManagerContent: Component = () => {
comments={reviewComments()}
onCommentsChange={setReviewCommentsForSelection}
composer={reviewComposer}
onClose={() => setSidePanel(null)}
onExpand={selection() !== null ? openReviewTab : undefined}
onSendClick={() => metrics.track("send_review_comments", "side_review")}
onClose={metrics.click("side_review_close", "side_review", () => setSidePanel(null))}
onExpand={
selection() !== null
? metrics.click("fullscreen_review", "side_review", openReviewTab, { action: "open" })
: undefined
}
onRequestDiff={requestDiffFile}
onOpenFile={(file, line) => {
const id = currentDiffSessionId()
@@ -3082,7 +3114,7 @@ const AgentManagerContent: Component = () => {
vscode.postMessage({ type: "agentManager.openFile", sessionId: id, filePath: file, line })
else if (selection() === LOCAL) vscode.postMessage({ type: "openFile", filePath: file, line })
}}
onRevertFile={revertCtl.revert}
onRevertFile={metrics.use("revert_file", "side_review", revertCtl.revert)}
revertingFiles={revertCtl.reverting()}
activeTerminalId={terms.activeId()}
/>
@@ -3104,6 +3136,7 @@ const AgentManagerContent: Component = () => {
onCommentsChange={setReviewCommentsForSelection}
composer={reviewComposer}
onSendAll={closeReviewTab}
onSendClick={() => metrics.track("send_review_comments", "fullscreen_review")}
diffStyle={reviewDiffStyle()}
onDiffStyleChange={setSharedDiffStyle}
markdownRender={markdown.render()}
@@ -3114,10 +3147,10 @@ const AgentManagerContent: Component = () => {
if (id) vscode.postMessage({ type: "agentManager.openFile", sessionId: id, filePath: file, line })
else if (selection() === LOCAL) vscode.postMessage({ type: "openFile", filePath: file, line })
}}
onRevertFile={revertCtl.revert}
onRevertFile={metrics.use("revert_file", "fullscreen_review", revertCtl.revert)}
revertingFiles={revertCtl.reverting()}
activeTerminalId={terms.activeId()}
onClose={closeReviewTab}
onClose={metrics.click("fullscreen_review", "fullscreen_review", closeReviewTab, { action: "close" })}
/>
</div>
</Show>
@@ -75,6 +75,7 @@ interface DiffPanelProps {
onCommentsChange: (comments: ReviewComment[]) => void
composer?: ReviewComposer
onSendAll?: () => void
onSendClick?: () => void
onClose: () => void
onExpand?: () => void
onRequestDiff?: (file: string) => void
@@ -439,6 +440,11 @@ export const DiffPanel: Component<DiffPanelProps> = (props) => {
props.onSendAll?.()
}
const sendAllClick = () => {
props.onSendClick?.()
sendAllToChat()
}
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key !== "Enter") return
if (!(e.metaKey || e.ctrlKey)) return
@@ -731,7 +737,7 @@ export const DiffPanel: Component<DiffPanelProps> = (props) => {
{comments().length} comment{comments().length !== 1 ? "s" : ""}
</span>
<TooltipKeybind title={t("agentManager.review.sendAllToChat")} keybind={sendAllKeybind()} placement="top">
<Button variant="primary" size="small" onClick={sendAllToChat}>
<Button variant="primary" size="small" onClick={sendAllClick}>
{t("agentManager.review.sendAllToChat")}
</Button>
</TooltipKeybind>
@@ -34,6 +34,7 @@ import { useSpeechToText } from "../src/components/speech-to-text/useSpeechToTex
import { convertToMentionPath } from "../src/utils/path-mentions"
import { insertSpacedText } from "../src/components/chat/prompt-input-utils"
import { BranchSelect, BranchSelectPopover } from "../src/components/shared/BranchSelect"
import { tracker } from "./telemetry"
type VersionCount = 1 | 2 | 3 | 4
const VERSION_OPTIONS: VersionCount[] = [1, 2, 3, 4]
@@ -71,6 +72,10 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
const session = useSession()
const provider = useProvider()
const { config } = useConfig()
const metrics = tracker(vscode)
const track = (button: string, properties?: Record<string, string | number | boolean | undefined>) =>
metrics.track(button, "configure_worktree_dialog", properties)
const click = metrics.click
const [tab, setTab] = createSignal<DialogTab>("new")
@@ -209,6 +214,8 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
if (compareMode() && totalAllocations(modelAllocations()) === 0) return false
return true
}
const total = () => (compareMode() ? totalAllocations(modelAllocations()) : versions())
const mode = () => (compareMode() ? "compare_models" : versions() > 1 ? "multiple_versions" : "single")
const handleSubmit = () => {
if (!canSubmit()) return
@@ -224,7 +231,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
const isCompare = compareMode()
const allocations = isCompare ? allocationsToArray(modelAllocations()) : undefined
const count = isCompare ? totalAllocations(modelAllocations()) : versions()
const count = total()
const sel = isCompare ? null : model()
vscode.postMessage({
@@ -320,6 +327,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
const handleBranchSelect = (name: string) => {
if (isPending()) return
track("import_branch")
setImportPending(true)
setBranchOpen(false)
setBranchSearch("")
@@ -333,7 +341,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
<button
class="am-tab-switcher-pill"
classList={{ "am-tab-switcher-pill-active": tab() === "new" }}
onClick={() => setTab("new")}
onClick={click("switch_dialog_tab", "configure_worktree_dialog", () => setTab("new"), { tab: "new" })}
type="button"
>
{t("agentManager.dialog.tab.new")}
@@ -341,7 +349,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
<button
class="am-tab-switcher-pill"
classList={{ "am-tab-switcher-pill-active": tab() === "import" }}
onClick={() => setTab("import")}
onClick={click("switch_dialog_tab", "configure_worktree_dialog", () => setTab("import"), { tab: "import" })}
type="button"
>
{t("agentManager.dialog.tab.import")}
@@ -460,7 +468,16 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
</div>
{/* Advanced options toggle */}
<button class="am-advanced-toggle" onClick={() => setShowAdvanced(!showAdvanced())} type="button">
<button
class="am-advanced-toggle"
onClick={click(
"advanced_options",
"configure_worktree_dialog",
() => setShowAdvanced(!showAdvanced()),
() => ({ action: showAdvanced() ? "close" : "open" }),
)}
type="button"
>
<Icon name={showAdvanced() ? "chevron-down" : "chevron-right"} size="small" />
<span>{t("agentManager.dialog.advancedOptions")}</span>
</button>
@@ -584,7 +601,9 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
<button
class="am-nv-pill"
classList={{ "am-nv-pill-active": versions() === count }}
onClick={() => setVersions(count)}
onClick={click("version_count", "configure_worktree_dialog", () => setVersions(count), {
count,
})}
type="button"
>
{count}
@@ -595,7 +614,13 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
placement="top"
contentClass="am-tooltip-wrap"
>
<button class="am-nv-pill am-nv-pill-compare" onClick={() => setCompareMode(true)} type="button">
<button
class="am-nv-pill am-nv-pill-compare"
onClick={click("compare_models", "configure_worktree_dialog", () => setCompareMode(true), {
action: "open",
})}
type="button"
>
<Icon name="layers" size="small" />
<span class="am-nv-pill-compare-label">{t("agentManager.dialog.compareModels")}</span>
</button>
@@ -622,6 +647,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
<button
class="am-nv-pill-back"
onClick={() => {
track("compare_models", { action: "close" })
setCompareMode(false)
setModelAllocations(new Map())
}}
@@ -670,7 +696,21 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
</div>
{/* Submit button — fixed footer, always visible */}
<div class="am-nv-dialog-footer">
<Button variant="primary" size="large" class="am-nv-submit" onClick={handleSubmit} disabled={!canSubmit()}>
<Button
variant="primary"
size="large"
class="am-nv-submit"
onClick={click("create_worktree", "configure_worktree_dialog", handleSubmit, () => ({
mode: mode(),
versionCount: total(),
advanced: showAdvanced(),
customBranch: showAdvanced() && !!branchName().trim(),
customBase: showAdvanced() && !!baseBranch(),
hasPrompt: !!prompt().trim(),
hasAttachments: imageAttach.images().length > 0,
}))}
disabled={!canSubmit()}
>
<Show
when={!starting()}
fallback={
@@ -714,7 +754,7 @@ export const NewWorktreeDialog: Component<{ onClose: () => void; defaultBaseBran
<Button
variant="secondary"
size="small"
onClick={handlePRSubmit}
onClick={click("import_pull_request", "configure_worktree_dialog", handlePRSubmit)}
disabled={!prUrl().trim() || isPending()}
>
<Show when={prPending()} fallback={t("agentManager.import.open")}>
@@ -0,0 +1,46 @@
import { TelemetryEventName } from "../../src/services/telemetry/types"
import type { TelemetryRequest } from "../src/types/messages/webview-messages"
interface Target {
postMessage(message: TelemetryRequest): void
}
type Value = string | number | boolean | undefined
type Properties = Record<string, Value>
type Input = Properties | (() => Properties)
export function capture(target: Target, button: string, surface: string, properties: Properties = {}) {
target.postMessage({
type: "telemetry",
event: TelemetryEventName.AGENT_MANAGER_BUTTON_CLICKED,
properties: {
...properties,
source: "agent-manager",
button,
surface,
},
})
}
function clicked(target: Target, button: string, surface: string, action: () => void, properties: Input = {}) {
return () => {
capture(target, button, surface, typeof properties === "function" ? properties() : properties)
action()
}
}
function used<T>(target: Target, button: string, surface: string, action: (value: T) => void) {
return (value: T) => {
capture(target, button, surface)
action(value)
}
}
export function tracker(target: Target) {
return {
track: (button: string, surface: string, properties?: Properties) => capture(target, button, surface, properties),
click: (button: string, surface: string, action: () => void, properties?: Input) =>
clicked(target, button, surface, action, properties),
use: <T>(button: string, surface: string, action: (value: T) => void) => used(target, button, surface, action),
}
}
@@ -72,6 +72,7 @@ interface FullScreenDiffViewProps {
onCommentsChange: (comments: ReviewComment[]) => void
composer?: ReviewComposer
onSendAll?: () => void
onSendClick?: () => void
diffStyle: DiffStyle
onDiffStyleChange: (style: DiffStyle) => void
markdownRender?: boolean
@@ -443,6 +444,11 @@ export const FullScreenDiffView: Component<FullScreenDiffViewProps> = (props) =>
props.onSendAll?.()
}
const sendAllClick = () => {
props.onSendClick?.()
sendAllToChat()
}
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key !== "Enter") return
if (!(e.metaKey || e.ctrlKey)) return
@@ -573,7 +579,7 @@ export const FullScreenDiffView: Component<FullScreenDiffViewProps> = (props) =>
keybind={sendAllKeybind()}
placement="bottom"
>
<Button variant="primary" size="small" onClick={sendAllToChat}>
<Button variant="primary" size="small" onClick={sendAllClick}>
{t("agentManager.review.sendAllToChatWithCount", { count: comments().length })}
</Button>
</TooltipKeybind>