Skip to content

Commit 92852e5

Browse files
committed
feat: add prompt suggest tool for contextual suggestions
- Add prompt_suggest tool for providing contextual next step suggestions - Add PromptSuggest UI component to display suggestions - Update capabilities and rules with prompt suggest documentation - Add XML utils for processing prompt suggestions - Add prompt_suggest to experiment flags - Update tool groups to include prompt suggest - Install fast-xml-parser for XML handling
1 parent 3917371 commit 92852e5

File tree

17 files changed

+415
-17
lines changed

17 files changed

+415
-17
lines changed

package-lock.json

Lines changed: 27 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@
325325
"diff": "^5.2.0",
326326
"diff-match-patch": "^1.0.5",
327327
"fast-deep-equal": "^3.1.3",
328+
"fast-xml-parser": "^4.5.1",
328329
"fastest-levenshtein": "^1.0.16",
329330
"get-folder-size": "^5.0.0",
330331
"globby": "^14.0.2",

src/core/Cline.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import { McpHub } from "../services/mcp/McpHub"
6464
import crypto from "crypto"
6565
import { insertGroups } from "./diff/insert-groups"
6666
import { EXPERIMENT_IDS, experiments as Experiments } from "../shared/experiments"
67+
import { parseXml } from "../utils/xml"
6768

6869
const cwd =
6970
vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) ?? path.join(os.homedir(), "Desktop") // may or may not exist but fs checking existence would immediately ask for permission which would be bad UX, need to come up with a better solution
@@ -1136,6 +1137,9 @@ export class Cline {
11361137
const modeName = getModeBySlug(mode, customModes)?.name ?? mode
11371138
return `[${block.name} in ${modeName} mode: '${message}']`
11381139
}
1140+
case "prompt_suggest": {
1141+
return `[${block.name}`
1142+
}
11391143
}
11401144
}
11411145

@@ -2434,6 +2438,64 @@ export class Cline {
24342438
break
24352439
}
24362440
}
2441+
case "prompt_suggest": {
2442+
const result: string | undefined = block.params.result
2443+
try {
2444+
if (block.partial) {
2445+
await this.ask(
2446+
"prompt_suggest",
2447+
removeClosingTag("result", result),
2448+
block.partial,
2449+
).catch(() => {})
2450+
break
2451+
} else {
2452+
if (!result) {
2453+
this.consecutiveMistakeCount++
2454+
pushToolResult(await this.sayAndCreateMissingParamError("prompt_suggest", "result"))
2455+
break
2456+
}
2457+
2458+
type Suggest = {
2459+
suggest: string
2460+
}
2461+
2462+
let parsedSuggest: {
2463+
suggest: Suggest[] | Suggest
2464+
}
2465+
2466+
try {
2467+
parsedSuggest = parseXml(result, ["result.suggest"]) as {
2468+
suggest: Suggest[] | Suggest
2469+
}
2470+
} catch (error) {
2471+
this.consecutiveMistakeCount++
2472+
await this.say("error", `Failed to parse operations: ${error.message}`)
2473+
pushToolResult(formatResponse.toolError("Invalid operations xml format"))
2474+
break
2475+
}
2476+
2477+
this.consecutiveMistakeCount = 0
2478+
2479+
const normalizedSuggest = Array.isArray(parsedSuggest?.suggest)
2480+
? parsedSuggest.suggest
2481+
: [parsedSuggest?.suggest].filter((sug): sug is Suggest => sug !== undefined)
2482+
2483+
const { text, images } = await this.ask(
2484+
"prompt_suggest",
2485+
JSON.stringify(normalizedSuggest),
2486+
false,
2487+
)
2488+
await this.say("user_feedback", text ?? "", images)
2489+
pushToolResult(
2490+
formatResponse.toolResult(`<user_feedback>\n${text}\n</user_feedback>`, images),
2491+
)
2492+
break
2493+
}
2494+
} catch (error) {
2495+
await handleError("prompt suggest", error)
2496+
break
2497+
}
2498+
}
24372499
case "switch_mode": {
24382500
const mode_slug: string | undefined = block.params.mode_slug
24392501
const reason: string | undefined = block.params.reason

src/core/assistant-message/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const toolUseNames = [
2525
"attempt_completion",
2626
"switch_mode",
2727
"new_task",
28+
"prompt_suggest",
2829
] as const
2930

3031
// Converts array of tool call names into a union type ("execute_command" | "read_file" | ...)
@@ -138,3 +139,8 @@ export interface NewTaskToolUse extends ToolUse {
138139
name: "new_task"
139140
params: Partial<Pick<Record<ToolParamName, string>, "mode" | "message">>
140141
}
142+
143+
export interface PromptSuggestToolUse extends ToolUse {
144+
name: "prompt_suggest"
145+
params: Partial<Pick<Record<ToolParamName, string>, "result">>
146+
}

0 commit comments

Comments
 (0)