Skip to content

Commit

Permalink
feat: Add debug mode and enhance logging for large outputs
Browse files Browse the repository at this point in the history
  • Loading branch information
coolcline committed Feb 16, 2025
1 parent 67baf9a commit 34a83d6
Show file tree
Hide file tree
Showing 6 changed files with 507 additions and 133 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@
}
},
"description": "Settings for VSCode Language Model API"
},
"coolcline.debugMode": {
"type": "boolean",
"default": false,
"description": "启用调试模式,将在输出面板显示详细日志"
}
}
}
Expand Down
108 changes: 85 additions & 23 deletions src/core/CoolCline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import crypto from "crypto"
import { insertGroups } from "./diff/insert-groups"
import { EXPERIMENT_IDS, experiments as Experiments } from "../shared/experiments"
import { CheckpointService } from "../services/checkpoints/CheckpointService"
import { logger } from "../utils/logging"

const cwd =
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
Expand Down Expand Up @@ -241,34 +242,95 @@ export class CoolCline {
await this.saveCoolClineMessages()
}

private static readonly MAX_MESSAGE_SIZE = 1000000 // 1MB 限制
private static readonly MAX_MESSAGE_PREVIEW_SIZE = 100000 // 预览大小限制

private async saveCoolClineMessages() {
try {
const filePath = path.join(await this.ensureTaskDirectoryExists(), GlobalFileNames.uiMessages)
await fs.writeFile(filePath, JSON.stringify(this.coolclineMessages))
// combined as they are in ChatView
const apiMetrics = getApiMetrics(
combineApiRequests(combineCommandSequences(this.coolclineMessages.slice(1))),
)
const taskMessage = this.coolclineMessages[0] // first message is always the task say
const lastRelevantMessage =
this.coolclineMessages[
findLastIndex(
this.coolclineMessages,
(m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task"),
)
]
await this.providerRef.deref()?.updateTaskHistory({
id: this.taskId,
ts: lastRelevantMessage.ts,
task: taskMessage.text ?? "",
tokensIn: apiMetrics.totalTokensIn,
tokensOut: apiMetrics.totalTokensOut,
cacheWrites: apiMetrics.totalCacheWrites,
cacheReads: apiMetrics.totalCacheReads,
totalCost: apiMetrics.totalCost,

// 处理大型消息
const processedMessages = this.coolclineMessages.map((msg) => {
if (!msg.text) return msg

// 检查消息大小
if (msg.text.length > CoolCline.MAX_MESSAGE_SIZE) {
logger.warn("消息内容过大,将被截断", {
ctx: "coolcline",
messageType: msg.type,
messageLength: msg.text.length,
limit: CoolCline.MAX_MESSAGE_SIZE,
})

// 对于命令输出类型的消息,添加特殊提示
if (msg.type === "say" && msg.say === "command_output") {
return {
...msg,
text:
msg.text.substring(0, CoolCline.MAX_MESSAGE_PREVIEW_SIZE) +
"\n\n... [输出内容过长,已截断。建议使用其他工具查看完整输出,比如将输出重定向到文件:command > output.txt]",
}
}

// 其他类型消息的通用处理
return {
...msg,
text: msg.text.substring(0, CoolCline.MAX_MESSAGE_PREVIEW_SIZE) + "\n... [内容过长已截断]",
}
}
return msg
})

// 分块写入文件
try {
await fs.writeFile(filePath, JSON.stringify(processedMessages), "utf8")

// 更新任务历史
const apiMetrics = getApiMetrics(
combineApiRequests(combineCommandSequences(processedMessages.slice(1))),
)
const taskMessage = processedMessages[0]
const lastRelevantMessage =
processedMessages[
findLastIndex(
processedMessages,
(m) => !(m.ask === "resume_task" || m.ask === "resume_completed_task"),
)
]

await this.providerRef.deref()?.updateTaskHistory({
id: this.taskId,
ts: lastRelevantMessage.ts,
task: taskMessage.text ?? "",
tokensIn: apiMetrics.totalTokensIn,
tokensOut: apiMetrics.totalTokensOut,
cacheWrites: apiMetrics.totalCacheWrites,
cacheReads: apiMetrics.totalCacheReads,
totalCost: apiMetrics.totalCost,
})
} catch (error) {
// 如果写入失败,尝试只保存最近的消息
logger.error("保存完整消息失败,尝试只保存最近的消息", {
ctx: "coolcline",
error: error instanceof Error ? error.message : String(error),
})

const recentMessages = processedMessages.slice(-10) // 只保留最近的10条消息
await fs.writeFile(filePath, JSON.stringify(recentMessages), "utf8")

// 通知用户
vscode.window.showWarningMessage(
"由于消息内容过大,只保存了最近的消息。建议清理历史记录或开启新的任务。",
)
}
} catch (error) {
console.error("Failed to save coolcline messages:", error)
logger.error("保存消息完全失败", {
ctx: "coolcline",
error: error instanceof Error ? error.message : String(error),
})

// 通知用户但继续运行
vscode.window.showErrorMessage("保存消息历史失败。建议保存重要内容到文件并重新开始任务。")
}
}

Expand Down
22 changes: 21 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as vscode from "vscode"
import { logger, initializeLogger } from "./utils/logging"

import { CoolClineProvider } from "./core/webview/CoolClineProvider"
import { createCoolClineAPI } from "./exports"
Expand All @@ -21,12 +22,31 @@ let extensionContext: vscode.ExtensionContext

// This method is called when your extension is activated.
// Your extension is activated the very first time the command is executed.
export function activate(context: vscode.ExtensionContext) {
export async function activate(context: vscode.ExtensionContext) {
extensionContext = context
outputChannel = vscode.window.createOutputChannel("CoolCline")
context.subscriptions.push(outputChannel)
outputChannel.appendLine("CoolCline extension activated")

// 初始化日志系统
try {
await initializeLogger(context)
logger.info("CoolCline extension activated", { ctx: "extension" })
} catch (error) {
const errorMessage = `日志系统初始化失败: ${error instanceof Error ? error.message : String(error)}`
outputChannel.appendLine(errorMessage)
console.error(errorMessage)

// 尝试记录更多诊断信息
try {
const storageUri = context.globalStorageUri
outputChannel.appendLine(`存储路径: ${storageUri.fsPath}`)
console.log("存储路径:", storageUri.fsPath)
} catch (e) {
outputChannel.appendLine(`无法获取存储路径: ${e instanceof Error ? e.message : String(e)}`)
}
}

// Get default commands from configuration.
const defaultCommands = vscode.workspace.getConfiguration("coolcline").get<string[]>("allowedCommands") || []

Expand Down
Loading

0 comments on commit 34a83d6

Please sign in to comment.