This commit is contained in:
zyh 2024-10-19 09:56:43 +00:00
parent 5b64cc4172
commit 884d546c29

View File

@ -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<string, string> = 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<string, string>) {
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<WebContainer> = 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能够处理大型项目,同时保持响应速度和准确性。