mirror of
https://github.com/stackblitz/bolt.new
synced 2025-06-26 18:17:50 +00:00
docs
This commit is contained in:
parent
5b64cc4172
commit
884d546c29
159
docs/系统流程-用户输入处理.md
Normal file
159
docs/系统流程-用户输入处理.md
Normal 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能够处理大型项目,同时保持响应速度和准确性。
|
||||||
Loading…
Reference in New Issue
Block a user