Skip to content
Draft
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
2 changes: 1 addition & 1 deletion pnpm-lock.yaml

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

1 change: 1 addition & 0 deletions src/core/prompts/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export function getToolDescriptionsForMode(
// Conditionally exclude codebase_search if feature is disabled or not configured
if (
!codeIndexManager ||
!codeIndexManager?.isManagedIndexingAvailable || // kilocode_change
!(codeIndexManager.isFeatureEnabled && codeIndexManager.isFeatureConfigured && codeIndexManager.isInitialized)
) {
tools.delete("codebase_search")
Expand Down
3 changes: 1 addition & 2 deletions src/core/tools/codebaseSearchTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,7 @@ ${jsonResult.results
(result) => `File path: ${result.filePath}
Score: ${result.score}
Lines: ${result.startLine}-${result.endLine}
Code Chunk: ${result.codeChunk}
`,
${result.codeChunk ? `Code Chunk: ${result.codeChunk}\n` : ""}`, // kilocode_change - don't include code chunk managed indexing
)
.join("\n")}`

Expand Down
84 changes: 84 additions & 0 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,10 @@ ${prompt}
}

await TelemetryService.instance.updateIdentity(providerSettings.kilocodeToken ?? "") // kilocode_change

// kilocode_change start Update code index with new Kilo org props
await this.updateCodeIndexWithKiloProps()
// kilocode_change end
} else {
await this.updateGlobalState("listApiConfigMeta", await this.providerSettingsManager.listConfig())
}
Expand Down Expand Up @@ -1423,6 +1427,10 @@ ${prompt}
await this.postStateToWebview()
await TelemetryService.instance.updateIdentity(providerSettings.kilocodeToken ?? "") // kilocode_change

// kilocode_change start Update code index with new Kilo org props
await this.updateCodeIndexWithKiloProps()
// kilocode_change end

if (providerSettings.apiProvider) {
this.emit(RooCodeEventName.ProviderProfileChanged, { name, provider: providerSettings.apiProvider })
}
Expand Down Expand Up @@ -3350,4 +3358,80 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
return vscode.Uri.file(filePath).toString()
}
}

// kilocode_change start
/**
* Updates the code index manager with current Kilo org credentials
* This should be called whenever the API configuration changes
*/
private async updateCodeIndexWithKiloProps(): Promise<void> {
try {
const { apiConfiguration } = await this.getState()

// Only proceed if we have both required credentials
if (!apiConfiguration.kilocodeToken || !apiConfiguration.kilocodeOrganizationId) {
return
}

// Get kilocodeTesterWarningsDisabledUntil from context
const kilocodeTesterWarningsDisabledUntil = this.contextProxy.getValue(
"kilocodeTesterWarningsDisabledUntil",
)

// Fetch organization settings to check if code indexing is enabled
const { OrganizationService } = await import("../../services/kilocode/OrganizationService")
const organization = await OrganizationService.fetchOrganization(
apiConfiguration.kilocodeToken,
apiConfiguration.kilocodeOrganizationId,
kilocodeTesterWarningsDisabledUntil,
)

// Check if code indexing is enabled for this organization
const codeIndexingEnabled = OrganizationService.isCodeIndexingEnabled(organization)

if (!codeIndexingEnabled) {
this.log("[updateCodeIndexWithKiloProps] Code indexing is disabled for this organization")
return
}

// Get project ID from Kilo config
const kiloConfig = await this.getKiloConfig()
const projectId = kiloConfig?.project?.id

if (!projectId) {
this.log("[updateCodeIndexWithKiloProps] No projectId found in Kilo config, skipping code index update")
return
}

// Get or create the code index manager for the current workspace
let codeIndexManager = this.getCurrentWorkspaceCodeIndexManager()

// If manager doesn't exist yet, it will be created on first access
// We need to ensure it's initialized with the context proxy
if (!codeIndexManager) {
// Try to get the manager again, which will create it if workspace exists
const workspacePath = this.cwd
if (workspacePath) {
codeIndexManager = CodeIndexManager.getInstance(this.context, workspacePath)
}
}

if (codeIndexManager) {
// Set the Kilo org props - code indexing is enabled
codeIndexManager.setKiloOrgCodeIndexProps({
kilocodeToken: apiConfiguration.kilocodeToken,
organizationId: apiConfiguration.kilocodeOrganizationId,
projectId,
})

// Initialize the manager with context proxy if not already initialized
if (!codeIndexManager.isInitialized) {
await codeIndexManager.initialize(this.contextProxy)
}
}
} catch (error) {
this.log(`Failed to update code index with Kilo props: ${error}`)
}
}
// kilocode_change end
}
146 changes: 146 additions & 0 deletions src/core/webview/__tests__/webviewMessageHandler.codeIndex.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { describe, it, expect, vi, beforeEach } from "vitest"
import { webviewMessageHandler } from "../webviewMessageHandler"
import type { ClineProvider } from "../ClineProvider"

