Skip to content

Commit

Permalink
clean up and add TODO
Browse files Browse the repository at this point in the history
  • Loading branch information
abeatrix committed Jan 7, 2025
1 parent 2e5d77e commit 0d55e7c
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 46 deletions.
6 changes: 3 additions & 3 deletions vscode/src/chat/agentic/CodyTool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { URI } from 'vscode-uri'
import { mockLocalStorage } from '../../services/LocalStorageProvider'
import type { ContextRetriever } from '../chat-view/ContextRetriever'
import { CodyTool, OpenCtxTool } from './CodyTool'
import { CodyToolProvider, ToolFactory, type ToolStatusCallback } from './CodyToolProvider'
import { CodyToolProvider, TestToolFactory, type ToolStatusCallback } from './CodyToolProvider'
import { toolboxManager } from './ToolboxManager'

const mockCallback: ToolStatusCallback = {
Expand All @@ -32,7 +32,7 @@ class TestTool extends CodyTool {
}

describe('CodyTool', () => {
let factory: ToolFactory
let factory: TestToolFactory
let mockSpan: any
let mockContextRetriever: ContextRetriever

Expand All @@ -51,7 +51,7 @@ describe('CodyTool', () => {
retrieveContext: vi.fn().mockResolvedValue(mockRretrievedResult),
} as unknown as ContextRetriever

factory = new ToolFactory(mockContextRetriever)
factory = new TestToolFactory(mockContextRetriever)
mockSpan = {}
factory.register({
name: 'TestTool',
Expand Down
4 changes: 3 additions & 1 deletion vscode/src/chat/agentic/CodyTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class SearchTool extends CodyTool {
subTag: ps`query`,
},
prompt: {
instruction: ps`Perform a symbol query search in the codebase-Do not support nature language search`,
instruction: ps`Perform a symbol query search in the codebase-Do not support natural language search`,
placeholder: ps`SEARCH_QUERY`,
examples: [
ps`Locate a function found in an error log: \`<TOOLSEARCH><query>function name</query></TOOLSEARCH>\``,
Expand Down Expand Up @@ -277,6 +277,8 @@ export class OpenCtxTool extends CodyTool {
const results: ContextItem[] = []
const idObject: Pick<ContextMentionProviderMetadata, 'id'> = { id: this.provider.id }
try {
// TODO: Investigate if we can batch queries for better performance.
// For example, would it cause issues if we fire 10 requests to a OpenCtx provider for fetching Linear?
for (const query of queries) {
const mention = parseMentionQuery(query, idObject)
// First get the items without content
Expand Down
12 changes: 6 additions & 6 deletions vscode/src/chat/agentic/CodyToolProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { URI } from 'vscode-uri'
import { mockLocalStorage } from '../../services/LocalStorageProvider'
import type { ContextRetriever } from '../chat-view/ContextRetriever'
import { CodyTool, type CodyToolConfig } from './CodyTool'
import { CodyToolProvider, type ToolConfiguration, ToolFactory } from './CodyToolProvider'
import { CodyToolProvider, TestToolFactory, type ToolConfiguration } from './CodyToolProvider'
import { toolboxManager } from './ToolboxManager'

const localStorageData: { [key: string]: unknown } = {}
Expand Down Expand Up @@ -108,7 +108,7 @@ describe('CodyToolProvider', () => {
})

describe('ToolFactory', () => {
let factory: ToolFactory
let factory: TestToolFactory

class TestCodyTool extends CodyTool {
protected async execute(): Promise<ContextItem[]> {
Expand Down Expand Up @@ -143,7 +143,7 @@ describe('ToolFactory', () => {
const mockContextRetriever = {
retrieveContext: vi.fn().mockResolvedValue(mockRretrievedResult),
} as unknown as ContextRetriever
factory = new ToolFactory(mockContextRetriever)
factory = new TestToolFactory(mockContextRetriever)
})

it('should register and create tools correctly', () => {
Expand All @@ -158,15 +158,15 @@ describe('ToolFactory', () => {
expect(unknownTool).toBeUndefined()
})

it('should return all registered tool instances', () => {
it('should return all registered tool instances including default tools', () => {
const testToolConfig1 = { ...testToolConfig, name: 'TestTool1' }
const testToolConfig2 = { ...testToolConfig, name: 'TestTool2' }

factory.register(testToolConfig1)
factory.register(testToolConfig2)

const tools = factory.getInstances()
expect(tools.length).toBe(2)
expect(tools.every(tool => tool instanceof TestCodyTool)).toBe(true)
expect(tools.length).toBeGreaterThan(2)
expect(tools.filter(tool => tool instanceof TestCodyTool).length).toBe(2)
})
})
78 changes: 42 additions & 36 deletions vscode/src/chat/agentic/CodyToolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,26 @@ export interface ToolConfiguration extends CodyToolConfig {
* - Handles both default tools (Search, File, CLI, Memory) and OpenCtx tools
* - Manages tool configuration and instantiation with proper context
*/
export class ToolFactory {
class ToolFactory {
private tools: Map<string, ToolConfiguration> = new Map()

constructor(private contextRetriever: Retriever) {}
constructor(private contextRetriever: Retriever) {
// Register default tools
for (const [name, { tool, useContextRetriever }] of Object.entries(TOOL_CONFIGS)) {
this.register({
name,
...tool.prototype.config,
createInstance: useContextRetriever
? (_, contextRetriever) => {
if (!contextRetriever) {
throw new Error(`Context retriever required for ${name}`)
}
return new tool(contextRetriever)
}
: () => new tool(),
})
}
}

public register(toolConfig: ToolConfiguration): void {
this.tools.set(toolConfig.name, toolConfig)
Expand Down Expand Up @@ -146,50 +162,40 @@ export class ToolFactory {
* - Access tools using getTools()
* - Set up OpenCtx integration using setupOpenCtxProviderListener()
*/
export namespace CodyToolProvider {
export let factory: ToolFactory
let openCtxSubscription: Unsubscribable | undefined
export class CodyToolProvider {
public factory: ToolFactory

private static instance: CodyToolProvider | undefined
public static openCtxSubscription: Unsubscribable | undefined

export function initialize(contextRetriever: Retriever): void {
factory = new ToolFactory(contextRetriever)
initializeRegistry()
private constructor(contextRetriever: Retriever) {
this.factory = new ToolFactory(contextRetriever)
}

export function getTools(): CodyTool[] {
const instances = factory.getInstances()
return instances
public static initialize(contextRetriever: Retriever): void {
CodyToolProvider.instance = new CodyToolProvider(contextRetriever)
}

export function setupOpenCtxProviderListener(): void {
if (!openCtxSubscription && factory && openCtx.controller) {
openCtxSubscription = openCtx.controller
.metaChanges({}, {})
.pipe(map(providers => providers.filter(p => !!p.mentions).map(openCtxProviderMetadata)))
.subscribe(providerMeta => factory?.createOpenCtxTools(providerMeta))
}
public static getTools(): CodyTool[] {
return CodyToolProvider.instance?.factory.getInstances() ?? []
}

function initializeRegistry(): void {
for (const [name, { tool, useContextRetriever }] of Object.entries(TOOL_CONFIGS)) {
factory.register({
name,
...tool.prototype.config,
createInstance: useContextRetriever
? (_, contextRetriever) => {
if (!contextRetriever) {
throw new Error(`Context retriever required for ${name}`)
}
return new tool(contextRetriever)
}
: () => new tool(),
})
public static setupOpenCtxProviderListener(): void {
const provider = CodyToolProvider.instance
if (provider && !CodyToolProvider.openCtxSubscription && openCtx.controller) {
CodyToolProvider.openCtxSubscription = openCtx.controller
.metaChanges({}, {})
.pipe(map(providers => providers.filter(p => !!p.mentions).map(openCtxProviderMetadata)))
.subscribe(providerMeta => provider.factory.createOpenCtxTools(providerMeta))
}
}

export function dispose(): void {
if (openCtxSubscription) {
openCtxSubscription.unsubscribe()
openCtxSubscription = undefined
public static dispose(): void {
if (CodyToolProvider.openCtxSubscription) {
CodyToolProvider.openCtxSubscription.unsubscribe()
CodyToolProvider.openCtxSubscription = undefined
}
}
}

export class TestToolFactory extends ToolFactory {}
1 change: 1 addition & 0 deletions vscode/src/chat/agentic/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ps } from '@sourcegraph/cody-shared'
import type { CodyToolConfig } from './CodyTool'

// Known tools that can be used in the chat.
export const OPENCTX_TOOL_CONFIG: Record<string, CodyToolConfig> = {
web: {
title: 'Web (OpenCtx)',
Expand Down

0 comments on commit 0d55e7c

Please sign in to comment.