Skip to content

Commit 592c718

Browse files
authored
Merge pull request #291 from ThinkInAIXYZ/dev
Release 0.1.0
2 parents efedf25 + 1a491e1 commit 592c718

File tree

271 files changed

+18660
-7607
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

271 files changed

+18660
-7607
lines changed

.cursor/rules/llm-agent-loop.mdc

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
description:
3+
globs: src/main/presenter/llmProviderPresenter/index.ts,src/main/presenter/llmProviderPresenter/baseProvider.ts
4+
alwaysApply: false
5+
---
6+
# LLM Agent Loop 和 Provider 架构
7+
8+
本文档概述了处理 LLM 流式补全的架构,特别关注涉及工具调用的 Agent 循环。
9+
10+
## 核心原则
11+
12+
1. **关注点分离 (Separation of Concerns):**
13+
* `src/main/presenter/llmProviderPresenter/index.ts`: 管理整体 Agent 循环、对话历史、通过 `McpPresenter` 执行工具、并通过 `eventBus` 与前端通信。
14+
* `src/main/presenter/llmProviderPresenter/providers/*.ts`: 每个 Provider 文件负责与特定的 LLM API 交互,处理特定于 Provider 的请求/响应格式,转换工具定义,管理原生与非原生工具调用机制(Prompt 包装),并将输出流标准化为通用事件格式。
15+
16+
2. **标准化流事件 (Standardized Stream Events):** Provider 实现 (`coreStream` 方法) 使用标准化接口 `yield` 事件,以将主循环与 Provider 的具体细节解耦。
17+
18+
3. **Provider 中的单次流式传输 (Single-Pass Streaming in Providers):** 每个 Provider 中的核心流式方法 (`coreStream`) 应为对话的每一轮执行*单次*流式 API 请求。它不应包含多轮工具调用的循环逻辑。
19+
20+
## 架构细节
21+
22+
### `llmProviderPresenter/index.ts` (`startStreamCompletion`)
23+
24+
* **Agent 循环:** 包含主要的 `while` 循环,管理对话流程,包括在需要时进行多轮 LLM 调用和工具使用。
25+
* **状态管理:** 在循环迭代中维护 `conversationMessages` 历史记录。
26+
* **Provider 交互:** 在每个循环迭代中调用 `provider.coreStream()` 方法。
27+
* **事件处理:**
28+
* 监听由 `coreStream` `yield` 的标准化事件。
29+
* 缓冲文本内容 (`currentContent`)。
30+
* 处理 `tool_call_start/chunk/end` 事件:
31+
* 收集完整的工具调用详细信息(id, name, arguments)。
32+
* 调用 `presenter.mcpPresenter.callTool` 执行工具。
33+
* 向前端发送带有工具调用状态(`tool_call: 'start' | 'end' | 'error'`)的 `STREAM_EVENTS.RESPONSE` 事件。
34+
* 将工具结果格式化为适合*下一次* LLM 调用的消息(例如,角色为 'tool' 或附加到用户消息)。
35+
* 设置 `needContinueConversation = true`。
36+
* 处理 `reasoning` 事件并通过 `STREAM_EVENTS.RESPONSE` 发送它们。
37+
* 处理 `text` 事件并通过 `STREAM_EVENTS.RESPONSE` 发送它们。
38+
* 处理 `image_data` 事件并通过 `STREAM_EVENTS.RESPONSE` 发送它们。
39+
* 处理 `usage` 事件并聚合它们。
40+
* 处理 `stop` 事件:
41+
* 如果 `stop_reason: 'tool_use'`,则添加缓冲的助手消息并准备下一次循环迭代。
42+
* 否则,添加最终的助手消息并跳出循环。
43+
* **循环控制:** 使用 `needContinueConversation` 和 `toolCallCount`(与 `MAX_TOOL_CALLS` 比较)来管理循环。
44+
* **前端通信:** 通过 `eventBus` 发送标准化的 `STREAM_EVENTS`(`RESPONSE`, `END`, `ERROR`)。
45+
46+
### Provider 实现 (`src/main/presenter/llmProviderPresenter/providers/*.ts`)
47+
48+
* **`coreStream(messages, modelId, temperature, maxTokens)` 方法:**
49+
* **输入:** 接收当前对话消息(根据 Provider 的需求格式化,可能包含上一轮的工具结果)和生成参数。
50+
* **工具处理:**
51+
* **原生支持:** 如果 Provider/模型支持原生函数调用,则将 MCP 工具转换为 Provider 的格式 (`convertToProviderTools`) 并包含在 API 请求中。
52+
* **无原生支持:** 如果不支持原生 FC,则在进行 API 调用之前使用 Prompt 包装 (`prepareFunctionCallPrompt`) 准备消息。
53+
* **API 调用:** 向 LLM Provider 发出*单次*流式 API 调用。
54+
* **流处理:** 迭代 Provider 的原生流数据块。
55+
* **事件标准化:** 解析特定于 Provider 的数据块,并 `yield` 符合 **标准化流事件接口** 的事件。
56+
* 解析文本、思考(`<think>` 或原生)、工具调用(原生或 `<function_call>`)、使用情况、错误、停止原因和图像数据。
57+
* **输出:** 异步 `yield` `StandardizedStreamEvent` 对象。
58+
* **辅助方法:** 包含特定于 Provider 的辅助函数,如 `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, `prepareFunctionCallPrompt` 等。
59+
60+
### 标准化流事件接口 (`LLMCoreStreamEvent`)
61+
62+
```typescript
63+
// 建议定义在例如 src/main/presenter/llmProviderPresenter/streamEvents.ts
64+
interface LLMCoreStreamEvent {
65+
type: 'text' | 'reasoning' | 'tool_call_start' | 'tool_call_chunk' | 'tool_call_end' | 'error' | 'usage' | 'stop' | 'image_data';
66+
content?: string; // 用于 type 'text'
67+
reasoning_content?: string; // 用于 type 'reasoning'
68+
tool_call_id?: string; // 用于 tool_call_* 类型
69+
tool_call_name?: string; // 用于 tool_call_start
70+
tool_call_arguments_chunk?: string; // 用于 tool_call_chunk (流式参数)
71+
tool_call_arguments_complete?: string; // 用于 tool_call_end (可选,如果一次性可用)
72+
error_message?: string; // 用于 type 'error'
73+
usage?: { // 用于 type 'usage'
74+
prompt_tokens: number;
75+
completion_tokens: number;
76+
total_tokens: number;
77+
};
78+
stop_reason?: 'tool_use' | 'max_tokens' | 'stop_sequence' | 'error' | 'complete'; // 用于 type 'stop'
79+
image_data?: { // 用于 type 'image_data'
80+
data: string; // Base64 编码的图像数据
81+
mimeType: string;
82+
};
83+
}
84+
```
85+
86+
## 优点
87+
88+
* **减少代码重复:** Agent 循环逻辑集中在 `index.ts`。
89+
* **提高可维护性:** Provider 实现更简单,专注于 API 交互和事件标准化。
90+
* **更容易添加新 Provider:** 添加新 Provider 只需根据标准化接口实现 `coreStream` 方法,无需复制复杂的 Agent 循环。
91+
* **行为一致性:** 确保工具处理、思考内容解析和事件发送在所有 Provider 之间保持一致。

.github/workflows/build.yml

+45
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
- all
1313
- windows
1414
- linux
15+
- mac
1516

1617
jobs:
1718
build-windows:
@@ -83,3 +84,47 @@ jobs:
8384
path: |
8485
dist/*
8586
!dist/linux-unpacked
87+
88+
build-mac:
89+
if: github.event.inputs.platform == 'all' || contains(github.event.inputs.platform, 'mac')
90+
runs-on: macos-latest
91+
strategy:
92+
matrix:
93+
arch: [x64, arm64]
94+
include:
95+
- arch: x64
96+
platform: mac-x64
97+
- arch: arm64
98+
platform: mac-arm64
99+
steps:
100+
- uses: actions/checkout@v4
101+
- name: Setup Node.js
102+
uses: actions/setup-node@v4
103+
with:
104+
node-version: '22'
105+
- name: Install dependencies
106+
run: npm install
107+
env:
108+
npm_config_platform: darwin
109+
npm_config_arch: ${{ matrix.arch }}
110+
- name: Install Node Runtime
111+
run: npm run installRuntime:mac:${{ matrix.arch }}
112+
- name: Install Sharp
113+
run: npm i --cpu=${{ matrix.arch }} --os=darwin sharp
114+
- name: Build Mac
115+
run: npm run build:mac:${{ matrix.arch }}
116+
env:
117+
CSC_LINK: ${{ secrets.DEEPCHAT_CSC_LINK }}
118+
CSC_KEY_PASSWORD: ${{ secrets.DEEPCHAT_CSC_KEY_PASS }}
119+
DEEPCHAT_APPLE_NOTARY_USERNAME: ${{ secrets.DEEPCHAT_APPLE_NOTARY_USERNAME }}
120+
DEEPCHAT_APPLE_NOTARY_TEAM_ID: ${{ secrets.DEEPCHAT_APPLE_NOTARY_TEAM_ID }}
121+
DEEPCHAT_APPLE_NOTARY_PASSWORD: ${{ secrets.DEEPCHAT_APPLE_NOTARY_PASSWORD }}
122+
build_for_release: '2'
123+
- name: Upload artifacts
124+
uses: actions/upload-artifact@v4
125+
with:
126+
name: deepchat-${{ matrix.platform }}
127+
path: |
128+
dist/*
129+
!dist/mac/*
130+
!dist/mac-arm64/*

.github/workflows/release.yml

+12
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ jobs:
7575
cp artifacts/deepchat-linux-x64/*.tar.gz release_assets/ 2>/dev/null || true
7676
fi
7777
78+
# Process Mac x64 artifacts
79+
if [ -d "artifacts/deepchat-mac-x64" ]; then
80+
cp artifacts/deepchat-mac-x64/*.dmg release_assets/ 2>/dev/null || true
81+
cp artifacts/deepchat-mac-x64/*.zip release_assets/ 2>/dev/null || true
82+
fi
83+
84+
# Process Mac arm64 artifacts
85+
if [ -d "artifacts/deepchat-mac-arm64" ]; then
86+
cp artifacts/deepchat-mac-arm64/*.dmg release_assets/ 2>/dev/null || true
87+
cp artifacts/deepchat-mac-arm64/*.zip release_assets/ 2>/dev/null || true
88+
fi
89+
7890
ls -la release_assets/
7991
8092
- name: Create New Release

0 commit comments

Comments
 (0)