persona-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db/client.d.ts +55 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +157 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/index.d.ts +7 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +7 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/repositories/executionRepository.d.ts +15 -0
- package/dist/db/repositories/executionRepository.d.ts.map +1 -0
- package/dist/db/repositories/executionRepository.js +41 -0
- package/dist/db/repositories/executionRepository.js.map +1 -0
- package/dist/db/repositories/index.d.ts +10 -0
- package/dist/db/repositories/index.d.ts.map +1 -0
- package/dist/db/repositories/index.js +10 -0
- package/dist/db/repositories/index.js.map +1 -0
- package/dist/db/repositories/nodeRepository.d.ts +15 -0
- package/dist/db/repositories/nodeRepository.d.ts.map +1 -0
- package/dist/db/repositories/nodeRepository.js +61 -0
- package/dist/db/repositories/nodeRepository.js.map +1 -0
- package/dist/db/repositories/personaRepository.d.ts +13 -0
- package/dist/db/repositories/personaRepository.d.ts.map +1 -0
- package/dist/db/repositories/personaRepository.js +42 -0
- package/dist/db/repositories/personaRepository.js.map +1 -0
- package/dist/db/repositories/planResultRepository.d.ts +13 -0
- package/dist/db/repositories/planResultRepository.d.ts.map +1 -0
- package/dist/db/repositories/planResultRepository.js +30 -0
- package/dist/db/repositories/planResultRepository.js.map +1 -0
- package/dist/db/repositories/scheduleRepository.d.ts +27 -0
- package/dist/db/repositories/scheduleRepository.d.ts.map +1 -0
- package/dist/db/repositories/scheduleRepository.js +187 -0
- package/dist/db/repositories/scheduleRepository.js.map +1 -0
- package/dist/db/repositories/types.d.ts +132 -0
- package/dist/db/repositories/types.d.ts.map +1 -0
- package/dist/db/repositories/types.js +5 -0
- package/dist/db/repositories/types.js.map +1 -0
- package/dist/db/schema.d.ts +742 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +85 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/capabilities.d.ts +56 -0
- package/dist/llm/capabilities.d.ts.map +1 -0
- package/dist/llm/capabilities.js +305 -0
- package/dist/llm/capabilities.js.map +1 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +10 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/interfaces.d.ts +249 -0
- package/dist/llm/interfaces.d.ts.map +1 -0
- package/dist/llm/interfaces.js +5 -0
- package/dist/llm/interfaces.js.map +1 -0
- package/dist/llm/providers/anthropic-compatible.d.ts +48 -0
- package/dist/llm/providers/anthropic-compatible.d.ts.map +1 -0
- package/dist/llm/providers/anthropic-compatible.js +163 -0
- package/dist/llm/providers/anthropic-compatible.js.map +1 -0
- package/dist/llm/providers/index.d.ts +14 -0
- package/dist/llm/providers/index.d.ts.map +1 -0
- package/dist/llm/providers/index.js +12 -0
- package/dist/llm/providers/index.js.map +1 -0
- package/dist/llm/providers/openai-compatible.d.ts +59 -0
- package/dist/llm/providers/openai-compatible.d.ts.map +1 -0
- package/dist/llm/providers/openai-compatible.js +207 -0
- package/dist/llm/providers/openai-compatible.js.map +1 -0
- package/dist/services/actionService.d.ts +132 -0
- package/dist/services/actionService.d.ts.map +1 -0
- package/dist/services/actionService.js +971 -0
- package/dist/services/actionService.js.map +1 -0
- package/dist/services/branchService.d.ts +19 -0
- package/dist/services/branchService.d.ts.map +1 -0
- package/dist/services/branchService.js +50 -0
- package/dist/services/branchService.js.map +1 -0
- package/dist/services/expressionEvaluator.d.ts +16 -0
- package/dist/services/expressionEvaluator.d.ts.map +1 -0
- package/dist/services/expressionEvaluator.js +70 -0
- package/dist/services/expressionEvaluator.js.map +1 -0
- package/dist/services/factory.d.ts +43 -0
- package/dist/services/factory.d.ts.map +1 -0
- package/dist/services/factory.js +30 -0
- package/dist/services/factory.js.map +1 -0
- package/dist/services/index.d.ts +15 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +17 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/interfaces.d.ts +117 -0
- package/dist/services/interfaces.d.ts.map +1 -0
- package/dist/services/interfaces.js +5 -0
- package/dist/services/interfaces.js.map +1 -0
- package/dist/services/loaders/fileLoader.d.ts +56 -0
- package/dist/services/loaders/fileLoader.d.ts.map +1 -0
- package/dist/services/loaders/fileLoader.js +161 -0
- package/dist/services/loaders/fileLoader.js.map +1 -0
- package/dist/services/loaders/index.d.ts +6 -0
- package/dist/services/loaders/index.d.ts.map +1 -0
- package/dist/services/loaders/index.js +6 -0
- package/dist/services/loaders/index.js.map +1 -0
- package/dist/services/loaders/transformers.d.ts +32 -0
- package/dist/services/loaders/transformers.d.ts.map +1 -0
- package/dist/services/loaders/transformers.js +78 -0
- package/dist/services/loaders/transformers.js.map +1 -0
- package/dist/services/mockAction.d.ts +65 -0
- package/dist/services/mockAction.d.ts.map +1 -0
- package/dist/services/mockAction.js +153 -0
- package/dist/services/mockAction.js.map +1 -0
- package/dist/services/mockBranch.d.ts +50 -0
- package/dist/services/mockBranch.d.ts.map +1 -0
- package/dist/services/mockBranch.js +75 -0
- package/dist/services/mockBranch.js.map +1 -0
- package/dist/services/mockThinking.d.ts +68 -0
- package/dist/services/mockThinking.d.ts.map +1 -0
- package/dist/services/mockThinking.js +89 -0
- package/dist/services/mockThinking.js.map +1 -0
- package/dist/services/thinkingService.d.ts +15 -0
- package/dist/services/thinkingService.d.ts.map +1 -0
- package/dist/services/thinkingService.js +117 -0
- package/dist/services/thinkingService.js.map +1 -0
- package/dist/temporal/activities/actionActivities.d.ts +15 -0
- package/dist/temporal/activities/actionActivities.d.ts.map +1 -0
- package/dist/temporal/activities/actionActivities.js +140 -0
- package/dist/temporal/activities/actionActivities.js.map +1 -0
- package/dist/temporal/activities/branchActivities.d.ts +13 -0
- package/dist/temporal/activities/branchActivities.d.ts.map +1 -0
- package/dist/temporal/activities/branchActivities.js +26 -0
- package/dist/temporal/activities/branchActivities.js.map +1 -0
- package/dist/temporal/activities/dbActivities.d.ts +14 -0
- package/dist/temporal/activities/dbActivities.d.ts.map +1 -0
- package/dist/temporal/activities/dbActivities.js +84 -0
- package/dist/temporal/activities/dbActivities.js.map +1 -0
- package/dist/temporal/activities/index.d.ts +9 -0
- package/dist/temporal/activities/index.d.ts.map +1 -0
- package/dist/temporal/activities/index.js +9 -0
- package/dist/temporal/activities/index.js.map +1 -0
- package/dist/temporal/activities/thinkingActivities.d.ts +17 -0
- package/dist/temporal/activities/thinkingActivities.d.ts.map +1 -0
- package/dist/temporal/activities/thinkingActivities.js +145 -0
- package/dist/temporal/activities/thinkingActivities.js.map +1 -0
- package/dist/temporal/activities/types.d.ts +100 -0
- package/dist/temporal/activities/types.d.ts.map +1 -0
- package/dist/temporal/activities/types.js +5 -0
- package/dist/temporal/activities/types.js.map +1 -0
- package/dist/temporal/client.d.ts +43 -0
- package/dist/temporal/client.d.ts.map +1 -0
- package/dist/temporal/client.js +75 -0
- package/dist/temporal/client.js.map +1 -0
- package/dist/temporal/index.d.ts +10 -0
- package/dist/temporal/index.d.ts.map +1 -0
- package/dist/temporal/index.js +12 -0
- package/dist/temporal/index.js.map +1 -0
- package/dist/temporal/personaCoreClient.d.ts +199 -0
- package/dist/temporal/personaCoreClient.d.ts.map +1 -0
- package/dist/temporal/personaCoreClient.js +233 -0
- package/dist/temporal/personaCoreClient.js.map +1 -0
- package/dist/temporal/personaWorker.d.ts +141 -0
- package/dist/temporal/personaWorker.d.ts.map +1 -0
- package/dist/temporal/personaWorker.js +93 -0
- package/dist/temporal/personaWorker.js.map +1 -0
- package/dist/temporal/worker.d.ts +66 -0
- package/dist/temporal/worker.d.ts.map +1 -0
- package/dist/temporal/worker.js +109 -0
- package/dist/temporal/worker.js.map +1 -0
- package/dist/temporal/workflows/index.d.ts +5 -0
- package/dist/temporal/workflows/index.d.ts.map +1 -0
- package/dist/temporal/workflows/index.js +5 -0
- package/dist/temporal/workflows/index.js.map +1 -0
- package/dist/temporal/workflows/scheduleWorkflow.d.ts +31 -0
- package/dist/temporal/workflows/scheduleWorkflow.d.ts.map +1 -0
- package/dist/temporal/workflows/scheduleWorkflow.js +256 -0
- package/dist/temporal/workflows/scheduleWorkflow.js.map +1 -0
- package/dist/types/common.d.ts +81 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +5 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/nodes.d.ts +496 -0
- package/dist/types/nodes.d.ts.map +1 -0
- package/dist/types/nodes.js +5 -0
- package/dist/types/nodes.js.map +1 -0
- package/dist/types/persona.d.ts +59 -0
- package/dist/types/persona.d.ts.map +1 -0
- package/dist/types/persona.js +36 -0
- package/dist/types/persona.js.map +1 -0
- package/dist/types/schedule.d.ts +143 -0
- package/dist/types/schedule.d.ts.map +1 -0
- package/dist/types/schedule.js +155 -0
- package/dist/types/schedule.js.map +1 -0
- package/dist/utils/dateUtils.d.ts +31 -0
- package/dist/utils/dateUtils.d.ts.map +1 -0
- package/dist/utils/dateUtils.js +53 -0
- package/dist/utils/dateUtils.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/inputResolver.d.ts +43 -0
- package/dist/utils/inputResolver.d.ts.map +1 -0
- package/dist/utils/inputResolver.js +137 -0
- package/dist/utils/inputResolver.js.map +1 -0
- package/dist/utils/sharedDataUtils.d.ts +36 -0
- package/dist/utils/sharedDataUtils.d.ts.map +1 -0
- package/dist/utils/sharedDataUtils.js +84 -0
- package/dist/utils/sharedDataUtils.js.map +1 -0
- package/dist/utils/typeGuards.d.ts +33 -0
- package/dist/utils/typeGuards.d.ts.map +1 -0
- package/dist/utils/typeGuards.js +50 -0
- package/dist/utils/typeGuards.js.map +1 -0
- package/docs/add-llm-provider.md +353 -0
- package/docs/external/deepseek-v32.md +28 -0
- package/docs/quick-start.md +849 -0
- package/docs/suite-guide.md +148 -0
- package/docs/usage-guide.md +1487 -0
- package/package.json +80 -0
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
# PersonaCore 快速入门指南
|
|
2
|
+
|
|
3
|
+
本文档介绍如何使用 `createPersonaWorker` 和 `PersonaCoreClient` 快速启动和运行 PersonaCore 工作流。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
1. [概述](#概述)
|
|
8
|
+
2. [前置条件](#前置条件)
|
|
9
|
+
3. [核心组件](#核心组件)
|
|
10
|
+
4. [快速开始](#快速开始)
|
|
11
|
+
5. [详细 API 说明](#详细-api-说明)
|
|
12
|
+
6. [LLM Provider 配置](#llm-provider-配置)
|
|
13
|
+
7. [完整示例](#完整示例)
|
|
14
|
+
8. [常见问题](#常见问题)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 概述
|
|
19
|
+
|
|
20
|
+
PersonaCore 提供两个核心简化 API:
|
|
21
|
+
|
|
22
|
+
| 组件 | 职责 | 说明 |
|
|
23
|
+
|-----|------|------|
|
|
24
|
+
| `createPersonaWorker` | **Worker 端** | 创建和运行 Temporal Worker,处理工作流任务 |
|
|
25
|
+
| `PersonaCoreClient` | **Client 端** | 启动工作流、监控状态、控制执行 |
|
|
26
|
+
|
|
27
|
+
典型部署架构:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
┌─────────────────────────┐ ┌─────────────────────────┐
|
|
31
|
+
│ 应用程序 (Client) │ │ Worker 进程 │
|
|
32
|
+
│ │ │ │
|
|
33
|
+
│ PersonaCoreClient │ │ createPersonaWorker │
|
|
34
|
+
│ - startWithThinking │◄────►│ - LLM Provider │
|
|
35
|
+
│ - startWithPersona │ │ - 执行思考/动作/分支 │
|
|
36
|
+
│ - getStatus │ │ │
|
|
37
|
+
└───────────┬─────────────┘ └───────────┬─────────────┘
|
|
38
|
+
│ │
|
|
39
|
+
└────────────┬───────────────────┘
|
|
40
|
+
▼
|
|
41
|
+
┌─────────────────────┐
|
|
42
|
+
│ Temporal Server │
|
|
43
|
+
│ + PostgreSQL/ │
|
|
44
|
+
│ PGlite │
|
|
45
|
+
└─────────────────────┘
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 前置条件
|
|
51
|
+
|
|
52
|
+
### 1. 安装依赖
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install persona-core
|
|
56
|
+
# 或
|
|
57
|
+
pnpm add persona-core
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Temporal Server
|
|
61
|
+
|
|
62
|
+
本地开发可使用 Docker 快速启动:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# 使用 Docker Compose 启动 Temporal
|
|
66
|
+
git clone https://github.com/temporalio/docker-compose.git
|
|
67
|
+
cd docker-compose
|
|
68
|
+
docker-compose up -d
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Temporal Server 默认运行在 `localhost:7233`。
|
|
72
|
+
|
|
73
|
+
### 3. 数据库
|
|
74
|
+
|
|
75
|
+
- **开发/测试**:无需配置,自动使用 PGlite 内存数据库
|
|
76
|
+
- **生产**:建议使用 PostgreSQL
|
|
77
|
+
|
|
78
|
+
### 4. LLM API Key
|
|
79
|
+
|
|
80
|
+
支持多种 LLM 服务,需要对应的 API Key:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# .env 文件
|
|
84
|
+
OPENAI_API_KEY=sk-xxx # OpenAI
|
|
85
|
+
DEEPSEEK_API_KEY=sk-xxx # DeepSeek
|
|
86
|
+
ANTHROPIC_API_KEY=sk-xxx # Claude
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 核心组件
|
|
92
|
+
|
|
93
|
+
### createPersonaWorker
|
|
94
|
+
|
|
95
|
+
简化的 Worker 创建函数,开箱即用:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { createPersonaWorker, OpenAICompatibleProvider } from 'persona-core';
|
|
99
|
+
|
|
100
|
+
const worker = await createPersonaWorker({
|
|
101
|
+
temporalAddress: 'localhost:7233',
|
|
102
|
+
taskQueue: 'my-task-queue',
|
|
103
|
+
llmProvider: new OpenAICompatibleProvider({
|
|
104
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
105
|
+
model: 'gpt-4',
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// 启动 Worker(阻塞)
|
|
110
|
+
await worker.workerHandle.worker.run();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### PersonaCoreClient
|
|
114
|
+
|
|
115
|
+
高级客户端,用于启动和控制工作流:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { PersonaCoreClient } from 'persona-core';
|
|
119
|
+
|
|
120
|
+
const client = await PersonaCoreClient.create({
|
|
121
|
+
temporalAddress: 'localhost:7233',
|
|
122
|
+
taskQueue: 'my-task-queue',
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// 启动工作流
|
|
126
|
+
const handle = await client.startWithThinking({
|
|
127
|
+
persona: myPersona,
|
|
128
|
+
thinkingPrompt: '帮我规划一个任务...',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// 等待完成
|
|
132
|
+
await handle.waitForCompletion();
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 快速开始
|
|
138
|
+
|
|
139
|
+
### 最小可运行示例
|
|
140
|
+
|
|
141
|
+
下面是一个完整的最小示例,展示如何使用 PersonaCore:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import {
|
|
145
|
+
createPersonaWorker,
|
|
146
|
+
PersonaCoreClient,
|
|
147
|
+
OpenAICompatibleProvider,
|
|
148
|
+
Persona,
|
|
149
|
+
ActionNodeType,
|
|
150
|
+
} from 'persona-core';
|
|
151
|
+
|
|
152
|
+
// 1. 定义 Persona
|
|
153
|
+
const myPersona: Persona = {
|
|
154
|
+
id: 'my-assistant',
|
|
155
|
+
name: '智能助手',
|
|
156
|
+
systemPrompt: '你是一个有帮助的助手。请根据用户需求规划任务。',
|
|
157
|
+
actionTypes: [
|
|
158
|
+
{
|
|
159
|
+
kind: 'action',
|
|
160
|
+
id: 'reply',
|
|
161
|
+
name: '回复',
|
|
162
|
+
description: '生成回复内容',
|
|
163
|
+
executionType: 'llm_call',
|
|
164
|
+
inputFields: [
|
|
165
|
+
{ name: 'message', required: true, typeHint: 'string' },
|
|
166
|
+
],
|
|
167
|
+
outputFields: [
|
|
168
|
+
{ name: 'response', required: true, typeHint: 'string' },
|
|
169
|
+
],
|
|
170
|
+
} as ActionNodeType,
|
|
171
|
+
],
|
|
172
|
+
createdAt: new Date(),
|
|
173
|
+
updatedAt: new Date(),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// 2. 创建 LLM Provider
|
|
177
|
+
const llmProvider = new OpenAICompatibleProvider({
|
|
178
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
179
|
+
model: 'gpt-4',
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const TASK_QUEUE = 'demo-queue';
|
|
183
|
+
|
|
184
|
+
// 3. 启动 Worker(在单独的进程中运行)
|
|
185
|
+
async function startWorker() {
|
|
186
|
+
const worker = await createPersonaWorker({
|
|
187
|
+
temporalAddress: 'localhost:7233',
|
|
188
|
+
taskQueue: TASK_QUEUE,
|
|
189
|
+
llmProvider,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
console.log('Worker started, waiting for tasks...');
|
|
193
|
+
await worker.workerHandle.worker.run();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 4. 启动工作流(在应用程序中调用)
|
|
197
|
+
async function startWorkflow() {
|
|
198
|
+
const client = await PersonaCoreClient.create({
|
|
199
|
+
temporalAddress: 'localhost:7233',
|
|
200
|
+
taskQueue: TASK_QUEUE,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const handle = await client.startWithThinking({
|
|
204
|
+
persona: myPersona,
|
|
205
|
+
thinkingPrompt: '用户说:你好,请介绍一下你自己。',
|
|
206
|
+
scheduleName: '自我介绍',
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
console.log(`Workflow started: ${handle.workflowId}`);
|
|
210
|
+
|
|
211
|
+
// 等待完成
|
|
212
|
+
await handle.waitForCompletion();
|
|
213
|
+
|
|
214
|
+
console.log('Workflow completed successfully');
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 详细 API 说明
|
|
221
|
+
|
|
222
|
+
### createPersonaWorker 配置
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
interface PersonaWorkerConfig {
|
|
226
|
+
// Temporal 连接(二选一)
|
|
227
|
+
temporalAddress?: string; // 如 'localhost:7233'
|
|
228
|
+
nativeConnection?: NativeConnection; // 用于测试环境
|
|
229
|
+
|
|
230
|
+
// 任务队列
|
|
231
|
+
taskQueue?: string; // 默认 'persona-core-queue'
|
|
232
|
+
|
|
233
|
+
// LLM 配置(必需)
|
|
234
|
+
llmProvider: LLMProvider; // 主要 LLM Provider
|
|
235
|
+
|
|
236
|
+
// 可选:为不同场景使用不同的 LLM
|
|
237
|
+
providers?: {
|
|
238
|
+
planning?: LLMProvider; // 规划专用(思考节点)
|
|
239
|
+
branch?: LLMProvider; // 分支决策专用
|
|
240
|
+
content?: LLMProvider; // 内容生成专用
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// 数据库配置
|
|
244
|
+
postgresUrl?: string; // PostgreSQL 连接字符串
|
|
245
|
+
databaseHandle?: DatabaseHandle; // 已有的数据库句柄
|
|
246
|
+
|
|
247
|
+
// 文件操作配置
|
|
248
|
+
fileConfig?: {
|
|
249
|
+
baseDir?: string; // 文件操作基础目录
|
|
250
|
+
maxFileSize?: number; // 最大文件大小(字节)
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// 连接超时
|
|
254
|
+
connectTimeout?: number; // 默认 10000ms
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### 返回值 PersonaWorkerHandle
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
interface PersonaWorkerHandle {
|
|
262
|
+
workerHandle: {
|
|
263
|
+
worker: Worker; // Temporal Worker 实例
|
|
264
|
+
shutdown: () => Promise<void>; // 关闭 Worker
|
|
265
|
+
};
|
|
266
|
+
databaseHandle: DatabaseHandle; // 数据库句柄
|
|
267
|
+
shutdown: () => Promise<void>; // 优雅关闭所有资源
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### PersonaCoreClient 配置
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface PersonaCoreClientConfig {
|
|
275
|
+
// Temporal 连接(二选一)
|
|
276
|
+
temporalAddress?: string;
|
|
277
|
+
temporalClient?: Client; // 已有的 Temporal Client
|
|
278
|
+
|
|
279
|
+
// 任务队列(必需)
|
|
280
|
+
taskQueue: string;
|
|
281
|
+
|
|
282
|
+
// 数据库配置
|
|
283
|
+
postgresUrl?: string;
|
|
284
|
+
db?: DatabaseClient; // 已有的数据库客户端
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 启动工作流的三种方式
|
|
289
|
+
|
|
290
|
+
#### 方式一:startWithThinking(推荐)
|
|
291
|
+
|
|
292
|
+
只需提供 Persona 和一个思考提示,系统自动创建 Schedule:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
const handle = await client.startWithThinking({
|
|
296
|
+
persona: myPersona,
|
|
297
|
+
thinkingPrompt: '帮我完成这个任务...',
|
|
298
|
+
scheduleName: '任务名称', // 可选
|
|
299
|
+
initialSharedData: { // 可选:初始共享数据
|
|
300
|
+
userName: '张三',
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### 方式二:startWithPersona
|
|
306
|
+
|
|
307
|
+
提供完整的 Persona 和 Schedule 定义:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
const schedule: Schedule = {
|
|
311
|
+
id: 'my-schedule',
|
|
312
|
+
personaId: 'my-persona',
|
|
313
|
+
name: '自定义任务',
|
|
314
|
+
entryNodeId: 'think-1',
|
|
315
|
+
nodes: {
|
|
316
|
+
'think-1': {
|
|
317
|
+
id: 'think-1',
|
|
318
|
+
kind: 'thinking',
|
|
319
|
+
thinkingPrompt: '规划任务...',
|
|
320
|
+
inputs: {},
|
|
321
|
+
nextNodeId: 'action-1',
|
|
322
|
+
},
|
|
323
|
+
'action-1': {
|
|
324
|
+
id: 'action-1',
|
|
325
|
+
kind: 'action',
|
|
326
|
+
actionTypeId: 'reply',
|
|
327
|
+
inputs: { message: { type: 'fixed', value: 'Hello' } },
|
|
328
|
+
outputMappings: [],
|
|
329
|
+
nextNodeId: null,
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
sharedData: { data: {}, fieldTypes: {} },
|
|
333
|
+
status: 'pending',
|
|
334
|
+
executionHistory: [],
|
|
335
|
+
createdAt: new Date(),
|
|
336
|
+
updatedAt: new Date(),
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const handle = await client.startWithPersona({
|
|
340
|
+
persona: myPersona,
|
|
341
|
+
schedule,
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### 方式三:startSchedule
|
|
346
|
+
|
|
347
|
+
使用已存在于数据库中的 Schedule:
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const handle = await client.startSchedule({
|
|
351
|
+
scheduleId: 'existing-schedule-id',
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### WorkflowHandle 操作
|
|
356
|
+
|
|
357
|
+
启动工作流后返回的句柄支持以下操作:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
interface WorkflowHandle {
|
|
361
|
+
workflowId: string;
|
|
362
|
+
scheduleId: string;
|
|
363
|
+
personaId: string;
|
|
364
|
+
|
|
365
|
+
// 获取执行状态
|
|
366
|
+
getStatus(): Promise<ScheduleExecutionStatus>;
|
|
367
|
+
|
|
368
|
+
// 暂停执行
|
|
369
|
+
pause(): Promise<void>;
|
|
370
|
+
|
|
371
|
+
// 恢复执行
|
|
372
|
+
resume(): Promise<void>;
|
|
373
|
+
|
|
374
|
+
// 取消执行
|
|
375
|
+
cancel(): Promise<void>;
|
|
376
|
+
|
|
377
|
+
// 等待执行完成
|
|
378
|
+
waitForCompletion(): Promise<void>;
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## LLM Provider 配置
|
|
385
|
+
|
|
386
|
+
### OpenAI 兼容格式
|
|
387
|
+
|
|
388
|
+
适用于 OpenAI、DeepSeek、Groq、Together AI、OpenRouter 等:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import { OpenAICompatibleProvider, DeepSeekProvider, OpenAIProvider } from 'persona-core';
|
|
392
|
+
|
|
393
|
+
// 通用 OpenAI 兼容格式
|
|
394
|
+
const provider = new OpenAICompatibleProvider({
|
|
395
|
+
apiKey: 'your-api-key',
|
|
396
|
+
baseUrl: 'https://api.openai.com/v1', // 可选
|
|
397
|
+
model: 'gpt-4', // 可选
|
|
398
|
+
defaultTimeout: 60000, // 可选
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// DeepSeek 快捷方式
|
|
402
|
+
const deepseek = new DeepSeekProvider({
|
|
403
|
+
apiKey: process.env.DEEPSEEK_API_KEY!,
|
|
404
|
+
model: 'deepseek-chat', // 可选,默认 deepseek-chat
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
// OpenAI 快捷方式
|
|
408
|
+
const openai = new OpenAIProvider({
|
|
409
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
410
|
+
model: 'gpt-4-turbo', // 可选,默认 gpt-4
|
|
411
|
+
});
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### Anthropic 兼容格式
|
|
415
|
+
|
|
416
|
+
适用于 Claude 及兼容服务:
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import { AnthropicCompatibleProvider, ClaudeProvider } from 'persona-core';
|
|
420
|
+
|
|
421
|
+
// 通用 Anthropic 兼容格式
|
|
422
|
+
const provider = new AnthropicCompatibleProvider({
|
|
423
|
+
apiKey: 'your-api-key',
|
|
424
|
+
baseUrl: 'https://api.anthropic.com', // 可选
|
|
425
|
+
model: 'claude-sonnet-4-20250514', // 可选
|
|
426
|
+
enableThinking: true, // 可选:启用 Extended Thinking
|
|
427
|
+
thinkingBudgetTokens: 10000, // 可选:思考 Token 预算
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// Claude 快捷方式
|
|
431
|
+
const claude = new ClaudeProvider({
|
|
432
|
+
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
433
|
+
model: 'claude-sonnet-4-20250514',
|
|
434
|
+
});
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 多 Provider 配置
|
|
438
|
+
|
|
439
|
+
为不同场景使用不同的模型以优化成本和效果:
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
const worker = await createPersonaWorker({
|
|
443
|
+
temporalAddress: 'localhost:7233',
|
|
444
|
+
taskQueue: 'my-queue',
|
|
445
|
+
|
|
446
|
+
// 默认 Provider
|
|
447
|
+
llmProvider: new DeepSeekProvider({ apiKey: '...' }),
|
|
448
|
+
|
|
449
|
+
// 场景专用 Provider
|
|
450
|
+
providers: {
|
|
451
|
+
// 规划任务用更强的模型
|
|
452
|
+
planning: new ClaudeProvider({
|
|
453
|
+
apiKey: '...',
|
|
454
|
+
model: 'claude-sonnet-4-20250514',
|
|
455
|
+
}),
|
|
456
|
+
// 分支决策用快速模型
|
|
457
|
+
branch: new DeepSeekProvider({
|
|
458
|
+
apiKey: '...',
|
|
459
|
+
model: 'deepseek-chat',
|
|
460
|
+
}),
|
|
461
|
+
// 内容生成用专门优化的模型
|
|
462
|
+
content: new OpenAIProvider({
|
|
463
|
+
apiKey: '...',
|
|
464
|
+
model: 'gpt-4',
|
|
465
|
+
}),
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## 完整示例
|
|
473
|
+
|
|
474
|
+
### 示例 1:简单问答机器人
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
import {
|
|
478
|
+
createPersonaWorker,
|
|
479
|
+
PersonaCoreClient,
|
|
480
|
+
DeepSeekProvider,
|
|
481
|
+
Persona,
|
|
482
|
+
ActionNodeType,
|
|
483
|
+
} from 'persona-core';
|
|
484
|
+
|
|
485
|
+
// 定义问答 Persona
|
|
486
|
+
const qaPersona: Persona = {
|
|
487
|
+
id: 'qa-bot',
|
|
488
|
+
name: '问答机器人',
|
|
489
|
+
systemPrompt: `你是一个智能问答机器人。
|
|
490
|
+
根据用户的问题,使用 "answer" 动作来生成回答。
|
|
491
|
+
|
|
492
|
+
规划时:
|
|
493
|
+
1. 声明共享数据字段 "answer"(非集合类型)
|
|
494
|
+
2. 创建 "answer" 动作节点,将用户问题作为输入
|
|
495
|
+
3. 将输出映射到 "answer" 共享数据字段`,
|
|
496
|
+
actionTypes: [
|
|
497
|
+
{
|
|
498
|
+
kind: 'action',
|
|
499
|
+
id: 'answer',
|
|
500
|
+
name: '回答问题',
|
|
501
|
+
description: '根据问题生成答案',
|
|
502
|
+
executionType: 'llm_call',
|
|
503
|
+
inputFields: [
|
|
504
|
+
{ name: 'question', required: true, typeHint: 'string', description: '用户问题' },
|
|
505
|
+
],
|
|
506
|
+
outputFields: [
|
|
507
|
+
{ name: 'answer', required: true, typeHint: 'string', description: '回答内容' },
|
|
508
|
+
],
|
|
509
|
+
} as ActionNodeType,
|
|
510
|
+
],
|
|
511
|
+
createdAt: new Date(),
|
|
512
|
+
updatedAt: new Date(),
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
async function main() {
|
|
516
|
+
const TASK_QUEUE = 'qa-queue';
|
|
517
|
+
|
|
518
|
+
// 创建 LLM Provider
|
|
519
|
+
const llmProvider = new DeepSeekProvider({
|
|
520
|
+
apiKey: process.env.DEEPSEEK_API_KEY!,
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
// 启动 Worker
|
|
524
|
+
const worker = await createPersonaWorker({
|
|
525
|
+
temporalAddress: 'localhost:7233',
|
|
526
|
+
taskQueue: TASK_QUEUE,
|
|
527
|
+
llmProvider,
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// 后台运行 Worker
|
|
531
|
+
const workerPromise = worker.workerHandle.worker.run();
|
|
532
|
+
|
|
533
|
+
try {
|
|
534
|
+
// 创建 Client(无需数据库配置,数据由 Worker 管理)
|
|
535
|
+
const client = await PersonaCoreClient.create({
|
|
536
|
+
temporalAddress: 'localhost:7233',
|
|
537
|
+
taskQueue: TASK_QUEUE,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// 启动工作流
|
|
541
|
+
const handle = await client.startWithThinking({
|
|
542
|
+
persona: qaPersona,
|
|
543
|
+
thinkingPrompt: '用户问:什么是 Temporal?',
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
console.log(`工作流已启动: ${handle.workflowId}`);
|
|
547
|
+
|
|
548
|
+
// 等待完成
|
|
549
|
+
await handle.waitForCompletion();
|
|
550
|
+
|
|
551
|
+
console.log('工作流执行完成');
|
|
552
|
+
} finally {
|
|
553
|
+
// 关闭 Worker
|
|
554
|
+
await worker.shutdown();
|
|
555
|
+
await workerPromise;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
main().catch(console.error);
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### 示例 2:内容创作机器人
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
import {
|
|
566
|
+
createPersonaWorker,
|
|
567
|
+
PersonaCoreClient,
|
|
568
|
+
ClaudeProvider,
|
|
569
|
+
Persona,
|
|
570
|
+
ActionNodeType,
|
|
571
|
+
} from 'persona-core';
|
|
572
|
+
|
|
573
|
+
const contentCreator: Persona = {
|
|
574
|
+
id: 'content-creator',
|
|
575
|
+
name: '内容创作者',
|
|
576
|
+
systemPrompt: `你是一个专业的内容创作者。
|
|
577
|
+
根据用户的需求,你可以:
|
|
578
|
+
1. 使用 "generate_outline" 生成文章大纲
|
|
579
|
+
2. 使用 "write_content" 根据大纲编写内容
|
|
580
|
+
3. 使用 "save_file" 将内容保存到文件
|
|
581
|
+
|
|
582
|
+
规划时请合理使用共享数据在节点间传递信息。`,
|
|
583
|
+
actionTypes: [
|
|
584
|
+
{
|
|
585
|
+
kind: 'action',
|
|
586
|
+
id: 'generate_outline',
|
|
587
|
+
name: '生成大纲',
|
|
588
|
+
executionType: 'llm_call',
|
|
589
|
+
inputFields: [
|
|
590
|
+
{ name: 'topic', required: true, typeHint: 'string' },
|
|
591
|
+
],
|
|
592
|
+
outputFields: [
|
|
593
|
+
{ name: 'outline', required: true, typeHint: 'string' },
|
|
594
|
+
],
|
|
595
|
+
} as ActionNodeType,
|
|
596
|
+
{
|
|
597
|
+
kind: 'action',
|
|
598
|
+
id: 'write_content',
|
|
599
|
+
name: '编写内容',
|
|
600
|
+
executionType: 'llm_call',
|
|
601
|
+
inputFields: [
|
|
602
|
+
{ name: 'outline', required: true, typeHint: 'string' },
|
|
603
|
+
{ name: 'style', required: false, typeHint: 'string' },
|
|
604
|
+
],
|
|
605
|
+
outputFields: [
|
|
606
|
+
{ name: 'content', required: true, typeHint: 'string' },
|
|
607
|
+
],
|
|
608
|
+
} as ActionNodeType,
|
|
609
|
+
{
|
|
610
|
+
kind: 'action',
|
|
611
|
+
id: 'save_file',
|
|
612
|
+
name: '保存文件',
|
|
613
|
+
executionType: 'file_write',
|
|
614
|
+
inputFields: [
|
|
615
|
+
{ name: 'filePath', required: true, typeHint: 'string' },
|
|
616
|
+
{ name: 'content', required: true, typeHint: 'string' },
|
|
617
|
+
],
|
|
618
|
+
outputFields: [
|
|
619
|
+
{ name: 'success', required: true, typeHint: 'boolean' },
|
|
620
|
+
{ name: 'filePath', required: true, typeHint: 'string' },
|
|
621
|
+
],
|
|
622
|
+
} as ActionNodeType,
|
|
623
|
+
],
|
|
624
|
+
createdAt: new Date(),
|
|
625
|
+
updatedAt: new Date(),
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
async function createArticle(topic: string) {
|
|
629
|
+
const TASK_QUEUE = 'content-queue';
|
|
630
|
+
|
|
631
|
+
const worker = await createPersonaWorker({
|
|
632
|
+
temporalAddress: 'localhost:7233',
|
|
633
|
+
taskQueue: TASK_QUEUE,
|
|
634
|
+
llmProvider: new ClaudeProvider({
|
|
635
|
+
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
636
|
+
}),
|
|
637
|
+
fileConfig: {
|
|
638
|
+
baseDir: './output',
|
|
639
|
+
},
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
const workerPromise = worker.workerHandle.worker.run();
|
|
643
|
+
|
|
644
|
+
try {
|
|
645
|
+
// 创建 Client(无需数据库配置)
|
|
646
|
+
const client = await PersonaCoreClient.create({
|
|
647
|
+
temporalAddress: 'localhost:7233',
|
|
648
|
+
taskQueue: TASK_QUEUE,
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
const handle = await client.startWithThinking({
|
|
652
|
+
persona: contentCreator,
|
|
653
|
+
thinkingPrompt: `请帮我创作一篇关于"${topic}"的文章,保存到 article.md`,
|
|
654
|
+
scheduleName: `创作:${topic}`,
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// 可以监控进度
|
|
658
|
+
const checkInterval = setInterval(async () => {
|
|
659
|
+
const status = await handle.getStatus();
|
|
660
|
+
console.log(`进度: 节点 ${status.currentNodeId}, 迭代 ${status.totalIterations}`);
|
|
661
|
+
}, 2000);
|
|
662
|
+
|
|
663
|
+
await handle.waitForCompletion();
|
|
664
|
+
clearInterval(checkInterval);
|
|
665
|
+
|
|
666
|
+
console.log('创作完成!');
|
|
667
|
+
} finally {
|
|
668
|
+
await worker.shutdown();
|
|
669
|
+
await workerPromise;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
createArticle('TypeScript 最佳实践').catch(console.error);
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
### 示例 3:使用测试环境
|
|
677
|
+
|
|
678
|
+
在单元测试或本地开发时,可以使用 Temporal 测试环境:
|
|
679
|
+
|
|
680
|
+
```typescript
|
|
681
|
+
import { describe, it, beforeAll, afterAll, expect } from 'vitest';
|
|
682
|
+
import { TestWorkflowEnvironment } from '@temporalio/testing';
|
|
683
|
+
import { createPersonaWorker, PersonaCoreClient, DeepSeekProvider } from 'persona-core';
|
|
684
|
+
|
|
685
|
+
describe('PersonaCore 测试', () => {
|
|
686
|
+
let testEnv: TestWorkflowEnvironment;
|
|
687
|
+
let worker: PersonaWorkerHandle;
|
|
688
|
+
let workerPromise: Promise<void>;
|
|
689
|
+
|
|
690
|
+
const TASK_QUEUE = 'test-queue';
|
|
691
|
+
|
|
692
|
+
beforeAll(async () => {
|
|
693
|
+
// 创建测试环境(无需真实 Temporal Server)
|
|
694
|
+
testEnv = await TestWorkflowEnvironment.createLocal();
|
|
695
|
+
|
|
696
|
+
// 使用 nativeConnection 而非 temporalAddress
|
|
697
|
+
worker = await createPersonaWorker({
|
|
698
|
+
nativeConnection: testEnv.nativeConnection,
|
|
699
|
+
taskQueue: TASK_QUEUE,
|
|
700
|
+
llmProvider: new DeepSeekProvider({
|
|
701
|
+
apiKey: process.env.DEEPSEEK_API_KEY!,
|
|
702
|
+
}),
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
workerPromise = worker.workerHandle.worker.run();
|
|
706
|
+
}, 30000);
|
|
707
|
+
|
|
708
|
+
afterAll(async () => {
|
|
709
|
+
await worker?.shutdown();
|
|
710
|
+
await workerPromise;
|
|
711
|
+
await testEnv?.teardown();
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it('should complete workflow', async () => {
|
|
715
|
+
// 使用 temporalClient 而非 temporalAddress(无需 db 配置)
|
|
716
|
+
const client = await PersonaCoreClient.create({
|
|
717
|
+
temporalClient: testEnv.client,
|
|
718
|
+
taskQueue: TASK_QUEUE,
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
const handle = await client.startWithThinking({
|
|
722
|
+
persona: myPersona,
|
|
723
|
+
thinkingPrompt: '测试提示',
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
await handle.waitForCompletion();
|
|
727
|
+
|
|
728
|
+
// 工作流执行完成
|
|
729
|
+
console.log('Workflow completed:', handle.scheduleId);
|
|
730
|
+
}, 60000);
|
|
731
|
+
});
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## 常见问题
|
|
737
|
+
|
|
738
|
+
### Q: Worker 和 Client 必须在同一个进程吗?
|
|
739
|
+
|
|
740
|
+
**不是**。在生产环境中,通常:
|
|
741
|
+
- Worker 作为独立的后台服务运行
|
|
742
|
+
- Client 集成在业务应用程序中
|
|
743
|
+
|
|
744
|
+
它们通过 Temporal Server 通信,只需要共享相同的 `taskQueue`。
|
|
745
|
+
|
|
746
|
+
### Q: 如何在多个 Worker 之间共享数据库?
|
|
747
|
+
|
|
748
|
+
可以通过 `postgresUrl` 配置使用同一个 PostgreSQL 数据库:
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
const POSTGRES_URL = 'postgres://user:pass@localhost:5432/persona_pilot';
|
|
752
|
+
|
|
753
|
+
// Worker 1
|
|
754
|
+
const worker1 = await createPersonaWorker({
|
|
755
|
+
temporalAddress: '...',
|
|
756
|
+
taskQueue: 'queue-1',
|
|
757
|
+
postgresUrl: POSTGRES_URL,
|
|
758
|
+
llmProvider: ...,
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
// Worker 2
|
|
762
|
+
const worker2 = await createPersonaWorker({
|
|
763
|
+
temporalAddress: '...',
|
|
764
|
+
taskQueue: 'queue-2',
|
|
765
|
+
postgresUrl: POSTGRES_URL,
|
|
766
|
+
llmProvider: ...,
|
|
767
|
+
});
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Q: 如何处理 Worker 优雅关闭?
|
|
771
|
+
|
|
772
|
+
使用 `shutdown()` 方法,它会等待正在执行的任务完成:
|
|
773
|
+
|
|
774
|
+
```typescript
|
|
775
|
+
const worker = await createPersonaWorker({ ... });
|
|
776
|
+
const runPromise = worker.workerHandle.worker.run();
|
|
777
|
+
|
|
778
|
+
// 监听终止信号
|
|
779
|
+
process.on('SIGTERM', async () => {
|
|
780
|
+
console.log('Shutting down...');
|
|
781
|
+
await worker.shutdown();
|
|
782
|
+
await runPromise;
|
|
783
|
+
process.exit(0);
|
|
784
|
+
});
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Q: 如何获取工作流的详细执行历史?
|
|
788
|
+
|
|
789
|
+
执行历史存储在 Worker 端的数据库中。如果需要查询,可以通过以下方式:
|
|
790
|
+
|
|
791
|
+
**方式 1:在 Worker 端查询**
|
|
792
|
+
|
|
793
|
+
```typescript
|
|
794
|
+
// 在 Worker 进程中
|
|
795
|
+
import { ExecutionRepositoryImpl } from 'persona-core';
|
|
796
|
+
|
|
797
|
+
const executionRepo = new ExecutionRepositoryImpl(worker.databaseHandle.db);
|
|
798
|
+
const history = await executionRepo.getExecutionHistory(scheduleId);
|
|
799
|
+
|
|
800
|
+
for (const execution of history) {
|
|
801
|
+
console.log(`节点: ${execution.nodeId}, 状态: ${execution.status}`);
|
|
802
|
+
}
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
**方式 2:通过 Workflow Query 获取状态**
|
|
806
|
+
|
|
807
|
+
```typescript
|
|
808
|
+
// 在 Client 端
|
|
809
|
+
const handle = await client.startWithThinking({ ... });
|
|
810
|
+
const status = await handle.getStatus();
|
|
811
|
+
|
|
812
|
+
console.log(`当前节点: ${status.currentNodeId}`);
|
|
813
|
+
console.log(`迭代次数: ${status.totalIterations}`);
|
|
814
|
+
console.log(`最近结果:`, status.lastNodeResults);
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### Q: startWithThinking 和 startWithPersona 有什么区别?
|
|
818
|
+
|
|
819
|
+
| 方法 | 使用场景 | 自动程度 |
|
|
820
|
+
|-----|---------|---------|
|
|
821
|
+
| `startWithThinking` | 快速启动,只需提供思考提示 | 自动创建 Schedule,只有入口思考节点 |
|
|
822
|
+
| `startWithPersona` | 需要预定义节点结构时 | 需要手动定义完整的 Schedule |
|
|
823
|
+
|
|
824
|
+
> **注意**:`startSchedule` 方法已废弃,推荐使用 `startWithPersona` 或 `startWithThinking`。
|
|
825
|
+
|
|
826
|
+
### Q: 如何暂停和恢复工作流?
|
|
827
|
+
|
|
828
|
+
```typescript
|
|
829
|
+
const handle = await client.startWithThinking({ ... });
|
|
830
|
+
|
|
831
|
+
// 暂停
|
|
832
|
+
await handle.pause();
|
|
833
|
+
|
|
834
|
+
// 检查状态
|
|
835
|
+
const status = await handle.getStatus();
|
|
836
|
+
console.log('已暂停:', status.isPaused);
|
|
837
|
+
|
|
838
|
+
// 恢复
|
|
839
|
+
await handle.resume();
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
## 下一步
|
|
845
|
+
|
|
846
|
+
- 阅读 [使用指南](./usage-guide.md) 了解更多类型定义和高级用法
|
|
847
|
+
- 阅读 [Suite 开发指南](./suite-guide.md) 了解如何创建预配置的 Persona 包
|
|
848
|
+
- 阅读 [添加 LLM Provider](./add-llm-provider.md) 了解如何支持新的 LLM 服务
|
|
849
|
+
|