diff --git a/docs/系统流程-用户输入处理.md b/docs/系统流程-用户输入处理.md new file mode 100644 index 0000000..49cc565 --- /dev/null +++ b/docs/系统流程-用户输入处理.md @@ -0,0 +1,159 @@ +# 系统流程:用户输入处理与文件目录内容管理 + +本文档详细说明了当用户发送聊天消息时,系统如何处理用户输入并管理庞大的文件目录内容。这个流程对于理解Bolt系统的核心功能至关重要。 + +## 1. 用户输入处理 (Chat.client.tsx) + +当用户发送消息时,系统会执行以下步骤: + +```typescript +const sendMessage = async (_event: React.UIEvent, messageInput?: string) => { + const _input = messageInput || input; + if (_input.length === 0 || isLoading) { + return; + } + + // 保存所有未保存的文件 + await workbenchStore.saveAllFiles(); + + // 获取文件修改信息 + const fileModifications = workbenchStore.getFileModifcations(); + + chatStore.setKey('aborted', false); + runAnimation(); + + if (fileModifications !== undefined) { + // 如果有文件修改,将修改信息添加到用户输入中 + const diff = fileModificationsToHTML(fileModifications); + append({ role: 'user', content: `${diff}\n\n${_input}` }); + workbenchStore.resetAllFileModifications(); + } else { + append({ role: 'user', content: _input }); + } + + setInput(''); + resetEnhancer(); + textareaRef.current?.blur(); +}; +``` + +这个过程确保了所有文件修改都被保存并包含在发送给AI的消息中。 + +## 2. 文件修改管理 (files.ts) + +`FilesStore` 类负责跟踪和管理文件修改: + +```typescript +export class FilesStore { + #modifiedFiles: Map = new Map(); + + async saveFile(filePath: string, content: string) { + const webcontainer = await this.#webcontainer; + const relativePath = nodePath.relative(webcontainer.workdir, filePath); + + if (!relativePath) { + throw new Error(`EINVAL: invalid file path, write '${relativePath}'`); + } + + const oldContent = this.getFile(filePath)?.content; + if (!oldContent) { + unreachable('Expected content to be defined'); + } + + await webcontainer.fs.writeFile(relativePath, content); + + if (!this.#modifiedFiles.has(filePath)) { + this.#modifiedFiles.set(filePath, oldContent); + } + + this.files.setKey(filePath, { type: 'file', content, isBinary: false }); + } + + getFileModifications() { + return computeFileModifications(this.files.get(), this.#modifiedFiles); + } + + resetFileModifications() { + this.#modifiedFiles.clear(); + } +} +``` + +这个类不仅管理文件的保存,还跟踪文件的修改历史,以便生成差异信息。 + +## 3. 文件差异计算 (diff.ts) + +`computeFileModifications` 函数用于计算文件的修改: + +```typescript +export function computeFileModifications(files: FileMap, modifiedFiles: Map) { + const modifications: FileModifications = {}; + let hasModifiedFiles = false; + + for (const [filePath, originalContent] of modifiedFiles) { + const file = files[filePath]; + if (file?.type !== 'file') continue; + + const unifiedDiff = diffFiles(filePath, originalContent, file.content); + if (!unifiedDiff) continue; + + hasModifiedFiles = true; + + if (unifiedDiff.length > file.content.length) { + modifications[filePath] = { type: 'file', content: file.content }; + } else { + modifications[filePath] = { type: 'diff', content: unifiedDiff }; + } + } + + return hasModifiedFiles ? modifications : undefined; +} +``` + +这个函数比较原始文件内容和当前内容,生成差异信息或决定是否直接使用新的文件内容。 + +## 4. WebContainer 集成 (index.ts) + +WebContainer 用于在浏览器中模拟文件系统: + +```typescript +export let webcontainer: Promise = new Promise(() => { + // noop for ssr +}); + +if (!import.meta.env.SSR) { + webcontainer = Promise.resolve() + .then(() => { + return WebContainer.boot({ workdirName: WORK_DIR_NAME }); + }) + .then((webcontainer) => { + webcontainerContext.loaded = true; + return webcontainer; + }); +} +``` + +这确保了 WebContainer 只在客户端环境中初始化,为文件系统操作提供了基础。 + +## 5. 文件内容处理和发送 + +在发送消息给AI时,系统会执行以下步骤: + +1. 保存所有未保存的文件 (`workbenchStore.saveAllFiles()`) +2. 获取文件修改信息 (`workbenchStore.getFileModifcations()`) +3. 如果有修改,生成差异HTML (`fileModificationsToHTML(fileModifications)`) +4. 将差异信息和用户输入组合成一条消息 +5. 发送组合后的消息给AI + +这个过程确保了AI能够获得最新的项目状态,包括所有recent的文件修改。 + +## 结论 + +Bolt系统通过精心设计的流程,实现了高效的用户输入处理和文件目录内容管理: + +1. 实时跟踪文件修改 +2. 智能计算文件差异 +3. 将相关修改信息与用户输入结合 +4. 利用WebContainer模拟真实的文件系统操作 + +这种方法不仅确保了AI获得最新和最相关的项目信息,还优化了数据传输,只发送必要的修改内容。这种设计使得Bolt能够处理大型项目,同时保持响应速度和准确性。