From 7e98535ec2bfd852493043a1fea66a3eb795a790 Mon Sep 17 00:00:00 2001 From: code-crusher Date: Wed, 21 Jan 2026 08:49:39 +0530 Subject: [PATCH 1/4] fix plan hover popup --- webview-ui/src/components/kilocode/BottomApiConfig.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/kilocode/BottomApiConfig.tsx b/webview-ui/src/components/kilocode/BottomApiConfig.tsx index 9316465d4..15ffc4e21 100644 --- a/webview-ui/src/components/kilocode/BottomApiConfig.tsx +++ b/webview-ui/src/components/kilocode/BottomApiConfig.tsx @@ -89,7 +89,7 @@ export const BottomApiConfig = () => { const rect = triggerRef.current.getBoundingClientRect() setCardPosition({ top: rect.top - 10, - left: rect.left + rect.width / 2, + left: rect.left, }) } setShowHoverCard(true) @@ -121,7 +121,7 @@ export const BottomApiConfig = () => { style={{ top: `${cardPosition.top}px`, left: `${cardPosition.left}px`, - transform: "translate(-50%, -100%)", + transform: "translate(0, -100%)", }}>
From 7dea996a13090b1a7a8ae921ba62e47a6f900b5b Mon Sep 17 00:00:00 2001 From: code-crusher Date: Wed, 21 Jan 2026 09:00:13 +0530 Subject: [PATCH 2/4] clean up profile page --- .../kilocode/settings/providers/KiloCode.tsx | 74 +++++++------------ .../src/components/settings/ApiOptions.tsx | 21 +++--- webview-ui/src/i18n/locales/en/kilocode.json | 2 +- webview-ui/src/i18n/locales/en/settings.json | 2 +- 4 files changed, 38 insertions(+), 61 deletions(-) diff --git a/webview-ui/src/components/kilocode/settings/providers/KiloCode.tsx b/webview-ui/src/components/kilocode/settings/providers/KiloCode.tsx index acdbde5e2..80769eeeb 100644 --- a/webview-ui/src/components/kilocode/settings/providers/KiloCode.tsx +++ b/webview-ui/src/components/kilocode/settings/providers/KiloCode.tsx @@ -1,18 +1,13 @@ -import { useCallback } from "react" -import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react" -import { getKiloCodeBackendSignInUrl } from "../../helpers" -import { Button } from "@src/components/ui" -import { type ProviderSettings, type OrganizationAllowList } from "@roo-code/types" +import { getAppUrl, type OrganizationAllowList, type ProviderSettings } from "@roo-code/types" import type { RouterModels } from "@roo/api" -import { useAppTranslation } from "@src/i18n/TranslationContext" import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink" -import { inputEventTransform } from "../../../settings/transforms" -import { ModelPicker } from "../../../settings/ModelPicker" +import { Button } from "@src/components/ui" +import { useAppTranslation } from "@src/i18n/TranslationContext" import { vscode } from "@src/utils/vscode" -import { OrganizationSelector } from "../../common/OrganizationSelector" import { KiloCodeWrapperProperties } from "../../../../../../src/shared/kilocode/wrapper" -import { getAppUrl } from "@roo-code/types" -import { useKiloIdentity } from "@src/utils/kilocode/useKiloIdentity" +import { ModelPicker } from "../../../settings/ModelPicker" +import { OrganizationSelector } from "../../common/OrganizationSelector" +import { getKiloCodeBackendSignInUrl } from "../../helpers" type KiloCodeProps = { apiConfiguration: ProviderSettings @@ -41,29 +36,29 @@ export const KiloCode = ({ }: KiloCodeProps) => { const { t } = useAppTranslation() - const handleInputChange = useCallback( - ( - field: K, - transform: (event: E) => ProviderSettings[K] = inputEventTransform, - ) => - (event: E | Event) => { - setApiConfigurationField(field, transform(event as E)) - }, - [setApiConfigurationField], - ) + // const handleInputChange = useCallback( + // ( + // field: K, + // transform: (event: E) => ProviderSettings[K] = inputEventTransform, + // ) => + // (event: E | Event) => { + // setApiConfigurationField(field, transform(event as E)) + // }, + // [setApiConfigurationField], + // ) // Use the existing hook to get user identity - const userIdentity = useKiloIdentity(apiConfiguration.kilocodeToken || "", "") - const isKiloCodeAiUser = userIdentity.endsWith("@matterai.so") + // const userIdentity = useKiloIdentity(apiConfiguration.kilocodeToken || "", "") + // const isKiloCodeAiUser = userIdentity.endsWith("@matterai.so") - const areKilocodeWarningsDisabled = apiConfiguration.kilocodeTesterWarningsDisabledUntil - ? apiConfiguration.kilocodeTesterWarningsDisabledUntil > Date.now() - : false + // const areKilocodeWarningsDisabled = apiConfiguration.kilocodeTesterWarningsDisabledUntil + // ? apiConfiguration.kilocodeTesterWarningsDisabledUntil > Date.now() + // : false - const handleToggleTesterWarnings = useCallback(() => { - const newTimestamp = Date.now() + (areKilocodeWarningsDisabled ? 0 : 24 * 60 * 60 * 1000) - setApiConfigurationField("kilocodeTesterWarningsDisabledUntil", newTimestamp) - }, [areKilocodeWarningsDisabled, setApiConfigurationField]) + // const handleToggleTesterWarnings = useCallback(() => { + // const newTimestamp = Date.now() + (areKilocodeWarningsDisabled ? 0 : 24 * 60 * 60 * 1000) + // setApiConfigurationField("kilocodeTesterWarningsDisabledUntil", newTimestamp) + // }, [areKilocodeWarningsDisabled, setApiConfigurationField]) return ( <> @@ -98,7 +93,7 @@ export const KiloCode = ({ {t("kilocode:settings.provider.login")} ))} - + {/*
- + */} @@ -122,21 +117,6 @@ export const KiloCode = ({ serviceUrl={getAppUrl()} organizationAllowList={organizationAllowList} /> - - {/* KILOCODE-TESTER warnings setting - only visible for @matterai.so users */} - {isKiloCodeAiUser && ( -
- -
- {areKilocodeWarningsDisabled - ? `Warnings disabled until ${new Date(apiConfiguration.kilocodeTesterWarningsDisabledUntil || 0).toLocaleString()}` - : "KILOCODE-TESTER warnings are currently enabled"} -
- -
- )} ) } diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index c3a807277..6aea243be 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -8,7 +8,6 @@ import { type ProviderSettings } from "@roo-code/types" import { useRouterModels } from "@src/components/ui/hooks/useRouterModels" import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel" import { useExtensionState } from "@src/context/ExtensionStateContext" -import { useAppTranslation } from "@src/i18n/TranslationContext" import { validateApiConfigurationExcludingModelErrors } from "@src/utils/validate" import { vscode } from "@src/utils/vscode" // kilocode_change start @@ -17,13 +16,11 @@ import { vscode } from "@src/utils/vscode" // OPENROUTER_DEFAULT_PROVIDER_NAME, //} from "@src/components/ui/hooks/useOpenRouterModelProviders" // kilocode_change start -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@src/components/ui" // import { ModelPicker } from "./ModelPicker" // kilocode_change import { KiloCode } from "../kilocode/settings/providers/KiloCode" // kilocode_change import { ApiErrorMessage } from "./ApiErrorMessage" import { ThinkingBudget } from "./ThinkingBudget" -import { TodoListSettingsControl } from "./TodoListSettingsControl" import { Verbosity } from "./Verbosity" export interface ApiOptionsProps { @@ -45,13 +42,13 @@ const ApiOptions = ({ uriScheme, apiConfiguration, setApiConfigurationField, - fromWelcomeView, + // fromWelcomeView, errorMessage, setErrorMessage, hideKiloCodeButton = false, currentApiConfigName, // kilocode_change }: ApiOptionsProps) => { - const { t } = useAppTranslation() + // const { t } = useAppTranslation() const { organizationAllowList, uiKind, // kilocode_change @@ -90,7 +87,7 @@ const ApiOptions = ({ [customHeaders, apiConfiguration?.openAiHeaders, setApiConfigurationField], ) - const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false) + // const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false) // const handleInputChange = useCallback( // ( @@ -440,7 +437,7 @@ const ApiOptions = ({ // kilocode_change end } */} - {!fromWelcomeView && ( + {/* {!fromWelcomeView && ( @@ -451,7 +448,7 @@ const ApiOptions = ({ todoListEnabled={apiConfiguration.todoListEnabled} onChange={(field, value) => setApiConfigurationField(field, value)} /> - {/* setApiConfigurationField(field, value)} @@ -474,8 +471,8 @@ const ApiOptions = ({ : DEFAULT_CONSECUTIVE_MISTAKE_LIMIT } onChange={(value) => setApiConfigurationField("consecutiveMistakeLimit", value)} - /> */} - {/* kilocode_change start + /> + kilocode_change start selectedProvider === "openrouter" && openRouterModelProviders && Object.keys(openRouterModelProviders).length > 0 && ( @@ -518,10 +515,10 @@ const ApiOptions = ({
) - kilocode_change end */} + kilocode_change end - )} + )} */} ) } diff --git a/webview-ui/src/i18n/locales/en/kilocode.json b/webview-ui/src/i18n/locales/en/kilocode.json index e2e60dfbd..e6877b60e 100644 --- a/webview-ui/src/i18n/locales/en/kilocode.json +++ b/webview-ui/src/i18n/locales/en/kilocode.json @@ -55,7 +55,7 @@ "account": "MatterAI Account", "apiKey": "Axon Code API Key", "login": "Log in at MatterAI", - "logout": "Log out from MatterAI", + "logout": "Log out from Axon Code", "providerRouting": { "title": "Provider Routing", "managedByOrganization": "Manage Organization-level Provider Routing", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 78d69fbb7..a23d64e6b 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -877,7 +877,7 @@ }, "modelPicker": { "automaticFetch": "The extension automatically fetches the latest list of models available on {{serviceName}}. If you're unsure which model to choose, Axon Code works best with {{defaultModelId}}.", - "label": "Model", + "label": "Default Model", "searchPlaceholder": "Search", "noMatchFound": "No match found", "useCustomModel": "Use custom: {{modelId}}" From 6480525c36cc402c7d6679631e0fdddb345c4985 Mon Sep 17 00:00:00 2001 From: code-crusher Date: Wed, 21 Jan 2026 09:46:29 +0530 Subject: [PATCH 3/4] multi-line chip rendering --- src/core/mentions/index.ts | 33 ++++++++++++++++--- src/shared/__tests__/support-prompts.spec.ts | 18 +++++----- src/shared/context-mentions.ts | 16 ++++++--- src/shared/support-prompt.ts | 5 +-- webview-ui/src/components/chat/ChatView.tsx | 5 +++ .../src/components/chat/CodeIndexPopover.tsx | 16 +++++---- webview-ui/src/index.css | 7 ++++ webview-ui/src/utils/chat-render.ts | 13 ++++++-- 8 files changed, 81 insertions(+), 32 deletions(-) diff --git a/src/core/mentions/index.ts b/src/core/mentions/index.ts index 607bc11bf..7f9852ed7 100644 --- a/src/core/mentions/index.ts +++ b/src/core/mentions/index.ts @@ -268,7 +268,21 @@ async function getFileOrFolderContent( showRooIgnoredFiles: boolean = false, maxReadFileLine?: number, ): Promise { - const unescapedPath = unescapeSpaces(mentionPath) + // Parse line numbers from the mention path (e.g., "file.ts#L20-80") + const lineMatch = mentionPath.match(/^(.*?)(?:#L(\d+)(?:-(\d+))?)?$/) + let filePath = mentionPath + let startLine: number | undefined + let endLine: number | undefined + + if (lineMatch) { + filePath = lineMatch[1] + if (lineMatch[2]) { + startLine = parseInt(lineMatch[2], 10) + endLine = lineMatch[3] ? parseInt(lineMatch[3], 10) : startLine + } + } + + const unescapedPath = unescapeSpaces(filePath) const absPath = path.resolve(cwd, unescapedPath) try { @@ -285,9 +299,20 @@ async function getFileOrFolderContent( // kilocode_change end try { const content = await extractTextFromFile(absPath, maxReadFileLine) + + // Extract specific lines if line numbers are specified + if (startLine !== undefined && endLine !== undefined) { + const lines = content.split("\n") + // Convert to 0-based index + const startIndex = Math.max(0, startLine - 1) + const endIndex = Math.min(lines.length, endLine) + const extractedLines = lines.slice(startIndex, endIndex) + return extractedLines.join("\n") + } + return content } catch (error) { - return `(Failed to read contents of ${mentionPath}): ${error.message}` + return `(Failed to read contents of ${filePath}): ${error.message}` } } else if (stats.isDirectory()) { const entries = await fs.readdir(absPath, { withFileTypes: true }) @@ -341,10 +366,10 @@ async function getFileOrFolderContent( const fileContents = (await Promise.all(fileContentPromises)).filter((content) => content) return `${folderContent}\n${fileContents.join("\n\n")}`.trim() } else { - return `(Failed to read contents of ${mentionPath})` + return `(Failed to read contents of ${filePath})` } } catch (error) { - throw new Error(`Failed to access path "${mentionPath}": ${error.message}`) + throw new Error(`Failed to access path "${filePath}": ${error.message}`) } } diff --git a/src/shared/__tests__/support-prompts.spec.ts b/src/shared/__tests__/support-prompts.spec.ts index ea6a193d5..548a909e0 100644 --- a/src/shared/__tests__/support-prompts.spec.ts +++ b/src/shared/__tests__/support-prompts.spec.ts @@ -97,7 +97,7 @@ describe("Code Action Prompts", () => { endLine: "1", diagnostics: [], }) - const expected = `${testFilePath}:1-1\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) @@ -110,7 +110,7 @@ describe("Code Action Prompts", () => { endLine: "20", diagnostics, }) - const expected = `${testFilePath}:10-20\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L10-20` expect(prompt).toBe(expected) }) @@ -123,7 +123,7 @@ describe("Code Action Prompts", () => { startLine: "5", endLine: "15", }) - const expected = `${testFilePath}:5-15\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L5-15` expect(prompt).toBe(expected) }) @@ -135,7 +135,7 @@ describe("Code Action Prompts", () => { startLine: "1", endLine: "1", }) // 'status' is missing - const expected = `${testFilePath}:1-1\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) @@ -147,7 +147,7 @@ describe("Code Action Prompts", () => { startLine: "1", endLine: "1", }) - const expected = `${testFilePath}:1-1\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) @@ -158,7 +158,7 @@ describe("Code Action Prompts", () => { startLine: "1", endLine: "1", }) - const expected = `${testFilePath}:1-1\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) @@ -171,7 +171,7 @@ describe("Code Action Prompts", () => { startLine: "1", endLine: "1", }) // Convert to strings - const expected = `${testFilePath}:1-1\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) @@ -184,7 +184,7 @@ describe("Code Action Prompts", () => { startLine: "1", endLine: "1", }) - const expected = `${testFilePath}:1-1\n\`\`\`\n${testCode}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) @@ -198,7 +198,7 @@ describe("Code Action Prompts", () => { endLine: "1", diagnostics: [], }) - const expected = `${testFilePath}:1-1\n\`\`\`\n${bashText}\n\`\`\`` + const expected = `@/${testFilePath}#L1-1` expect(prompt).toBe(expected) }) }) diff --git a/src/shared/context-mentions.ts b/src/shared/context-mentions.ts index 5a0c4c0bc..98d435cc3 100644 --- a/src/shared/context-mentions.ts +++ b/src/shared/context-mentions.ts @@ -10,12 +10,12 @@ Mention regex: - `(?:^|\s)`: - **Non-Capturing Group (`(?:...)`)**: Groups the alternatives without capturing them. - **Line Start or Whitespace (`^|\s`)**: The @ must be at the start of a line or preceded by whitespace. - + - `(? = ({ {t("settings:unsavedChangesDialog.description")} - - onConfirmDialogResult(false)}> - {t("settings:unsavedChangesDialog.cancelButton")} - - onConfirmDialogResult(true)}> - {t("settings:unsavedChangesDialog.discardButton")} - + +
+ onConfirmDialogResult(false)}> + {t("settings:unsavedChangesDialog.cancelButton")} + + onConfirmDialogResult(true)}> + {t("settings:unsavedChangesDialog.discardButton")} + +
diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index 810a68574..a5cd77c24 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -475,6 +475,13 @@ vscode-text-field::part(input) { color: var(--vscode-foreground); } +.mention-chip__line { + color: var(--vscode-foreground); + opacity: 0.7; + font-size: 0.9em; + margin-left: 2px; +} + /** * vscrui Overrides / Hacks */ diff --git a/webview-ui/src/utils/chat-render.ts b/webview-ui/src/utils/chat-render.ts index ec907d62a..9430b20a3 100644 --- a/webview-ui/src/utils/chat-render.ts +++ b/webview-ui/src/utils/chat-render.ts @@ -77,7 +77,9 @@ export const escapeHtml = (value: string): string => export const getFileIconForMention = (rawMention: string, materialIconsBaseUri: string): string => { const mention = unescapeSpaces(rawMention) - const filename = mention.split("/").pop() || "" + // Remove line numbers (#L20-80) before extracting filename + const pathWithoutLineNumbers = mention.replace(/#L\d+(?:-\d+)?$/, "") + const filename = pathWithoutLineNumbers.split("/").pop() || "" if (filename.includes(".")) { const iconName = getIconForFilePath(filename) @@ -92,7 +94,8 @@ export const renderMentionChip = ( materialIconsBaseUri: string, isCompactFile: boolean = false, ): string => { - const displayText = isCompactFile ? rawMention : formatMentionChipParts(rawMention).primary || rawMention + const parts = formatMentionChipParts(rawMention) + const displayText = isCompactFile ? rawMention : parts.primary || rawMention const escapedPrimary = escapeHtml(displayText) const label = escapeHtml(`${isCompactFile ? rawMention : unescapeSpaces(rawMention)}`) const mentionValue = escapeHtml(`@${isCompactFile ? rawMention : unescapeSpaces(rawMention)}`) @@ -100,7 +103,11 @@ export const renderMentionChip = ( const fileIconUrl = getFileIconForMention(rawMention, materialIconsBaseUri) const iconHtml = fileIconUrl ? `` : "" - return `${iconHtml}${escapedPrimary}` + // Extract line number from meta parts if available + const lineInfo = parts.meta.find((m) => m.startsWith("L")) + const lineHtml = lineInfo ? `${escapeHtml(lineInfo)}` : "" + + return `${iconHtml}${escapedPrimary}${lineHtml}` } export const valueToHtml = ( From 2472385a27a9f47e41c1b3ba503ef5c048a82d33 Mon Sep 17 00:00:00 2001 From: code-crusher Date: Wed, 21 Jan 2026 10:01:05 +0530 Subject: [PATCH 4/4] update changelog --- CHANGELOG.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 273a7f146..f988f7657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,54 @@ # Changelog +## [v5.2.5] - 2026-01-21 + +### Added + +- Multi-line chip rendering for improved mention display + +### Changed + +- Clean up profile page +- Enhanced chat rendering utilities + +### Fixed + +- Fixed plan hover popup display + +--- + +## [v5.2.4] - 2026-01-19 + +### Fixed + +- Fixed SourceControlPanel.tsx - addressed review comments +- Fixed chat text UI issues + +--- + +## [v5.2.3] - 2026-01-16 + +### Fixed + +- Fixed chat text UI with improved component structure + +--- + +## [v5.2.2] - 2026-01-16 + +### Added + +- Model selector moved to improved location + +### Changed + +- UI improvements and IDE theme fixes +- Enhanced ChatTextArea component +- Updated translations for all supported languages +- Improved select-dropdown and popover components + +--- + ## [v5.2.1] - 2026-01-15 ### Added