// Mock the getKiloConfig method
vi.mock("../../../utils/path", () => ({
getWorkspacePath: vi.fn(() => "/test/workspace"),
}))

describe("webviewMessageHandler - requestIndexingStatus with managed indexing", () => {
let mockProvider: any
let mockManager: any

beforeEach(() => {
vi.clearAllMocks()

mockManager = {
getCurrentStatus: vi.fn(() => ({
systemStatus: "Standby",
message: "",
processedItems: 0,
totalItems: 0,
currentItemUnit: "items",
workspacePath: "/test/workspace",
})),
getKiloOrgCodeIndexProps: vi.fn(() => null),
setKiloOrgCodeIndexProps: vi.fn(),
workspacePath: "/test/workspace",
}

mockProvider = {
getCurrentWorkspaceCodeIndexManager: vi.fn(() => mockManager),
getState: vi.fn(async () => ({
apiConfiguration: {
kilocodeToken: "test-token",
kilocodeOrganizationId: "test-org-id",
},
})),
getKiloConfig: vi.fn(async () => ({
project: {
id: "test-project-id",
},
})),
postMessageToWebview: vi.fn(),
log: vi.fn(),
} as unknown as ClineProvider
})

it("should set Kilo org props before getting status when organization credentials are available", async () => {
await webviewMessageHandler(mockProvider, {
type: "requestIndexingStatus",
})

// Verify that setKiloOrgCodeIndexProps was called with correct props
expect(mockManager.setKiloOrgCodeIndexProps).toHaveBeenCalledWith({
kilocodeToken: "test-token",
organizationId: "test-org-id",
projectId: "test-project-id",
})

// Verify that status was retrieved and sent to webview
expect(mockManager.getCurrentStatus).toHaveBeenCalled()
expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({
type: "indexingStatusUpdate",
values: expect.objectContaining({
systemStatus: "Standby",
}),
})
})

it("should not set Kilo org props if they are already set", async () => {
// Mock that props are already set
mockManager.getKiloOrgCodeIndexProps.mockReturnValue({
kilocodeToken: "test-token",
organizationId: "test-org-id",
projectId: "test-project-id",
})

await webviewMessageHandler(mockProvider, {
type: "requestIndexingStatus",
})

// Verify that setKiloOrgCodeIndexProps was NOT called
expect(mockManager.setKiloOrgCodeIndexProps).not.toHaveBeenCalled()

// Verify that status was still retrieved
expect(mockManager.getCurrentStatus).toHaveBeenCalled()
})

it("should not set Kilo org props if organization credentials are missing", async () => {
mockProvider.getState = vi.fn(async () => ({
apiConfiguration: {
// No kilocodeToken or kilocodeOrganizationId
},
}))

await webviewMessageHandler(mockProvider, {
type: "requestIndexingStatus",
})

// Verify that setKiloOrgCodeIndexProps was NOT called
expect(mockManager.setKiloOrgCodeIndexProps).not.toHaveBeenCalled()

// Verify that status was still retrieved
expect(mockManager.getCurrentStatus).toHaveBeenCalled()
})

it("should not set Kilo org props if project ID is missing", async () => {
mockProvider.getKiloConfig = vi.fn(async () => ({
project: {
// No id
},
}))

await webviewMessageHandler(mockProvider, {
type: "requestIndexingStatus",
})

// Verify that setKiloOrgCodeIndexProps was NOT called
expect(mockManager.setKiloOrgCodeIndexProps).not.toHaveBeenCalled()

// Verify that status was still retrieved
expect(mockManager.getCurrentStatus).toHaveBeenCalled()
})

it("should send error status when no workspace is open", async () => {
mockProvider.getCurrentWorkspaceCodeIndexManager = vi.fn(() => null)

await webviewMessageHandler(mockProvider, {
type: "requestIndexingStatus",
})

// Verify error status was sent
expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({
type: "indexingStatusUpdate",
values: {
systemStatus: "Error",
message: "orchestrator.indexingRequiresWorkspace",
processedItems: 0,
totalItems: 0,
currentItemUnit: "items",
workerspacePath: undefined,
},
})
})
})
Loading
Loading