Skip to content

Commit dac18d4

Browse files
committed
use vscode.lm tools
1 parent 57447fc commit dac18d4

File tree

16 files changed

+709
-31
lines changed

16 files changed

+709
-31
lines changed

.husky/pre-push

Lines changed: 0 additions & 29 deletions
This file was deleted.

packages/types/src/tool.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { z } from "zod"
44
* ToolGroup
55
*/
66

7-
export const toolGroups = ["read", "edit", "browser", "command", "mcp", "modes"] as const
7+
export const toolGroups = ["read", "edit", "browser", "command", "vsclmt", "mcp", "modes"] as const
88

99
export const toolGroupsSchema = z.enum(toolGroups)
1010

@@ -25,6 +25,7 @@ export const toolNames = [
2525
"list_files",
2626
"list_code_definition_names",
2727
"browser_action",
28+
"use_vsclmt",
2829
"use_mcp_tool",
2930
"access_mcp_resource",
3031
"ask_followup_question",

src/core/assistant-message/presentAssistantMessage.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { listCodeDefinitionNamesTool } from "../tools/listCodeDefinitionNamesToo
1717
import { searchFilesTool } from "../tools/searchFilesTool"
1818
import { browserActionTool } from "../tools/browserActionTool"
1919
import { executeCommandTool } from "../tools/executeCommandTool"
20+
import { useVSCLMT } from "../tools/vsclmt"
2021
import { useMcpToolTool } from "../tools/useMcpToolTool"
2122
import { accessMcpResourceTool } from "../tools/accessMcpResourceTool"
2223
import { askFollowupQuestionTool } from "../tools/askFollowupQuestionTool"
@@ -176,6 +177,8 @@ export async function presentAssistantMessage(cline: Task) {
176177
return `[${block.name} for '${block.params.path}']`
177178
case "browser_action":
178179
return `[${block.name} for '${block.params.action}']`
180+
case "use_vsclmt":
181+
return `[${block.name} for '${block.params.tool_name}']`
179182
case "use_mcp_tool":
180183
return `[${block.name} for '${block.params.server_name}']`
181184
case "access_mcp_resource":
@@ -431,6 +434,9 @@ export async function presentAssistantMessage(cline: Task) {
431434
case "execute_command":
432435
await executeCommandTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag)
433436
break
437+
case "use_vsclmt":
438+
await useVSCLMT(cline, block, askApproval, handleError, pushToolResult, removeClosingTag)
439+
break
434440
case "use_mcp_tool":
435441
await useMcpToolTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag)
436442
break

src/core/prompts/sections/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export { getSystemInfoSection } from "./system-info"
33
export { getObjectiveSection } from "./objective"
44
export { addCustomInstructions } from "./custom-instructions"
55
export { getSharedToolUseSection } from "./tool-use"
6+
export { getVSCLMTSection } from "./vsclmt"
67
export { getMcpServersSection } from "./mcp-servers"
78
export { getToolUseGuidelinesSection } from "./tool-use-guidelines"
89
export { getCapabilitiesSection } from "./capabilities"

src/core/prompts/sections/vsclmt.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { ToolInfo } from "../../../services/vsclm/VSCLMToolsService"
2+
3+
export function getVSCLMTSection(selectedVSCLMT: ToolInfo[]): string {
4+
if (!selectedVSCLMT || selectedVSCLMT.length === 0) {
5+
return ""
6+
}
7+
8+
const toolDescriptions = selectedVSCLMT
9+
.map((tool) => {
10+
const displayName = tool.displayName || tool.name
11+
const description = tool.description || tool.userDescription || "No description available"
12+
13+
let toolSection = `### ${displayName}
14+
**Provider Extension:** ${tool.providerExtensionDisplayName} (${tool.providerExtensionId})
15+
**Description:** ${description}
16+
17+
**Tool Name:** ${tool.name}`
18+
19+
// Add input schema information if available
20+
if (tool.inputSchema && typeof tool.inputSchema === "object") {
21+
try {
22+
const schemaStr = JSON.stringify(tool.inputSchema, null, 2)
23+
toolSection += `
24+
**Input Schema:**
25+
\`\`\`json
26+
${schemaStr}
27+
\`\`\``
28+
} catch (error) {
29+
// If schema can't be serialized, skip it
30+
console.log(`Error serializing input schema for tool ${tool.name}:`, error)
31+
}
32+
}
33+
34+
// Add tags if available
35+
if (tool.tags && tool.tags.length > 0) {
36+
toolSection += `
37+
**Tags:** ${tool.tags.join(", ")}`
38+
}
39+
40+
return toolSection
41+
})
42+
.join("\n\n")
43+
44+
return `## VS Code Language Model Tools
45+
46+
The following VS Code Language Model tools are available for use. You can invoke them using the \`use_vsclmt\` tool with the appropriate tool name and arguments.
47+
48+
${toolDescriptions}
49+
50+
**Usage:** To use any of these tools, use the \`use_vsclmt\` tool with the \`tool_name\` parameter set to the exact tool name shown above, and provide any required arguments as a JSON string in the \`arguments\` parameter.`
51+
}

src/core/prompts/system.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Mode, modes, defaultModeSlug, getModeBySlug, getGroupName, getModeSelec
77
import { DiffStrategy } from "../../shared/tools"
88
import { formatLanguage } from "../../shared/language"
99

10+
import { VSCLMToolsService } from "../../services/vsclm/VSCLMToolsService"
1011
import { McpHub } from "../../services/mcp/McpHub"
1112
import { CodeIndexManager } from "../../services/code-index/manager"
1213

@@ -18,6 +19,7 @@ import {
1819
getSystemInfoSection,
1920
getObjectiveSection,
2021
getSharedToolUseSection,
22+
getVSCLMTSection,
2123
getMcpServersSection,
2224
getToolUseGuidelinesSection,
2325
getCapabilitiesSection,
@@ -31,6 +33,7 @@ async function generatePrompt(
3133
cwd: string,
3234
supportsComputerUse: boolean,
3335
mode: Mode,
36+
vsclmtService?: VSCLMToolsService,
3437
mcpHub?: McpHub,
3538
diffStrategy?: DiffStrategy,
3639
browserViewportSize?: string,
@@ -56,8 +59,9 @@ async function generatePrompt(
5659
const modeConfig = getModeBySlug(mode, customModeConfigs) || modes.find((m) => m.slug === mode) || modes[0]
5760
const { roleDefinition, baseInstructions } = getModeSelection(mode, promptComponent, customModeConfigs)
5861

59-
const [modesSection, mcpServersSection] = await Promise.all([
62+
const [modesSection, vsclmtSection, mcpServersSection] = await Promise.all([
6063
getModesSection(context),
64+
vsclmtService ? getVSCLMTSection(vsclmtService.getSelectedTools()) : Promise.resolve(""),
6165
modeConfig.groups.some((groupEntry) => getGroupName(groupEntry) === "mcp")
6266
? getMcpServersSection(mcpHub, effectiveDiffStrategy, enableMcpServerCreation)
6367
: Promise.resolve(""),
@@ -87,6 +91,8 @@ ${getToolDescriptionsForMode(
8791
8892
${getToolUseGuidelinesSection(codeIndexManager)}
8993
94+
${vsclmtSection}
95+
9096
${mcpServersSection}
9197
9298
${getCapabilitiesSection(cwd, supportsComputerUse, mcpHub, effectiveDiffStrategy, codeIndexManager)}
@@ -108,6 +114,7 @@ export const SYSTEM_PROMPT = async (
108114
context: vscode.ExtensionContext,
109115
cwd: string,
110116
supportsComputerUse: boolean,
117+
vsclmtService?: VSCLMToolsService,
111118
mcpHub?: McpHub,
112119
diffStrategy?: DiffStrategy,
113120
browserViewportSize?: string,
@@ -182,6 +189,7 @@ ${customInstructions}`
182189
cwd,
183190
supportsComputerUse,
184191
currentMode.slug,
192+
vsclmtService,
185193
mcpHub,
186194
effectiveDiffStrategy,
187195
browserViewportSize,

src/core/prompts/tools/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getListCodeDefinitionNamesDescription } from "./list-code-definition-na
1717
import { getBrowserActionDescription } from "./browser-action"
1818
import { getAskFollowupQuestionDescription } from "./ask-followup-question"
1919
import { getAttemptCompletionDescription } from "./attempt-completion"
20+
import { getVSCLMTDescription } from "./vsclmt"
2021
import { getUseMcpToolDescription } from "./use-mcp-tool"
2122
import { getAccessMcpResourceDescription } from "./access-mcp-resource"
2223
import { getSwitchModeDescription } from "./switch-mode"
@@ -26,6 +27,7 @@ import { CodeIndexManager } from "../../../services/code-index/manager"
2627

2728
// Map of tool names to their description functions
2829
const toolDescriptionMap: Record<string, (args: ToolArgs) => string | undefined> = {
30+
use_vsclmt: (args) => getVSCLMTDescription(args),
2931
execute_command: (args) => getExecuteCommandDescription(args),
3032
read_file: (args) => getReadFileDescription(args),
3133
fetch_instructions: () => getFetchInstructionsDescription(),
@@ -134,6 +136,7 @@ export {
134136
getBrowserActionDescription,
135137
getAskFollowupQuestionDescription,
136138
getAttemptCompletionDescription,
139+
getVSCLMTDescription,
137140
getUseMcpToolDescription,
138141
getAccessMcpResourceDescription,
139142
getSwitchModeDescription,

src/core/prompts/tools/vsclmt.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ToolArgs } from "./types"
2+
3+
export function getVSCLMTDescription(args: ToolArgs): string {
4+
return `## use_vsclmt
5+
6+
Access and invoke VS Code Language Model tools that are selected and available in the current workspace.
7+
8+
Required parameters:
9+
- tool_name: The name of the VS Code LM tool to invoke
10+
11+
Optional parameters:
12+
- arguments: JSON string containing the arguments for the tool
13+
14+
The tool will:
15+
1. Validate that the specified VS Code LM tool is available and selected
16+
2. Parse and validate the provided arguments
17+
3. Invoke the tool using VS Code's native language model tool system
18+
4. Return the tool's result or any error messages
19+
20+
Use this tool to leverage VS Code's ecosystem of language model tools for enhanced functionality.
21+
22+
Example:
23+
<use_vsclmt>
24+
<tool_name>example-tool</tool_name>
25+
<arguments>{"param1": "value1", "param2": "value2"}</arguments>
26+
</use_vsclmt>`
27+
}

src/core/task/Task.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,7 @@ export class Task extends EventEmitter<ClineEvents> {
16151615
// kilocode_change end
16161616

16171617
/*private kilocode_change*/ async getSystemPrompt(): Promise<string> {
1618+
const vsclmtService = this.providerRef.deref()?.getVSCLMToolService()
16181619
const { mcpEnabled } = (await this.providerRef.deref()?.getState()) ?? {}
16191620
let mcpHub: McpHub | undefined
16201621
if (mcpEnabled ?? true) {
@@ -1666,6 +1667,7 @@ export class Task extends EventEmitter<ClineEvents> {
16661667
provider.context,
16671668
this.cwd,
16681669
(this.api.getModel().info.supportsComputerUse ?? false) && (browserToolEnabled ?? true),
1670+
vsclmtService,
16691671
mcpHub,
16701672
this.diffStrategy,
16711673
browserViewportSize,

src/core/tools/vsclmt.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import * as vscode from "vscode"
2+
import { formatResponse } from "../prompts/responses"
3+
import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools"
4+
import { Task } from "../task/Task"
5+
6+
export async function useVSCLMT(
7+
cline: Task,
8+
toolUse: ToolUse,
9+
askApproval: AskApproval,
10+
handleError: HandleError,
11+
pushToolResult: PushToolResult,
12+
removeClosingTag: RemoveClosingTag,
13+
): Promise<void> {
14+
const { tool_name, arguments: toolArgs } = toolUse.params
15+
16+
// Handle partial tool invocation (missing parameters)
17+
if (toolUse.partial) {
18+
const partialMessage = JSON.stringify({
19+
type: "vsclmt_tool",
20+
toolName: removeClosingTag("tool_name", tool_name),
21+
arguments: removeClosingTag("arguments", toolArgs),
22+
})
23+
24+
await cline.ask("tool", partialMessage, toolUse.partial).catch(() => {})
25+
return
26+
}
27+
28+
// Non-partial: require tool_name
29+
if (!tool_name) {
30+
cline.recordToolError("use_vsclmt")
31+
pushToolResult(await cline.sayAndCreateMissingParamError("use_vsclmt", "tool_name"))
32+
return
33+
}
34+
35+
// Get the vsclmt service from ClineProvider
36+
const provider = cline.providerRef.deref()
37+
const vsclmtService = provider?.getVSCLMToolService()
38+
39+
if (!vsclmtService) {
40+
pushToolResult(formatResponse.toolError("VS Code LM tool system not available"))
41+
return
42+
}
43+
44+
// Parse arguments if provided
45+
let parsedArgs: any = {}
46+
if (toolArgs) {
47+
try {
48+
parsedArgs = JSON.parse(toolArgs)
49+
} catch (error) {
50+
pushToolResult(formatResponse.toolError(`Invalid JSON arguments: ${error.message}`))
51+
return
52+
}
53+
}
54+
55+
try {
56+
// Check if tool is selected
57+
if (!vsclmtService.isToolSelected(tool_name)) {
58+
pushToolResult(
59+
formatResponse.toolError(
60+
`Tool '${tool_name}' is not selected for use. Please select it in the Tool Selection panel.`,
61+
),
62+
)
63+
return
64+
}
65+
66+
// Prepare tool invocation to get any user confirmation message
67+
const prepared = await vsclmtService.prepareToolInvocation(tool_name, parsedArgs)
68+
if (prepared?.confirmationMessages) {
69+
// Ask for approval with the tool's custom confirmation message
70+
const message =
71+
prepared.confirmationMessages.message instanceof vscode.MarkdownString
72+
? prepared.confirmationMessages.message.value
73+
: prepared.confirmationMessages.message
74+
75+
const confirmText = `${prepared.confirmationMessages.title}\n${message}`
76+
const approved = await askApproval("tool", confirmText)
77+
78+
if (!approved) {
79+
pushToolResult(formatResponse.toolDenied())
80+
return
81+
}
82+
}
83+
84+
// Invoke the tool with any progress message from preparation
85+
const result = await vsclmtService.invokeTool(tool_name, parsedArgs)
86+
87+
// Format the result for display
88+
let resultText: string
89+
if (typeof result === "string") {
90+
resultText = result
91+
} else if (result && typeof result === "object") {
92+
resultText = JSON.stringify(result, null, 2)
93+
} else {
94+
resultText = String(result)
95+
}
96+
97+
pushToolResult(`VS Code LM tool '${tool_name}' executed successfully:\n\n${resultText}`)
98+
} catch (error) {
99+
await handleError("VS Code LM tool invocation", error)
100+
pushToolResult(formatResponse.toolError(`Failed to invoke VS Code LM tool '${tool_name}': ${error.message}`))
101+
}
102+
}

0 commit comments

Comments
 (0)