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
11 changes: 11 additions & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ export const DEFAULT_WRITE_DELAY_MS = 1000
*/
export const DEFAULT_TERMINAL_OUTPUT_CHARACTER_LIMIT = 50_000

export const codeReviewSettingsSchema = z.object({
enterpriseHost: z.string().optional(),
enterpriseApiKey: z.string().optional(),
reviewOnlyMode: z.boolean().optional(),
})

export type CodeReviewSettings = z.infer<typeof codeReviewSettingsSchema>

/**
* GlobalSettings
*/
Expand Down Expand Up @@ -177,6 +185,9 @@ export const globalSettingsSchema = z.object({
hasOpenedModeSelector: z.boolean().optional(),
lastModeExportPath: z.string().optional(),
lastModeImportPath: z.string().optional(),

// Code Review Settings
codeReviewSettings: codeReviewSettingsSchema.optional(),
})

export type GlobalSettings = z.infer<typeof globalSettingsSchema>
Expand Down
28 changes: 25 additions & 3 deletions src/core/kilocode/api/codeReviewService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ export class CodeReviewService {
private readonly MAX_POLLING_DURATION = 5 * 60 * 1000 // 5 minutes
private readonly REQUEST_TIMEOUT = 30 * 1000 // 30 seconds

constructor(private kilocodeToken: string) {}
constructor(
private kilocodeToken: string,
private enterpriseHost?: string,
private enterpriseApiKey?: string,
) {}

async requestCodeReview(request: CodeReviewRequest): Promise<CodeReviewResultsPayload> {
return this.requestCodeReviewWithRetry(request, 3) // Max 3 retries for initial request
Expand Down Expand Up @@ -72,7 +76,17 @@ export class CodeReviewService {
request: CodeReviewRequest,
headers: Record<string, string>,
): Promise<CodeReviewStartResponse> {
const url = getKiloUrlFromToken("https://api.matterai.so/codereview", this.kilocodeToken)
let url: string

if (this.enterpriseHost && this.enterpriseApiKey) {
console.log("this.enterpriseApiKey", this.enterpriseApiKey)
// Use enterprise host and API key
url = `${this.enterpriseHost.replace(/\/$/, "")}/codereview`
headers["Authorization"] = `Bearer ${this.enterpriseApiKey}`
} else {
// Use default MatterAI service
url = getKiloUrlFromToken("https://api.matterai.so/codereview", this.kilocodeToken)
}

const response = await axios.post<CodeReviewStartResponse>(url, request, {
headers,
Expand Down Expand Up @@ -139,7 +153,15 @@ export class CodeReviewService {
requestId: string,
headers: Record<string, string>,
): Promise<CodeReviewStatusResponse> {
const url = getKiloUrlFromToken(`https://api.matterai.so/codereview/${requestId}`, this.kilocodeToken)
let url: string

if (this.enterpriseHost && this.enterpriseApiKey) {
// Use enterprise host and API key
url = `${this.enterpriseHost.replace(/\/$/, "")}/codereview/${requestId}`
} else {
// Use default MatterAI service
url = getKiloUrlFromToken(`https://api.matterai.so/codereview/${requestId}`, this.kilocodeToken)
}

const response = await axios.get<CodeReviewStatusResponse>(url, {
headers,
Expand Down
3 changes: 3 additions & 0 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1936,6 +1936,7 @@ ${prompt}
maxConcurrentFileReads,
allowVeryLargeReads, // kilocode_change
ghostServiceSettings, // kilocode_changes
codeReviewSettings,
condensingApiConfigId,
customCondensingPrompt,
codebaseIndexConfig,
Expand Down Expand Up @@ -2138,6 +2139,7 @@ ${prompt}
openRouterImageGenerationSelectedModel,
openRouterUseMiddleOutTransform,
featureRoomoteControlEnabled,
codeReviewSettings,
}
}

Expand Down Expand Up @@ -2385,6 +2387,7 @@ ${prompt}
openRouterImageApiKey: stateValues.openRouterImageApiKey,
kiloCodeImageApiKey: stateValues.kiloCodeImageApiKey,
openRouterImageGenerationSelectedModel: stateValues.openRouterImageGenerationSelectedModel,
codeReviewSettings: stateValues.codeReviewSettings, // kilocode_change
featureRoomoteControlEnabled: (() => {
try {
const userSettings = CloudService.instance.getUserSettings()
Expand Down
48 changes: 46 additions & 2 deletions src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import delay from "delay"
import * as vscode from "vscode"
// kilocode_change start
import axios from "axios"
import { getKiloUrlFromToken, isGlobalStateKey } from "@roo-code/types"
import { codeReviewSettingsSchema, CodeReviewSettings, getKiloUrlFromToken, isGlobalStateKey } from "@roo-code/types"
import { getAppUrl } from "@roo-code/types"
import {
MaybeTypedWebviewMessage,
Expand Down Expand Up @@ -1025,7 +1025,13 @@ export const webviewMessageHandler = async (
// Call the code review API
const { CodeReviewService } = await import("../kilocode/api/codeReviewService")
const state = await provider.getState()
const codeReviewService = new CodeReviewService(state.apiConfiguration?.kilocodeToken || "")

// Use enterprise settings if available, otherwise fall back to default
const enterpriseHost = state.codeReviewSettings?.enterpriseHost
const enterpriseApiKey = state.codeReviewSettings?.enterpriseApiKey
const apiToken = state.apiConfiguration?.kilocodeToken || ""

const codeReviewService = new CodeReviewService(apiToken, enterpriseHost, enterpriseApiKey)
const results = await codeReviewService.requestCodeReview({
git_diff: gitDiff,
git_owner: gitMetadata.gitOwner,
Expand Down Expand Up @@ -2228,6 +2234,44 @@ ${comment.suggestion}
vscode.commands.executeCommand("axon-code.ghost.reload")
break
// kilocode_change end
case "codeReviewSettings": {
const values = message.values as CodeReviewSettings
const validated = codeReviewSettingsSchema.parse(values)
await updateGlobalState("codeReviewSettings", validated)

// If both host and key are provided, ping the server
if (validated.enterpriseHost && validated.enterpriseApiKey) {
try {
const pingUrl = `${validated.enterpriseHost?.replace(/\/$/, "")}/codereview/ping`
const response = await axios.get(pingUrl, {
headers: {
Authorization: `Bearer ${validated.enterpriseApiKey}`,
},
})

if (response.data?.valid === true) {
// Send toast message to webview
provider.postMessageToWebview({
type: "showToast",
toastType: "success",
toastMessage: "Enterprise server connected successfully",
})
}
} catch (error) {
console.error("Failed to ping enterprise server:", error)
// Send error toast message to webview
provider.postMessageToWebview({
type: "showToast",
toastType: "error",
toastMessage: "Failed to connect to enterprise server. Please check your host URL and API key.",
})
}
}

provider.postMessageToWebview({ type: "state", state: await provider.getStateToPostToWebview() })
break
}
// kilocode_change end
case "includeTaskHistoryInEnhance":
await updateGlobalState("includeTaskHistoryInEnhance", message.bool ?? true)
await provider.postStateToWebview()
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "%extension.displayName%",
"description": "%extension.description%",
"publisher": "matterai",
"version": "4.210.1",
"version": "4.210.2",
"icon": "assets/icons/matterai-ic.png",
"galleryBanner": {
"color": "#FFFFFF",
Expand Down
24 changes: 9 additions & 15 deletions src/services/code-index/service-factory.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { TelemetryService } from "@roo-code/telemetry"
import { TelemetryEventName } from "@roo-code/types"
import { Ignore } from "ignore"
import * as vscode from "vscode"
import { OpenAiEmbedder } from "./embedders/openai"
import { CodeIndexOllamaEmbedder } from "./embedders/ollama"
import { OpenAICompatibleEmbedder } from "./embedders/openai-compatible"
import { GeminiEmbedder } from "./embedders/gemini"
import { MistralEmbedder } from "./embedders/mistral"
import { VercelAiGatewayEmbedder } from "./embedders/vercel-ai-gateway"
import { EmbedderProvider, getDefaultModelId, getModelDimension } from "../../shared/embeddingModels"
import { HttpVectorStore } from "./vector-store/http-vector-store"
import { codeParser, DirectoryScanner, FileWatcher } from "./processors"
import { ICodeParser, IEmbedder, IFileWatcher, IVectorStore } from "./interfaces"
import { CodeIndexConfigManager } from "./config-manager"
import { CacheManager } from "./cache-manager"
import { RooIgnoreController } from "../../core/ignore/RooIgnoreController"
import { Ignore } from "ignore"
import { t } from "../../i18n"
import { TelemetryService } from "@roo-code/telemetry"
import { TelemetryEventName } from "@roo-code/types"
import { EmbedderProvider, getDefaultModelId, getModelDimension } from "../../shared/embeddingModels"
import { Package } from "../../shared/package"
import { CacheManager } from "./cache-manager"
import { CodeIndexConfigManager } from "./config-manager"
import { BATCH_SEGMENT_THRESHOLD } from "./constants"
import { MatterAiEmbedder } from "./embedders/matterai"
import { ICodeParser, IEmbedder, IFileWatcher, IVectorStore } from "./interfaces"
import { codeParser, DirectoryScanner, FileWatcher } from "./processors"
import { HttpVectorStore } from "./vector-store/http-vector-store"

/**
* Factory class responsible for creating and configuring code indexing service dependencies.
Expand Down
4 changes: 4 additions & 0 deletions src/shared/ExtensionMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export interface ExtensionMessage {
| "showTimestamps" // kilocode_change
| "organizationSwitchResult"
| "implementPlan" // kilocode_change: Plan mode implementation
| "showToast" // kilocode_change
text?: string
// kilocode_change start
payload?:
Expand Down Expand Up @@ -230,6 +231,8 @@ export interface ExtensionMessage {
subtitle?: string
message: string
} // kilocode_change
toastType?: "success" | "error" | "info" | "warning" // kilocode_change
toastMessage?: string // kilocode_change
url?: string // kilocode_change
keybindings?: Record<string, string> // kilocode_change
setting?: string
Expand Down Expand Up @@ -368,6 +371,7 @@ export type ExtensionState = Pick<
| "openRouterImageGenerationSelectedModel"
| "includeTaskHistoryInEnhance"
| "reasoningBlockCollapsed"
| "codeReviewSettings"
> & {
version: string
clineMessages: ClineMessage[]
Expand Down
4 changes: 4 additions & 0 deletions src/shared/WebviewMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,8 @@ export interface WebviewMessage {
| "applyAllCodeReviewFixes"
| "getGitChangesForReview"
| "gitChangesForReview"
| "codeReviewSettings" // kilocode_change
| "showToast" // kilocode_change
// kilocode_change end
text?: string
editedMessageContent?: string
Expand All @@ -340,6 +342,8 @@ export interface WebviewMessage {
subtitle?: string
message: string
}
toastType?: "success" | "error" | "info" | "warning" // kilocode_change
toastMessage?: string // kilocode_change
mcpId?: string
toolNames?: string[]
autoApprove?: boolean
Expand Down
27 changes: 23 additions & 4 deletions webview-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { TooltipProvider } from "./components/ui/tooltip"
import { STANDARD_TOOLTIP_DELAY } from "./components/ui/standard-tooltip"
import { useKiloIdentity } from "./utils/kilocode/useKiloIdentity"
import { MemoryWarningBanner } from "./kilocode/MemoryWarningBanner"
import { ToastProvider, useToast } from "./components/ui/toast"

type Tab = "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account" | "cloud" | "profile" // kilocode_change: add "profile"

Expand Down Expand Up @@ -89,7 +90,9 @@ const App = () => {
renderContext,
mdmCompliant,
apiConfiguration, // kilocode_change
codeReviewSettings, // kilocode_change
} = useExtensionState()
const { showToast } = useToast()

// Create a persistent state manager
const marketplaceStateManager = useMemo(() => new MarketplaceViewStateManager(), [])
Expand Down Expand Up @@ -208,9 +211,16 @@ const App = () => {
if (message.type === "acceptInput") {
chatViewRef.current?.acceptInput()
}

if (message.type === "showToast" && message.toastType && message.toastMessage) {
showToast({
type: message.toastType,
message: message.toastMessage,
})
}
},
// kilocode_change: add tab
[tab, switchTab],
// kilocode_change: add tab and showToast
[tab, switchTab, showToast],
)

useEvent("message", onMessage)
Expand Down Expand Up @@ -276,7 +286,14 @@ const App = () => {

// Do not conditionally load ChatView, it's expensive and there's state we
// don't want to lose (user input, disableInput, askResponse promise, etc.)
return showWelcome ? (
// Allow settings access even when showWelcome is true

// Check if enterprise credentials are set (for review-only mode)
const hasEnterpriseHost = !!codeReviewSettings?.enterpriseHost
const hasEnterpriseApiKey = !!codeReviewSettings?.enterpriseApiKey
const hasEnterpriseCredentials = hasEnterpriseHost && hasEnterpriseApiKey

return showWelcome && tab !== "settings" && !hasEnterpriseCredentials ? (
<WelcomeView />
) : (
<>
Expand Down Expand Up @@ -404,7 +421,9 @@ const AppWithProviders = () => (
<TranslationProvider>
<QueryClientProvider client={queryClient}>
<TooltipProvider delayDuration={STANDARD_TOOLTIP_DELAY}>
<App />
<ToastProvider>
<App />
</ToastProvider>
</TooltipProvider>
</QueryClientProvider>
</TranslationProvider>
Expand Down
Loading
Loading