Add codespell support (config, workflow to detect/not fix) and make it fix some typos (#2939)

* Add github action to codespell main on push and PRs

* Add rudimentary codespell config

* run codespell throughout fixing typos automagically (but ignoring overall fail due to ambigous ones)

=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w || :",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^

* Do interactive fixing of some ambigous typos

=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w -i 3 -C 4",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^

* Fix Formatting

---------

Co-authored-by: Dennis Bartlett <bartlett.dc.1@gmail.com>
This commit is contained in:
Yaroslav Halchenko 2025-04-16 22:53:16 -04:00 committed by GitHub
parent 6c5b99d304
commit 45b1666325
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 63 additions and 32 deletions

6
.codespellrc Normal file
View File

@ -0,0 +1,6 @@
[codespell]
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
skip = .git*,*.svg,package-lock.json,*.css,.codespellrc,locales
check-hidden = true
ignore-regex = (\b(optIn|isTaller)\b|https://\S+)
# ignore-words-list =

25
.github/workflows/codespell.yml vendored Normal file
View File

@ -0,0 +1,25 @@
# Codespell configuration is within .codespellrc
---
name: Codespell
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Annotate locations with typos
uses: codespell-project/codespell-problem-matcher@v1
- name: Codespell
uses: codespell-project/actions-codespell@v2

View File

@ -58,7 +58,7 @@
- Add recommended models for Cline provider
- Add ability to detect when user edits files manually so Cline knows to re-read, leading to reduced diff edit errors
- Add improvements to file mention searching for faster searching
- Add scoring logic to file mentions to sort and exlcude results based on relevance
- Add scoring logic to file mentions to sort and exclude results based on relevance
- Add Support for Bytedance Doubao (Thanks Tunixer!)
- Fix to prevent duplicate BOM (Thanks bamps53!)
@ -536,7 +536,7 @@
- Adds "Always allow read-only operations" setting to let Claude read files and view directories without needing approval (off by default)
- Implement sliding window context management to keep tasks going past 200k tokens
- Adds Google Cloud Vertex AI support and updates Claude 3.5 Sonnet max output to 8192 tokens for all providers.
- Improves system prompt to gaurd against lazy edits (less "//rest of code here")
- Improves system prompt to guard against lazy edits (less "//rest of code here")
## [1.3.0]

View File

@ -50,7 +50,7 @@ export class OpenAiNativeHandler implements ApiHandler {
case "o1":
case "o1-preview":
case "o1-mini": {
// o1 doesnt support streaming, non-1 temp, or system prompt
// o1 doesn't support streaming, non-1 temp, or system prompt
const response = await this.client.chat.completions.create({
model: model.id,
messages: [{ role: "user", content: systemPrompt }, ...convertToOpenAiMessages(messages)],

View File

@ -123,7 +123,7 @@ export function parseAssistantMessage(assistantMessage: string) {
contentBlocks.push(currentToolUse)
}
// Note: it doesnt matter if check for currentToolUse or currentTextContent, only one of them will be defined since only one can be partial at a time
// Note: it doesn't matter if check for currentToolUse or currentTextContent, only one of them will be defined since only one can be partial at a time
if (currentTextContent) {
// stream did not complete text content, add it as partial
contentBlocks.push(currentTextContent)

View File

@ -537,7 +537,7 @@ export class ContextManager {
// we can assume that thisExistingFileReads does not have many entries
if (!thisExistingFileReads.includes(filePath)) {
// meaning we havent already replaced this file read
// meaning we haven't already replaced this file read
const entireMatch = match[0] // The entire matched string
@ -590,7 +590,7 @@ export class ContextManager {
) {
const pattern = new RegExp(`(<final_file_content path="[^"]*">)[\\s\\S]*?(</final_file_content>)`)
// check if this exists in the text, it wont exist if the user rejects the file change for example
// check if this exists in the text, it won't exist if the user rejects the file change for example
if (pattern.test(secondBlockText)) {
const replacementText = secondBlockText.replace(pattern, `$1 ${formatResponse.duplicateFileReadNotice()} $2`)
const indices = fileReadIndices.get(filePath) || []
@ -741,7 +741,7 @@ export class ContextManager {
let totalCharactersSaved = 0
for (let i = startIndex; i < endIndex; i++) {
// looping over the outer indicies of messages
// looping over the outer indices of messages
const message = apiMessages[i]
if (!message.content) {
@ -782,7 +782,7 @@ export class ContextManager {
totalCharCount += originalTextLength
} else {
// meaning there was an update to this text previously, but we didnt just alter it
// meaning there was an update to this text previously, but we didn't just alter it
totalCharCount += latestUpdate[2][0].length
}
} else {
@ -790,7 +790,7 @@ export class ContextManager {
totalCharCount += block.text.length
}
} else {
// reach here if there's no alterations for this outer index, meaning each inner index wont have any changes either
// reach here if there's no alterations for this outer index, meaning each inner index won't have any changes either
totalCharCount += block.text.length
}
} else if (block.type === "image" && block.source) {

View File

@ -504,7 +504,7 @@ export class Controller {
break
}
case "checkpointRestore": {
await this.cancelTask() // we cannot alter message history say if the task is active, as it could be in the middle of editing a file or running a command, which expect the ask to be responded to rather than being superceded by a new message eg add deleted_api_reqs
await this.cancelTask() // we cannot alter message history say if the task is active, as it could be in the middle of editing a file or running a command, which expect the ask to be responded to rather than being superseded by a new message eg add deleted_api_reqs
// cancel task waits for any open editor to be reverted and starts a new cline instance
if (message.number) {
// wait for messages to be loaded
@ -1740,7 +1740,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
}
}
// if we tried to get a task that doesn't exist, remove it from state
// FIXME: this seems to happen sometimes when the json file doesnt save to disk for some reason
// FIXME: this seems to happen sometimes when the json file doesn't save to disk for some reason
await this.deleteTaskFromState(id)
throw new Error("Task not found")
}
@ -1917,7 +1917,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
// conversation history to send in API requests
/*
It seems that some API messages do not comply with vscode state requirements. Either the Anthropic library is manipulating these values somehow in the backend in a way thats creating cyclic references, or the API returns a function or a Symbol as part of the message content.
It seems that some API messages do not comply with vscode state requirements. Either the Anthropic library is manipulating these values somehow in the backend in a way that's creating cyclic references, or the API returns a function or a Symbol as part of the message content.
VSCode docs about state: "The value must be JSON-stringifyable ... value — A value. MUST not contain cyclic references."
For now we'll store the conversation history in memory, and if we need to store in state directly we'd need to do a manual conversion to ensure proper json stringification.
*/

View File

@ -440,7 +440,7 @@ export class Task {
return
}
// TODO: handle if this is called from outside original workspace, in which case we need to show user error message we cant show diff outside of workspace?
// TODO: handle if this is called from outside original workspace, in which case we need to show user error message we can't show diff outside of workspace?
if (!this.checkpointTracker && !this.checkpointTrackerErrorMessage) {
try {
this.checkpointTracker = await CheckpointTracker.create(this.taskId, this.context.globalStorageUri.fsPath)
@ -885,7 +885,7 @@ export class Task {
await this.overwriteClineMessages(modifiedClineMessages)
this.clineMessages = await getSavedClineMessages(this.getContext(), this.taskId)
// Now present the cline messages to the user and ask if they want to resume (NOTE: we ran into a bug before where the apiconversationhistory wouldnt be initialized when opening a old task, and it was because we were waiting for resume)
// Now present the cline messages to the user and ask if they want to resume (NOTE: we ran into a bug before where the apiconversationhistory wouldn't be initialized when opening a old task, and it was because we were waiting for resume)
// This is important in case the user deletes messages without resuming the task first
this.apiConversationHistory = await getSavedApiConversationHistory(this.getContext(), this.taskId)
@ -2433,7 +2433,7 @@ export class Task {
try {
if (block.partial) {
if (this.shouldAutoApproveTool(block.name)) {
// since depending on an upcoming parameter, requiresApproval this may become an ask - we cant partially stream a say prematurely. So in this particular case we have to wait for the requiresApproval parameter to be completed before presenting it.
// since depending on an upcoming parameter, requiresApproval this may become an ask - we can't partially stream a say prematurely. So in this particular case we have to wait for the requiresApproval parameter to be completed before presenting it.
// await this.say(
// "command",
// removeClosingTag("command", command),
@ -2479,7 +2479,7 @@ export class Task {
let didAutoApprove = false
// If the model says this command is safe and auto aproval for safe commands is true, execute the command
// If the model says this command is safe and auto approval for safe commands is true, execute the command
// If the model says the command is risky, but *BOTH* auto approve settings are true, execute the command
const autoApproveResult = this.shouldAutoApproveTool(block.name)
const [autoApproveSafe, autoApproveAll] = Array.isArray(autoApproveResult)
@ -3003,7 +3003,7 @@ export class Task {
)
} else {
// last message is completion_result
// we have command string, which means we have the result as well, so finish it (doesnt have to exist yet)
// we have command string, which means we have the result as well, so finish it (doesn't have to exist yet)
await this.say("completion_result", removeClosingTag("result", result), undefined, false)
await this.saveCheckpoint(true)
await addNewChangesFlagToLastCompletionResultMessage()
@ -3039,7 +3039,7 @@ export class Task {
let commandResult: ToolResponse | undefined
if (command) {
if (lastMessage && lastMessage.ask !== "command") {
// havent sent a command message yet so first send completion_result then command
// haven't sent a command message yet so first send completion_result then command
await this.say("completion_result", result, undefined, false)
await this.saveCheckpoint(true)
await addNewChangesFlagToLastCompletionResultMessage()
@ -3408,7 +3408,7 @@ export class Task {
if (this.didRejectTool) {
// userContent has a tool rejection, so interrupt the assistant's response to present the user's feedback
assistantMessage += "\n\n[Response interrupted by user feedback]"
// this.userMessageContentReady = true // instead of setting this premptively, we allow the present iterator to finish and set userMessageContentReady when its ready
// this.userMessageContentReady = true // instead of setting this preemptively, we allow the present iterator to finish and set userMessageContentReady when its ready
break
}
@ -3463,7 +3463,7 @@ export class Task {
partialBlocks.forEach((block) => {
block.partial = false
})
// this.assistantMessageContent.forEach((e) => (e.partial = false)) // cant just do this bc a tool could be in the middle of executing ()
// this.assistantMessageContent.forEach((e) => (e.partial = false)) // can't just do this bc a tool could be in the middle of executing ()
if (partialBlocks.length > 0) {
this.presentAssistantMessage() // if there is content to update then it will complete and update this.userMessageContentReady to true, which we pwaitfor before making the next request. all this is really doing is presenting the last partial message that we just set to complete
}

View File

@ -193,7 +193,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
/*
content security policy of your webview to only allow scripts that have a specific nonce
create a content security policy meta tag so that only loading scripts with a nonce is allowed
As your extension grows you will likely want to add custom styles, fonts, and/or images to your webview. If you do, you will need to update the content security policy meta tag to explicity allow for these resources. E.g.
As your extension grows you will likely want to add custom styles, fonts, and/or images to your webview. If you do, you will need to update the content security policy meta tag to explicitly allow for these resources. E.g.
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; font-src ${webview.cspSource}; img-src ${webview.cspSource} https:; script-src 'nonce-${nonce}';">
- 'unsafe-inline' is required for styles due to vscode-webview-toolkit's dynamic style injection
- since we pass base64 images to the webview, we need to specify img-src ${webview.cspSource} data:;

View File

@ -61,7 +61,7 @@ class DiagnosticsMonitor {
return currentDiagnostics
}
let timeout = 300 // only way this happens is if theres no errors
let timeout = 300 // only way this happens is if there's no errors
// if diagnostics contain existing errors (since the check above didn't trigger) then it's likely cline just did something that should have fixed the error, so we'll give a longer grace period for diagnostics to catch up
const hasErrors = currentDiagnostics.some(([_, diagnostics]) =>

View File

@ -289,7 +289,7 @@ export class DiffViewProvider {
updatedDocument.positionAt(updatedDocument.getText().length),
)
edit.replace(updatedDocument.uri, fullRange, this.originalContent ?? "")
// Apply the edit and save, since contents shouldnt have changed this wont show in local history unless of course the user made changes and saved during the edit
// Apply the edit and save, since contents shouldn't have changed this won't show in local history unless of course the user made changes and saved during the edit
await vscode.workspace.applyEdit(edit)
await updatedDocument.save()
console.log(`File ${absolutePath} has been reverted to its original content.`)

View File

@ -95,7 +95,7 @@ export class TerminalProcess extends EventEmitter<TerminalProcessEvents> {
}
// first few chunks could be the command being echoed back, so we must ignore
// note this means that 'echo' commands wont work
// note this means that 'echo' commands won't work
if (!didOutputNonCommand) {
const lines = data.split("\n")
for (let i = 0; i < lines.length; i++) {
@ -145,7 +145,7 @@ export class TerminalProcess extends EventEmitter<TerminalProcessEvents> {
isCompiling ? PROCESS_HOT_TIMEOUT_COMPILING : PROCESS_HOT_TIMEOUT_NORMAL,
)
// For non-immediately returning commands we want to show loading spinner right away but this wouldnt happen until it emits a line break, so as soon as we get any output we emit "" to let webview know to show spinner
// For non-immediately returning commands we want to show loading spinner right away but this wouldn't happen until it emits a line break, so as soon as we get any output we emit "" to let webview know to show spinner
if (!didEmitEmptyLine && !this.fullOutput && data) {
this.emit("line", "") // empty line to indicate start of command output stream
didEmitEmptyLine = true

View File

@ -120,7 +120,7 @@ export async function searchWorkspaceFiles(
limit: limit * 2,
})
// The min threshold value will require some testing and tuning as the scores are exponential, and exagerated
// The min threshold value will require some testing and tuning as the scores are exponential, and exaggerated
const MIN_SCORE_THRESHOLD = 100
// Filter results by score and map to original items

View File

@ -157,7 +157,7 @@ async function parseFile(
formattedOutput += "|----\n"
}
// Only add the first line of the definition
// query captures includes the definition name and the definition implementation, but we only want the name (I found discrepencies in the naming structure for various languages, i.e. javascript names would be 'name' and typescript names would be 'name.definition)
// query captures includes the definition name and the definition implementation, but we only want the name (I found discrepancies in the naming structure for various languages, i.e. javascript names would be 'name' and typescript names would be 'name.definition)
if (name.includes("name") && lines[startLine]) {
formattedOutput += `${lines[startLine]}\n`
}

View File

@ -91,7 +91,7 @@ function getWindowsShellFromVSCode(): string | null {
// If the profile name indicates PowerShell, do version-based detection.
// In testing it was found these typically do not have a path, and this
// implementation manages to deductively get the corect version of PowerShell
// implementation manages to deductively get the correct version of PowerShell
if (defaultProfileName.toLowerCase().includes("powershell")) {
if (profile?.path) {
// If there's an explicit PowerShell path, return that

View File

@ -29,7 +29,7 @@ const linkContainerStyle: CSSProperties = { margin: "0" }
const linkStyle: CSSProperties = { display: "inline" }
/*
You must update the latestAnnouncementId in ClineProvider for new announcements to show to users. This new id will be compared with whats in state for the 'last announcement shown', and if it's different then the announcement will render. As soon as an announcement is shown, the id will be updated in state. This ensures that announcements are not shown more than once, even if the user doesn't close it themselves.
You must update the latestAnnouncementId in ClineProvider for new announcements to show to users. This new id will be compared with what's in state for the 'last announcement shown', and if it's different then the announcement will render. As soon as an announcement is shown, the id will be updated in state. This ensures that announcements are not shown more than once, even if the user doesn't close it themselves.
*/
const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
const minorVersion = version.split(".").slice(0, 2).join(".") // 2.0.0 -> 2.0

View File

@ -1153,7 +1153,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
display: "flex",
alignItems: "flex-center",
height: textAreaBaseHeight || 31,
bottom: 9.5, // should be 10 but doesnt look good on mac
bottom: 9.5, // should be 10 but doesn't look good on mac
zIndex: 2,
}}>
<div

View File

@ -114,7 +114,7 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
})
// If the field is the provider, save it immediately
// Neccesary for favorite model selection to work without undoing provider changes
// Necessary for favorite model selection to work without undoing provider changes
if (field === "apiProvider") {
vscode.postMessage({
type: "apiConfiguration",

View File

@ -27,7 +27,7 @@ class VSCodeAPIWrapper {
* @remarks When running webview code inside a web browser, postMessage will instead
* log the given message to the console.
*
* @param message Abitrary data (must be JSON serializable) to send to the extension context.
* @param message Arbitrary data (must be JSON serializable) to send to the extension context.
*/
public postMessage(message: WebviewMessage) {
if (this.vsCodeApi) {