Skip to content

Commit

Permalink
wip - apply feedback 2
Browse files Browse the repository at this point in the history
  • Loading branch information
abeatrix committed Jan 6, 2025
1 parent 848120d commit 0fda5f5
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 58 deletions.
14 changes: 11 additions & 3 deletions lib/shared/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,12 +466,20 @@ export interface FireworksCodeCompletionParams {

export interface AgentToolboxSettings {
/**
* The agent ID that user has currently enabled.
* The agent that user has currently enabled.
*/
agent?: string
agent?: {
/**
* The name of the agent that user has currently enabled. E.g. "deep-cody"
*/
name?: string
}
/**
* Whether the user has enabled terminal context.
* Defaulted to undefined if shell context is not enabled by site admin via feature flag.
*/
shell?: boolean
shell?: {
enabled: boolean
error?: string
}
}
4 changes: 2 additions & 2 deletions vscode/src/chat/agentic/CodyTool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ describe('CodyTool', () => {
})

it('should register all default tools based on toolbox settings', () => {
const mockedToolboxSettings = { agent: 'mock-agent', shell: true }
const mockedToolboxSettings = { agent: { name: 'mock-agent' }, shell: { enabled: true } }
vi.spyOn(toolboxManager, 'getSettings').mockReturnValue(mockedToolboxSettings)
const localStorageData: { [key: string]: unknown } = {}
mockLocalStorage({
Expand All @@ -226,7 +226,7 @@ describe('CodyTool', () => {
expect(tools.some(t => t.config.title.includes('Terminal'))).toBeTruthy()

// Disable shell and check if terminal tool is removed.
mockedToolboxSettings.shell = false
mockedToolboxSettings.shell.enabled = false
vi.spyOn(toolboxManager, 'getSettings').mockReturnValue(mockedToolboxSettings)
const newTools = CodyToolProvider.getTools()
expect(newTools.some(t => t.config.title.includes('Terminal'))).toBeFalsy()
Expand Down
10 changes: 8 additions & 2 deletions vscode/src/chat/agentic/CodyToolProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,19 @@ describe('CodyToolProvider', () => {
})

it('should not include CLI tool if shell is disabled', () => {
vi.spyOn(toolboxManager, 'getSettings').mockReturnValue({ agent: 'deep-cody', shell: false })
vi.spyOn(toolboxManager, 'getSettings').mockReturnValue({
agent: { name: 'deep-cody' },
shell: { enabled: false },
})
const tools = CodyToolProvider.getTools()
expect(tools.some(tool => tool.config.title === 'Terminal')).toBe(false)
})

it('should include CLI tool if shell is enabled', () => {
vi.spyOn(toolboxManager, 'getSettings').mockReturnValue({ agent: 'deep-cody', shell: true })
vi.spyOn(toolboxManager, 'getSettings').mockReturnValue({
agent: { name: 'deep-cody' },
shell: { enabled: true },
})
const tools = CodyToolProvider.getTools()
expect(tools.some(tool => tool.config.title === 'Terminal')).toBe(true)
})
Expand Down
16 changes: 12 additions & 4 deletions vscode/src/chat/agentic/CodyToolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,16 @@ export class ToolFactory {

private generateToolName(provider: ContextMentionProviderMetadata): string {
const suffix = provider.id.includes('modelcontextprotocol') ? 'MCP' : ''
const title = provider.title.replace(' ', '').split('/').at(-1)
return 'TOOL' + title?.toUpperCase().replace(/[^a-zA-Z0-9]/g, '') + suffix
return (
'TOOL' +
provider.title
.split('/')
.pop()
?.replace(/\s+/g, '')
?.toUpperCase()
?.replace(/[^A-Z0-9]/g, '') +
suffix
)
}

private getToolConfig(provider: ContextMentionProviderMetadata): CodyToolConfig {
Expand Down Expand Up @@ -151,7 +159,7 @@ export namespace CodyToolProvider {
}

export function setupOpenCtxProviderListener(): void {
if (!openCtx.controller) {
if (!openCtx.controller || !factory) {
console.error('OpenCtx controller not available')
}
if (openCtxSubscription || !openCtx.controller) {
Expand All @@ -161,7 +169,7 @@ export namespace CodyToolProvider {
openCtxSubscription = openCtx.controller
.metaChanges({}, {})
.pipe(map(providers => providers.filter(p => !!p.mentions).map(openCtxProviderMetadata)))
.subscribe(providerMeta => factory.createOpenCtxTools(providerMeta))
.subscribe(providerMeta => factory?.createOpenCtxTools(providerMeta))
}

function initializeRegistry(): void {
Expand Down
29 changes: 20 additions & 9 deletions vscode/src/chat/agentic/ToolboxManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type StoredToolboxSettings = {
* NOTE: This is a Singleton class.
*/
class ToolboxManager {
private static readonly STORAGE_KEY = 'CODY_CHATAGENTS_TOOLBOX_SETTINGS'
private static readonly STORAGE_KEY = 'CODYAGENT_TOOLBOX_SETTINGS'
private static instance?: ToolboxManager

private constructor() {
Expand All @@ -51,8 +51,8 @@ class ToolboxManager {
private getStoredUserSettings(): StoredToolboxSettings {
return (
localStorage.get<StoredToolboxSettings>(ToolboxManager.STORAGE_KEY) ?? {
agent: undefined,
shell: this.shellConfig.user,
agent: this.isEnabled ? 'deep-cody' : undefined,
shell: false,
}
)
}
Expand All @@ -62,20 +62,31 @@ class ToolboxManager {
return null
}
const { agent, shell } = this.getStoredUserSettings()
const isShellEnabled = this.shellConfig.instance && this.shellConfig.client ? shell : undefined
return {
agent,
agent: { name: agent },
// Only show shell option if it's supported by instance and client.
shell: this.shellConfig.instance && this.shellConfig.client ? shell : undefined,
shell: { enabled: isShellEnabled ?? false },
}
}

public async updateToolboxSettings(settings: AgentToolboxSettings): Promise<void> {
public async updateSettings(settings: AgentToolboxSettings): Promise<void> {
logDebug('ToolboxManager', 'Updating toolbox settings', { verbose: settings })
await localStorage.set(ToolboxManager.STORAGE_KEY, settings)
await localStorage.set(ToolboxManager.STORAGE_KEY, {
agent: settings.agent?.name,
shell: settings.shell?.enabled ?? false,
})
this.changeNotifications.next()
}

public readonly settings: Observable<AgentToolboxSettings | null> = combineLatest(
/**
* Returns a real-time Observable stream of toolbox settings that updates when any of the following changes:
* - Feature flags
* - User subscription
* - Available models
* - Manual settings updates
* Use this when you need to react to settings changes over time.
*/
public readonly observable: Observable<AgentToolboxSettings | null> = combineLatest(
featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCody),
featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.ContextAgentDefaultChatModel),
featureFlagProvider.evaluatedFeatureFlag(FeatureFlag.DeepCodyShellContext),
Expand Down
6 changes: 3 additions & 3 deletions vscode/src/chat/chat-view/ChatController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
editorState,
intent: detectedIntent,
manuallySelectedIntent: manuallySelectedIntent ? detectedIntent : undefined,
agent: toolboxManager.getSettings()?.agent,
agent: toolboxManager.getSettings()?.agent?.name,
})
this.postViewTranscript({ speaker: 'assistant' })

Expand Down Expand Up @@ -1544,10 +1544,10 @@ export class ChatController implements vscode.Disposable, vscode.WebviewViewProv
userProductSubscription.pipe(
map(value => (value === pendingOperation ? null : value))
),
toolboxSettings: () => toolboxManager.settings,
toolboxSettings: () => toolboxManager.observable,
updateToolboxSettings: settings => {
return promiseFactoryToObservable(async () => {
await toolboxManager.updateToolboxSettings(settings)
await toolboxManager.updateSettings(settings)
})
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,50 +79,48 @@ export const ToolboxButton: FC<ToolboxButtonProps> = memo(({ settings, api }) =>
<div className="tw-flex tw-flex-1 tw-w-full tw-items-center tw-justify-between">
<h3 className="tw-text-sm">Self-Reflection Context Agent</h3>
<Switch
checked={!!settingsForm.agent}
checked={!!settingsForm.agent?.name}
onChange={() =>
setSettingsForm({
...settingsForm,
agent: settingsForm.agent
? undefined
: 'deep-cody',
agent: {
name: settingsForm.agent?.name
? undefined
: 'deep-cody', // TODO: update name when finalized.
},
})
}
/>
</div>
<div className="tw-text-sm tw-mb-4 tw-text-muted-foreground">
{ToolboxOptionText.agentic}
</div>
{settings.shell !== undefined && (
<>
<div className="tw-flex tw-flex-1 tw-w-full tw-items-center tw-justify-between">
<h3 className="tw-text-sm">
Terminal Context Agent
</h3>
<Switch
checked={settingsForm.shell}
disabled={settingsForm.agent === undefined}
onChange={() =>
setSettingsForm({
...settingsForm,
shell:
!!settingsForm.agent &&
!settingsForm.shell,
})
}
/>
</div>
<div
className="tw-text-sm tw-bg-red-100 tw-border tw-border-red-400 tw-text-red-700 tw-px-2 tw-py-1 tw-rounded"
role="alert"
>
Enable with caution as mistakes are possible.
</div>
<div className="tw-text-sm tw-mb-4 tw-text-muted-foreground">
{ToolboxOptionText.terminal}
</div>
</>
)}
<div className="tw-flex tw-flex-1 tw-w-full tw-items-center tw-justify-between">
<h3 className="tw-text-sm">Terminal Context Agent</h3>
<Switch
checked={settingsForm.shell?.enabled}
disabled={settingsForm.agent?.name === undefined}
onChange={() =>
setSettingsForm({
...settingsForm,
shell: {
enabled:
!!settingsForm.agent?.name &&
!settingsForm.shell?.enabled,
},
})
}
/>
</div>
<div
className="tw-text-sm tw-bg-red-100 tw-border tw-border-red-400 tw-text-red-700 tw-px-2 tw-py-1 tw-rounded"
role="alert"
>
Enable with caution as mistakes are possible.
</div>
<div className="tw-text-sm tw-mb-4 tw-text-muted-foreground">
{ToolboxOptionText.terminal}
</div>
</div>
</div>
</CommandGroup>
Expand Down Expand Up @@ -153,7 +151,7 @@ export const ToolboxButton: FC<ToolboxButtonProps> = memo(({ settings, api }) =>
>
<Button variant="ghost" className="!tw-p-2 tw-relative">
<BrainIcon size={16} strokeWidth={1.25} className="tw-w-8 tw-h-8" />
{settings.agent ? (
{settings.agent?.name ? (
<span className="tw-absolute tw-top-0 tw-right-0 tw-w-2 tw-h-2 tw-rounded-full tw-bg-green-500 tw-animate-[pulse_5s_ease-in-out_infinite]" />
) : (
<span className="tw-absolute tw-top-0 tw-right-0 tw-w-2 tw-h-2 tw-rounded-full tw-bg-red-500 tw-animate-[pulse_5s_ease-in-out_infinite]" />
Expand Down

0 comments on commit 0fda5f5

Please sign in to comment.