@limo-labs/deity 0.1.3-alpha.4 → 0.2.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/README.md +557 -409
- package/dist/index.cjs +4521 -3995
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2231 -2815
- package/dist/index.d.ts +2231 -2815
- package/dist/index.js +4464 -3840
- package/dist/index.js.map +1 -1
- package/dist/jsx-dev-runtime-Dg782FK5.d.cts +1816 -0
- package/dist/jsx-dev-runtime-Dg782FK5.d.ts +1816 -0
- package/dist/jsx-dev-runtime.cjs +63 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.cts +2 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.js +58 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.cjs +63 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.d.cts +2 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +58 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/package.json +31 -2
package/README.md
CHANGED
|
@@ -1,533 +1,681 @@
|
|
|
1
|
-
# @limo-labs/deity
|
|
1
|
+
# @limo-labs/deity
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **Declarative AI Agent Framework** — Build type-safe AI agents with JSX/TSX syntax for agents and declarative API for workflows
|
|
4
4
|
|
|
5
|
-
Deity
|
|
5
|
+
Deity is a declarative framework for building AI agents. **Agents** use familiar JSX/TSX syntax like React components. **Workflows** use declarative function composition. Full TypeScript support and zero runtime overhead.
|
|
6
|
+
|
|
7
|
+
**Important Distinction:**
|
|
8
|
+
- **Agent Definition:** Uses true JSX/TSX tags (`<Agent>`, `<Prompt>`) in `.tsx` files
|
|
9
|
+
- **Workflow Definition:** Uses function calls (`Workflow()`, `Sequence()`) in `.ts` files
|
|
6
10
|
|
|
7
11
|
[](https://www.npmjs.com/package/@limo-labs/deity)
|
|
8
|
-
[](https://github.com/
|
|
12
|
+
[](https://github.com/Limo-Labs/Limo-Deity/blob/main/LICENSE)
|
|
9
13
|
[](https://www.typescriptlang.org/)
|
|
10
14
|
|
|
11
|
-
## ✨
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- ✅ **内存管理** - 分层内存(核心/详细)、自动优先级
|
|
26
|
-
- ✅ **会话持久化** - 自动保存/恢复、灾难恢复
|
|
27
|
-
- ✅ **UI 集成** - 实时进度更新、事件驱动
|
|
28
|
-
- ✅ **工具调用** - 自动工具执行循环
|
|
29
|
-
- ✅ **统计跟踪** - 执行时间、token 使用、重试次数
|
|
30
|
-
|
|
31
|
-
### 🔧 开发体验
|
|
32
|
-
- 🎨 **直观的 API** - 简洁的函数式接口
|
|
33
|
-
- 📝 **完整的文档** - API 文档 + 使用示例
|
|
34
|
-
- 🧪 **305 个测试** - 100% 通过率
|
|
35
|
-
- 📊 **性能基准** - 27 个基准测试验证
|
|
36
|
-
- 🔍 **详细的跟踪** - 完整的执行日志
|
|
37
|
-
|
|
38
|
-
## 📦 安装
|
|
15
|
+
## ✨ Features
|
|
16
|
+
|
|
17
|
+
- 🎨 **JSX/TSX Syntax for Agents** - Write agents with familiar React-like JSX tags (`.tsx` files)
|
|
18
|
+
- 📦 **Declarative Workflow API** - Compose workflows with function calls (`.ts` files)
|
|
19
|
+
- 🔒 **Type Safe** - Full TypeScript support with Zod schema validation
|
|
20
|
+
- 🔧 **Declarative** - Compose agents and workflows from reusable components
|
|
21
|
+
- 🚀 **Zero Runtime Overhead** - Compiles to lightweight AST nodes
|
|
22
|
+
- 🎯 **LLM Agnostic** - Works with any LLM adapter
|
|
23
|
+
- 🔁 **Auto Retry** - Built-in retry logic with LLM feedback
|
|
24
|
+
- ✅ **Output Validation** - Declarative validation rules
|
|
25
|
+
- 🛠️ **Tool Support** - Native tool calling integration
|
|
26
|
+
- 📊 **Observability** - Built-in execution tracing
|
|
27
|
+
|
|
28
|
+
## 📦 Installation
|
|
39
29
|
|
|
40
30
|
```bash
|
|
41
|
-
npm install @limo-labs/deity
|
|
31
|
+
npm install @limo-labs/deity zod
|
|
42
32
|
```
|
|
43
33
|
|
|
44
34
|
```bash
|
|
45
|
-
yarn add @limo-labs/deity
|
|
35
|
+
yarn add @limo-labs/deity zod
|
|
46
36
|
```
|
|
47
37
|
|
|
48
38
|
```bash
|
|
49
|
-
pnpm add @limo-labs/deity
|
|
39
|
+
pnpm add @limo-labs/deity zod
|
|
50
40
|
```
|
|
51
41
|
|
|
52
|
-
## 🚀
|
|
42
|
+
## 🚀 Quick Start
|
|
53
43
|
|
|
54
|
-
###
|
|
44
|
+
### 1. Configure TypeScript (Optional - For JSX/TSX Agent Syntax)
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
import { z } from 'zod';
|
|
58
|
-
import { executeComponent, createEnhancedContext, InMemoryStore, InMemoryTrace } from '@limo-labs/deity';
|
|
59
|
-
import type { AgentComponent, LLMAdapter } from '@limo-labs/deity';
|
|
60
|
-
|
|
61
|
-
// 定义组件
|
|
62
|
-
const summarizer: AgentComponent<{ text: string }, { summary: string }> = {
|
|
63
|
-
id: 'summarizer',
|
|
64
|
-
inputSchema: z.object({ text: z.string() }),
|
|
65
|
-
outputSchema: z.object({ summary: z.string() }),
|
|
66
|
-
|
|
67
|
-
buildPrompt(ctx) {
|
|
68
|
-
return [
|
|
69
|
-
{ role: 'system', content: 'You are a summarization expert.' },
|
|
70
|
-
{ role: 'user', content: `Summarize: ${ctx.inputs.text}` }
|
|
71
|
-
];
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
validate(output) {
|
|
75
|
-
if (output.summary.length < 10) {
|
|
76
|
-
return { valid: false, errors: ['Summary too short'] };
|
|
77
|
-
}
|
|
78
|
-
return { valid: true };
|
|
79
|
-
},
|
|
46
|
+
If you want to use **JSX/TSX tags** for Agent definitions (`.tsx` files), add JSX support to your `tsconfig.json`:
|
|
80
47
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"compilerOptions": {
|
|
51
|
+
"jsx": "react-jsx",
|
|
52
|
+
"jsxImportSource": "@limo-labs/deity"
|
|
84
53
|
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// 创建上下文
|
|
88
|
-
const ctx = await createEnhancedContext({
|
|
89
|
-
inputs: { text: 'Long article text...' },
|
|
90
|
-
store: new InMemoryStore(),
|
|
91
|
-
trace: new InMemoryTrace()
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// 执行组件
|
|
95
|
-
const result = await executeComponent(summarizer, ctx, llmAdapter);
|
|
96
|
-
console.log(result.output.summary);
|
|
54
|
+
}
|
|
97
55
|
```
|
|
98
56
|
|
|
99
|
-
|
|
57
|
+
**Note:** Workflow definitions use function calls and work in regular `.ts` files without JSX configuration.
|
|
100
58
|
|
|
101
|
-
|
|
102
|
-
import { runWorkflow, createStepNode, createSequenceNode } from '@limo-labs/deity';
|
|
103
|
-
import type { WorkflowConfig } from '@limo-labs/deity';
|
|
104
|
-
|
|
105
|
-
// 定义步骤
|
|
106
|
-
const step1: AgentComponent = {
|
|
107
|
-
id: 'analyze',
|
|
108
|
-
inputSchema: z.object({ code: z.string() }),
|
|
109
|
-
outputSchema: z.object({ issues: z.array(z.string()) }),
|
|
110
|
-
buildPrompt: (ctx) => [
|
|
111
|
-
{ role: 'user', content: `Analyze this code: ${ctx.inputs.code}` }
|
|
112
|
-
],
|
|
113
|
-
validate: () => ({ valid: true })
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const step2: AgentComponent = {
|
|
117
|
-
id: 'fix',
|
|
118
|
-
inputSchema: z.object({}),
|
|
119
|
-
outputSchema: z.object({ fixes: z.array(z.string()) }),
|
|
120
|
-
buildPrompt: (ctx) => {
|
|
121
|
-
const analysis = ctx.getOutput<{ issues: string[] }>('analyze');
|
|
122
|
-
return [
|
|
123
|
-
{ role: 'user', content: `Fix these issues: ${analysis.issues.join(', ')}` }
|
|
124
|
-
];
|
|
125
|
-
},
|
|
126
|
-
validate: () => ({ valid: true })
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
// 配置工作流
|
|
130
|
-
const config: WorkflowConfig = {
|
|
131
|
-
name: 'code-fix-workflow',
|
|
132
|
-
graph: createSequenceNode([
|
|
133
|
-
createStepNode(step1),
|
|
134
|
-
createStepNode(step2)
|
|
135
|
-
]),
|
|
136
|
-
defaultModel: { adapter: llmAdapter }
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
// 运行工作流
|
|
140
|
-
const result = await runWorkflow(config, { code: 'function test() { ... }' });
|
|
141
|
-
console.log(result.fixes);
|
|
142
|
-
```
|
|
59
|
+
### 2. Create Your First Agent (Using JSX/TSX Tags)
|
|
143
60
|
|
|
144
|
-
|
|
61
|
+
**File:** `agent.tsx` (note the `.tsx` extension for JSX support)
|
|
145
62
|
|
|
146
|
-
```
|
|
147
|
-
import {
|
|
63
|
+
```tsx
|
|
64
|
+
import { Agent, Prompt, System, User, Result } from '@limo-labs/deity';
|
|
65
|
+
import { z } from 'zod';
|
|
148
66
|
|
|
149
|
-
//
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
store: new InMemoryStore(),
|
|
153
|
-
trace: new InMemoryTrace(),
|
|
154
|
-
enableConversation: {
|
|
155
|
-
maxTokens: 4000,
|
|
156
|
-
pruneWhenFull: true
|
|
157
|
-
}
|
|
67
|
+
// Define schemas
|
|
68
|
+
const InputSchema = z.object({
|
|
69
|
+
topic: z.string()
|
|
158
70
|
});
|
|
159
71
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
conv.addMessage({ role: 'assistant', content: 'Hi there!' });
|
|
165
|
-
|
|
166
|
-
// 获取历史
|
|
167
|
-
const history = conv.getHistory();
|
|
168
|
-
|
|
169
|
-
// 按角色过滤
|
|
170
|
-
const userMessages = conv.getMessages('user');
|
|
72
|
+
const OutputSchema = z.object({
|
|
73
|
+
summary: z.string(),
|
|
74
|
+
keyPoints: z.array(z.string())
|
|
75
|
+
});
|
|
171
76
|
|
|
172
|
-
//
|
|
173
|
-
|
|
77
|
+
// Create agent using JSX tags (requires .tsx file)
|
|
78
|
+
const SummarizerAgent = (
|
|
79
|
+
<Agent id="summarizer" input={InputSchema} output={OutputSchema}>
|
|
80
|
+
<Prompt>
|
|
81
|
+
<System>You are a summarization expert.</System>
|
|
82
|
+
<User>{(ctx: any): string => `Summarize this topic: ${ctx.inputs.topic}`}</User>
|
|
83
|
+
</Prompt>
|
|
84
|
+
<Result>
|
|
85
|
+
{(ctx: any, llmResult: any) => {
|
|
86
|
+
// Extract output from LLM response
|
|
87
|
+
const content = llmResult.response.content;
|
|
88
|
+
return JSON.parse(content);
|
|
89
|
+
}}
|
|
90
|
+
</Result>
|
|
91
|
+
</Agent>
|
|
92
|
+
);
|
|
174
93
|
```
|
|
175
94
|
|
|
176
|
-
###
|
|
95
|
+
### 3. Execute the Agent
|
|
177
96
|
|
|
178
97
|
```typescript
|
|
179
|
-
import { createEnhancedContext } from '@limo-labs/deity';
|
|
98
|
+
import { compileAgent, executeComponent, createEnhancedContext } from '@limo-labs/deity';
|
|
180
99
|
|
|
181
|
-
//
|
|
100
|
+
// Compile JSX to executable component
|
|
101
|
+
const component = compileAgent(SummarizerAgent);
|
|
102
|
+
|
|
103
|
+
// Create execution context
|
|
182
104
|
const ctx = await createEnhancedContext({
|
|
183
|
-
inputs: {}
|
|
184
|
-
store: new InMemoryStore(),
|
|
185
|
-
trace: new InMemoryTrace(),
|
|
186
|
-
enableMemory: {
|
|
187
|
-
coreBudget: {
|
|
188
|
-
maxItems: 10,
|
|
189
|
-
maxTotalSize: 8192
|
|
190
|
-
}
|
|
191
|
-
}
|
|
105
|
+
inputs: { topic: 'Climate change' }
|
|
192
106
|
});
|
|
193
107
|
|
|
194
|
-
//
|
|
195
|
-
const
|
|
108
|
+
// Execute
|
|
109
|
+
const result = await executeComponent(component, ctx, llmAdapter);
|
|
110
|
+
console.log(result.output.summary);
|
|
111
|
+
```
|
|
196
112
|
|
|
197
|
-
|
|
198
|
-
await memory.set('user_name', 'Alice');
|
|
199
|
-
const name = await memory.get('user_name');
|
|
113
|
+
## 📖 Core Concepts
|
|
200
114
|
|
|
201
|
-
|
|
202
|
-
await memory.addCoreMemory({
|
|
203
|
-
id: 'core1',
|
|
204
|
-
content: 'User prefers concise responses',
|
|
205
|
-
importance: 9,
|
|
206
|
-
tags: ['preference']
|
|
207
|
-
});
|
|
115
|
+
### Components
|
|
208
116
|
|
|
209
|
-
|
|
210
|
-
const relevant = memory.loadWorkingMemory({
|
|
211
|
-
currentTask: 'response-generation',
|
|
212
|
-
keywords: ['preference'],
|
|
213
|
-
maxItems: 5
|
|
214
|
-
});
|
|
215
|
-
```
|
|
117
|
+
Deity provides declarative components for building agents:
|
|
216
118
|
|
|
217
|
-
|
|
119
|
+
- **`<Agent>`** - Root component defining the agent
|
|
120
|
+
- **`<Prompt>`** - Prompt construction
|
|
121
|
+
- **`<System>`** - System message
|
|
122
|
+
- **`<User>`** - User message
|
|
123
|
+
- **`<Result>`** - Output extraction
|
|
124
|
+
- **`<Validate>`** - Output validation
|
|
125
|
+
- **`<Retry>`** - Retry configuration
|
|
126
|
+
- **`<Observe>`** - LLM loop observation
|
|
218
127
|
|
|
219
|
-
|
|
220
|
-
import { createUIBridge, runWorkflow } from '@limo-labs/deity';
|
|
128
|
+
### Agent Component
|
|
221
129
|
|
|
222
|
-
|
|
223
|
-
const ui = createUIBridge();
|
|
130
|
+
The `<Agent>` component is the root of every agent:
|
|
224
131
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
132
|
+
```tsx
|
|
133
|
+
<Agent
|
|
134
|
+
id="unique-id"
|
|
135
|
+
input={InputSchema}
|
|
136
|
+
output={OutputSchema}
|
|
137
|
+
loopConfig={{ maxToolRounds: 10, timeout: 30000 }}
|
|
138
|
+
tools={[...]}
|
|
139
|
+
>
|
|
140
|
+
{/* Children components */}
|
|
141
|
+
</Agent>
|
|
142
|
+
```
|
|
229
143
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
144
|
+
**Props:**
|
|
145
|
+
- `id` (required) - Unique agent identifier
|
|
146
|
+
- `input` (required) - Zod schema for input validation
|
|
147
|
+
- `output` (required) - Zod schema for output validation
|
|
148
|
+
- `loopConfig` (optional) - LLM loop configuration
|
|
149
|
+
- `loopValidator` (optional) - Custom loop validator
|
|
150
|
+
- `tools` (optional) - Tool definitions
|
|
151
|
+
|
|
152
|
+
### Prompt Component
|
|
153
|
+
|
|
154
|
+
The `<Prompt>` component defines how to build the LLM prompt:
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<Prompt>
|
|
158
|
+
<System>
|
|
159
|
+
{async (): Promise<string> => {
|
|
160
|
+
// Load prompt from file or construct dynamically
|
|
161
|
+
return await loadPromptTemplate();
|
|
162
|
+
}}
|
|
163
|
+
</System>
|
|
164
|
+
<User>
|
|
165
|
+
{(ctx: any): string => `Process: ${ctx.inputs.task}`}
|
|
166
|
+
</User>
|
|
167
|
+
</Prompt>
|
|
168
|
+
```
|
|
233
169
|
|
|
234
|
-
|
|
235
|
-
console.log(`✅ ${update.name} completed`);
|
|
236
|
-
});
|
|
170
|
+
### Result Component
|
|
237
171
|
|
|
238
|
-
|
|
239
|
-
const config: WorkflowConfig = {
|
|
240
|
-
name: 'my-workflow',
|
|
241
|
-
graph: createSequenceNode([...]),
|
|
242
|
-
defaultModel: { adapter: llmAdapter },
|
|
243
|
-
enhancements: { ui }
|
|
244
|
-
};
|
|
172
|
+
The `<Result>` component extracts structured output:
|
|
245
173
|
|
|
246
|
-
|
|
174
|
+
```tsx
|
|
175
|
+
<Result>
|
|
176
|
+
{(ctx: any, llmResult: any): OutputType => {
|
|
177
|
+
// Extract from tool calls
|
|
178
|
+
const toolCall = llmResult.response.toolCalls?.find(
|
|
179
|
+
tc => tc.name === 'submit_result'
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
if (toolCall) {
|
|
183
|
+
return JSON.parse(toolCall.arguments);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Or extract from text content
|
|
187
|
+
const match = llmResult.response.content.match(/```json\n(.*?)\n```/s);
|
|
188
|
+
return JSON.parse(match[1]);
|
|
189
|
+
}}
|
|
190
|
+
</Result>
|
|
247
191
|
```
|
|
248
192
|
|
|
249
|
-
|
|
193
|
+
### Validate Component
|
|
194
|
+
|
|
195
|
+
The `<Validate>` component defines validation rules:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
<Validate>
|
|
199
|
+
{(output: any, ctx: any) => ({
|
|
200
|
+
rules: [
|
|
201
|
+
{
|
|
202
|
+
check: output.summary.length >= 100,
|
|
203
|
+
error: 'Summary must be at least 100 characters'
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
check: output.keyPoints.length >= 3,
|
|
207
|
+
error: 'Must have at least 3 key points'
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
})}
|
|
211
|
+
</Validate>
|
|
212
|
+
```
|
|
250
213
|
|
|
251
|
-
###
|
|
214
|
+
### Retry Component
|
|
252
215
|
|
|
253
|
-
|
|
216
|
+
The `<Retry>` component configures retry behavior:
|
|
254
217
|
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
validate(output: O, ctx: ExecutionContext<I>): ValidationResult; // 语义验证
|
|
262
|
-
tools?: Tool[]; // 可选工具
|
|
263
|
-
retry?: RetryConfig; // 重试配置
|
|
264
|
-
model?: ModelConfig; // 模型覆盖
|
|
265
|
-
}
|
|
218
|
+
```tsx
|
|
219
|
+
<Retry
|
|
220
|
+
maxAttempts={3}
|
|
221
|
+
feedbackOnError={true}
|
|
222
|
+
retryOnToolError={true}
|
|
223
|
+
/>
|
|
266
224
|
```
|
|
267
225
|
|
|
268
|
-
|
|
226
|
+
## 🎯 Examples
|
|
227
|
+
|
|
228
|
+
### Simple Summarizer
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
const Summarizer = (
|
|
232
|
+
<Agent id="summarizer" input={InputSchema} output={OutputSchema}>
|
|
233
|
+
<Prompt>
|
|
234
|
+
<System>You are a summarization expert.</System>
|
|
235
|
+
<User>{(ctx: any): string => `Summarize: ${ctx.inputs.text}`}</User>
|
|
236
|
+
</Prompt>
|
|
237
|
+
<Result>
|
|
238
|
+
{(ctx: any, llmResult: any) => ({
|
|
239
|
+
summary: llmResult.response.content
|
|
240
|
+
})}
|
|
241
|
+
</Result>
|
|
242
|
+
<Validate>
|
|
243
|
+
{(output: any) => ({
|
|
244
|
+
rules: [
|
|
245
|
+
{
|
|
246
|
+
check: output.summary.length >= 50,
|
|
247
|
+
error: 'Summary too short'
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
})}
|
|
251
|
+
</Validate>
|
|
252
|
+
<Retry maxAttempts={2} feedbackOnError={true} />
|
|
253
|
+
</Agent>
|
|
254
|
+
);
|
|
255
|
+
```
|
|
269
256
|
|
|
270
|
-
|
|
257
|
+
### Code Analyzer with Tools
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
import { createMemoryTools } from '@limo-labs/deity';
|
|
261
|
+
|
|
262
|
+
const CodeAnalyzer = (
|
|
263
|
+
<Agent
|
|
264
|
+
id="analyzer"
|
|
265
|
+
input={z.object({ repoPath: z.string() })}
|
|
266
|
+
output={z.object({ findings: z.array(z.any()) })}
|
|
267
|
+
tools={[
|
|
268
|
+
...createMemoryTools(),
|
|
269
|
+
{
|
|
270
|
+
name: 'read_file',
|
|
271
|
+
description: 'Read file contents',
|
|
272
|
+
inputSchema: z.object({ path: z.string() }),
|
|
273
|
+
async execute(input) {
|
|
274
|
+
return { content: await fs.readFile(input.path, 'utf-8') };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
]}
|
|
278
|
+
>
|
|
279
|
+
<Prompt>
|
|
280
|
+
<System>
|
|
281
|
+
{async (): Promise<string> => {
|
|
282
|
+
return await fs.readFile('./prompts/analyzer.md', 'utf-8');
|
|
283
|
+
}}
|
|
284
|
+
</System>
|
|
285
|
+
<User>
|
|
286
|
+
{(ctx: any): string => `Analyze repository at: ${ctx.inputs.repoPath}`}
|
|
287
|
+
</User>
|
|
288
|
+
</Prompt>
|
|
289
|
+
<Result>
|
|
290
|
+
{(ctx: any, llmResult: any) => {
|
|
291
|
+
// Count memory_store tool calls to verify analysis
|
|
292
|
+
const findings = llmResult.response.toolCalls
|
|
293
|
+
?.filter((tc: any) => tc.name === 'memory_store')
|
|
294
|
+
.map((tc: any) => JSON.parse(tc.arguments));
|
|
295
|
+
|
|
296
|
+
return { findings };
|
|
297
|
+
}}
|
|
298
|
+
</Result>
|
|
299
|
+
</Agent>
|
|
300
|
+
);
|
|
301
|
+
```
|
|
271
302
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
303
|
+
### Dynamic Tool Factory (NEW in 4.0)
|
|
304
|
+
|
|
305
|
+
**Tool Factory Pattern** - Create tools dynamically based on execution context:
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
import { createMemoryTools } from '@limo-labs/deity';
|
|
309
|
+
|
|
310
|
+
const DynamicAgent = (
|
|
311
|
+
<Agent
|
|
312
|
+
id="dynamic"
|
|
313
|
+
input={z.object({ enableMemory: z.boolean() })}
|
|
314
|
+
output={z.object({ result: z.string() })}
|
|
315
|
+
tools={(ctx) => {
|
|
316
|
+
// Static tools always available
|
|
317
|
+
const staticTools = [
|
|
318
|
+
{
|
|
319
|
+
name: 'read_file',
|
|
320
|
+
description: 'Read file',
|
|
321
|
+
inputSchema: z.object({ path: z.string() }),
|
|
322
|
+
async execute(input) {
|
|
323
|
+
return await fs.readFile(input.path, 'utf-8');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
];
|
|
327
|
+
|
|
328
|
+
// Add memory tools conditionally
|
|
329
|
+
const memoryTools = ctx.memory ? createMemoryTools(ctx) : [];
|
|
330
|
+
|
|
331
|
+
return [...staticTools, ...memoryTools];
|
|
332
|
+
}}
|
|
333
|
+
>
|
|
334
|
+
{/* ... */}
|
|
335
|
+
</Agent>
|
|
336
|
+
);
|
|
289
337
|
```
|
|
290
338
|
|
|
291
|
-
|
|
339
|
+
**Key Benefits:**
|
|
340
|
+
- ✅ Tools can access ExecutionContext at creation time
|
|
341
|
+
- ✅ Conditional tool inclusion based on context state
|
|
342
|
+
- ✅ Enables Deity's memory tools in TSX workflows
|
|
343
|
+
- ✅ Backward compatible with static tool arrays
|
|
344
|
+
|
|
345
|
+
### Multi-Step Workflow
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
const MultiStepAgent = (
|
|
349
|
+
<Agent id="multi-step" input={InputSchema} output={OutputSchema}>
|
|
350
|
+
<Prompt>
|
|
351
|
+
<System>
|
|
352
|
+
{async (): Promise<string> => {
|
|
353
|
+
const step = ctx.inputs.currentStep;
|
|
354
|
+
return await loadStepPrompt(step);
|
|
355
|
+
}}
|
|
356
|
+
</System>
|
|
357
|
+
<User>{(ctx: any): string => buildStepMessage(ctx)}</User>
|
|
358
|
+
</Prompt>
|
|
359
|
+
<Observe>
|
|
360
|
+
{(llmResult: any) => ({
|
|
361
|
+
toolCallCount: llmResult.response.toolCalls?.length || 0,
|
|
362
|
+
roundsExecuted: llmResult.rounds
|
|
363
|
+
})}
|
|
364
|
+
</Observe>
|
|
365
|
+
<Result>
|
|
366
|
+
{(ctx: any, llmResult: any, observed: any) => {
|
|
367
|
+
console.log(`Executed ${observed.roundsExecuted} rounds`);
|
|
368
|
+
return extractStepOutput(llmResult);
|
|
369
|
+
}}
|
|
370
|
+
</Result>
|
|
371
|
+
</Agent>
|
|
372
|
+
);
|
|
373
|
+
```
|
|
292
374
|
|
|
293
|
-
|
|
375
|
+
## 🔧 Advanced Features
|
|
294
376
|
|
|
295
|
-
|
|
296
|
-
// 顺序执行
|
|
297
|
-
createSequenceNode([step1, step2, step3])
|
|
377
|
+
### Loop Validation
|
|
298
378
|
|
|
299
|
-
|
|
300
|
-
createConditionalNode(
|
|
301
|
-
(ctx) => ctx.getOutput('check').needsMore,
|
|
302
|
-
trueBranch,
|
|
303
|
-
falseBranch
|
|
304
|
-
)
|
|
379
|
+
Use `loopValidator` to validate during LLM execution loops:
|
|
305
380
|
|
|
306
|
-
|
|
307
|
-
|
|
381
|
+
```typescript
|
|
382
|
+
import type { Validator, LLMLoopState, ExecutionContext } from '@limo-labs/deity';
|
|
383
|
+
|
|
384
|
+
class CustomValidator implements Validator {
|
|
385
|
+
async validate(
|
|
386
|
+
ctx: ExecutionContext,
|
|
387
|
+
loopState: LLMLoopState
|
|
388
|
+
): Promise<ValidationResult> {
|
|
389
|
+
// Check if required tool was called
|
|
390
|
+
const requiredTool = loopState.toolCallsThisRound.find(
|
|
391
|
+
tc => tc.name === 'submit_plan'
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
if (!requiredTool) {
|
|
395
|
+
return {
|
|
396
|
+
valid: false,
|
|
397
|
+
feedback: 'You must call submit_plan tool to complete this task'
|
|
398
|
+
};
|
|
399
|
+
}
|
|
308
400
|
|
|
309
|
-
|
|
310
|
-
|
|
401
|
+
return { valid: true };
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const agent = (
|
|
406
|
+
<Agent
|
|
407
|
+
id="planner"
|
|
408
|
+
input={InputSchema}
|
|
409
|
+
output={OutputSchema}
|
|
410
|
+
loopValidator={new CustomValidator()}
|
|
411
|
+
>
|
|
412
|
+
{/* ... */}
|
|
413
|
+
</Agent>
|
|
414
|
+
);
|
|
311
415
|
```
|
|
312
416
|
|
|
313
|
-
|
|
417
|
+
### Loop Configuration
|
|
418
|
+
|
|
419
|
+
Configure LLM execution loop behavior:
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
<Agent
|
|
423
|
+
id="agent"
|
|
424
|
+
input={InputSchema}
|
|
425
|
+
output={OutputSchema}
|
|
426
|
+
loopConfig={{
|
|
427
|
+
maxToolRounds: 15, // Max tool execution rounds
|
|
428
|
+
timeout: 180000 // 3 minute timeout
|
|
429
|
+
}}
|
|
430
|
+
>
|
|
431
|
+
{/* ... */}
|
|
432
|
+
</Agent>
|
|
433
|
+
```
|
|
314
434
|
|
|
315
|
-
|
|
316
|
-
- [使用示例](./docs/EXAMPLES.md) - 实际使用案例
|
|
317
|
-
- [迁移指南](./docs/MIGRATION.md) - 从 3.x 迁移
|
|
318
|
-
- [最佳实践](./docs/BEST_PRACTICES.md) - 设计模式和建议
|
|
319
|
-
- [性能报告](./PHASE_9_PERFORMANCE_REPORT.md) - 基准测试结果
|
|
435
|
+
### Dynamic Prompts
|
|
320
436
|
|
|
321
|
-
|
|
437
|
+
Load prompts from files or construct dynamically:
|
|
322
438
|
|
|
323
|
-
|
|
439
|
+
```tsx
|
|
440
|
+
<System>
|
|
441
|
+
{async (ctx: any): Promise<string> => {
|
|
442
|
+
// Load from file
|
|
443
|
+
const template = await fs.readFile('./prompts/system.md', 'utf-8');
|
|
324
444
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
└─────────────────────────────────────────┘
|
|
330
|
-
↓
|
|
331
|
-
┌─────────────────────────────────────────┐
|
|
332
|
-
│ Execution Context │
|
|
333
|
-
│ ┌──────────┬──────────┬──────────┐ │
|
|
334
|
-
│ │Conversation│Memory │ Session │ │
|
|
335
|
-
│ │ Manager │Manager │ Store │ │
|
|
336
|
-
│ └──────────┴──────────┴──────────┘ │
|
|
337
|
-
│ ┌──────────┬──────────┬──────────┐ │
|
|
338
|
-
│ │ UI │ Stats │ Trace │ │
|
|
339
|
-
│ │ Bridge │ Tracker │ Logger │ │
|
|
340
|
-
│ └──────────┴──────────┴──────────┘ │
|
|
341
|
-
└─────────────────────────────────────────┘
|
|
342
|
-
↓
|
|
343
|
-
┌─────────────────────────────────────────┐
|
|
344
|
-
│ LLM Adapter │
|
|
345
|
-
│ (OpenAI, Anthropic, etc.) │
|
|
346
|
-
└─────────────────────────────────────────┘
|
|
445
|
+
// Inject dynamic content
|
|
446
|
+
return template.replace('{{language}}', ctx.inputs.language);
|
|
447
|
+
}}
|
|
448
|
+
</System>
|
|
347
449
|
```
|
|
348
450
|
|
|
349
|
-
|
|
451
|
+
## 🎨 Component Composition
|
|
350
452
|
|
|
351
|
-
|
|
352
|
-
- **Context** - 执行上下文和状态管理
|
|
353
|
-
- **Conversation** - 对话历史管理
|
|
354
|
-
- **Memory** - 分层内存系统
|
|
355
|
-
- **Session** - 持久化和恢复
|
|
356
|
-
- **UI** - 实时进度更新
|
|
357
|
-
- **Core** - 核心类型和工具
|
|
453
|
+
Agents can be composed from reusable functions:
|
|
358
454
|
|
|
359
|
-
|
|
455
|
+
```typescript
|
|
456
|
+
// Reusable prompt builders
|
|
457
|
+
function buildSystemPrompt(role: string) {
|
|
458
|
+
return async (): Promise<string> => {
|
|
459
|
+
return `You are a ${role}.`;
|
|
460
|
+
};
|
|
461
|
+
}
|
|
360
462
|
|
|
361
|
-
|
|
463
|
+
function buildUserPrompt(template: string) {
|
|
464
|
+
return (ctx: any): string => {
|
|
465
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => ctx.inputs[key]);
|
|
466
|
+
};
|
|
467
|
+
}
|
|
362
468
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
469
|
+
// Reusable result extractors
|
|
470
|
+
function extractJSONFromToolCall(toolName: string) {
|
|
471
|
+
return (ctx: any, llmResult: any) => {
|
|
472
|
+
const toolCall = llmResult.response.toolCalls?.find(
|
|
473
|
+
(tc: any) => tc.name === toolName
|
|
474
|
+
);
|
|
475
|
+
return JSON.parse(toolCall.arguments);
|
|
476
|
+
};
|
|
477
|
+
}
|
|
370
478
|
|
|
371
|
-
|
|
479
|
+
// Compose agent
|
|
480
|
+
const agent = (
|
|
481
|
+
<Agent id="composer" input={InputSchema} output={OutputSchema}>
|
|
482
|
+
<Prompt>
|
|
483
|
+
<System>{buildSystemPrompt('expert')}</System>
|
|
484
|
+
<User>{buildUserPrompt('Process {{task}}')}</User>
|
|
485
|
+
</Prompt>
|
|
486
|
+
<Result>{extractJSONFromToolCall('submit')}</Result>
|
|
487
|
+
</Agent>
|
|
488
|
+
);
|
|
489
|
+
```
|
|
372
490
|
|
|
373
|
-
##
|
|
491
|
+
## 📚 Utilities
|
|
374
492
|
|
|
375
|
-
|
|
493
|
+
### Tool Result Extraction
|
|
376
494
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
- **85%+ 代码覆盖率** - 核心模块
|
|
495
|
+
```typescript
|
|
496
|
+
import { extractLastToolResult, extractAllToolResults, countToolCalls } from '@limo-labs/deity';
|
|
380
497
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
498
|
+
// Extract single tool result
|
|
499
|
+
const result = extractLastToolResult(llmResult, 'tool_name', {
|
|
500
|
+
unwrap: true,
|
|
501
|
+
required: true
|
|
502
|
+
});
|
|
384
503
|
|
|
385
|
-
|
|
386
|
-
|
|
504
|
+
// Extract all results from a tool
|
|
505
|
+
const allResults = extractAllToolResults(llmResult, 'memory_store');
|
|
387
506
|
|
|
388
|
-
|
|
389
|
-
|
|
507
|
+
// Count tool calls
|
|
508
|
+
const count = countToolCalls(llmResult, 'memory_store', (result) => {
|
|
509
|
+
return result?.success === true;
|
|
510
|
+
});
|
|
390
511
|
```
|
|
391
512
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
### 1. 代码分析代理
|
|
513
|
+
### Memory Tools
|
|
395
514
|
|
|
396
515
|
```typescript
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
516
|
+
import { createMemoryTools } from '@limo-labs/deity';
|
|
517
|
+
|
|
518
|
+
const agent = (
|
|
519
|
+
<Agent
|
|
520
|
+
id="agent"
|
|
521
|
+
input={InputSchema}
|
|
522
|
+
output={OutputSchema}
|
|
523
|
+
tools={createMemoryTools()}
|
|
524
|
+
>
|
|
525
|
+
{/* Agent can now use memory_store, memory_recall, etc. */}
|
|
526
|
+
</Agent>
|
|
527
|
+
);
|
|
403
528
|
```
|
|
404
529
|
|
|
405
|
-
|
|
530
|
+
## 🏗️ Architecture
|
|
406
531
|
|
|
407
|
-
```typescript
|
|
408
|
-
// 启用对话和内存
|
|
409
|
-
const ctx = await createEnhancedContext({
|
|
410
|
-
inputs: {},
|
|
411
|
-
enableConversation: true,
|
|
412
|
-
enableMemory: true
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// 组件可以访问对话历史和记忆
|
|
416
532
|
```
|
|
533
|
+
┌─────────────────────────────────────────┐
|
|
534
|
+
│ JSX/TSX Components │
|
|
535
|
+
│ <Agent>, <Prompt>, <Result>, etc. │
|
|
536
|
+
└─────────────────────────────────────────┘
|
|
537
|
+
↓ compileAgent()
|
|
538
|
+
┌─────────────────────────────────────────┐
|
|
539
|
+
│ AST Nodes │
|
|
540
|
+
│ AgentNode, PromptNode, ResultNode │
|
|
541
|
+
└─────────────────────────────────────────┘
|
|
542
|
+
↓ executeComponent()
|
|
543
|
+
┌─────────────────────────────────────────┐
|
|
544
|
+
│ Execution Engine │
|
|
545
|
+
│ - Build Prompt │
|
|
546
|
+
│ - Call LLM Loop │
|
|
547
|
+
│ - Extract Output │
|
|
548
|
+
│ - Validate │
|
|
549
|
+
│ - Retry if needed │
|
|
550
|
+
└─────────────────────────────────────────┘
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
## 🧪 Testing
|
|
417
554
|
|
|
418
|
-
|
|
555
|
+
Deity includes utilities for testing agents:
|
|
419
556
|
|
|
420
557
|
```typescript
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
558
|
+
import { testFullAgent } from '@limo-labs/deity';
|
|
559
|
+
|
|
560
|
+
const result = await testFullAgent(agent, {
|
|
561
|
+
inputs: { task: 'test' },
|
|
562
|
+
mockLLMResponse: {
|
|
563
|
+
content: '{"result": "success"}',
|
|
564
|
+
toolCalls: []
|
|
565
|
+
}
|
|
425
566
|
});
|
|
426
567
|
|
|
427
|
-
|
|
568
|
+
expect(result.output).toEqual({ result: 'success' });
|
|
428
569
|
```
|
|
429
570
|
|
|
430
|
-
|
|
571
|
+
## 📖 Documentation
|
|
431
572
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
573
|
+
- [API Reference](./docs/API.md) - Full API documentation
|
|
574
|
+
- [**Declarative Workflow Guide**](./docs/TSX_WORKFLOW.md) - **NEW: Build workflows with declarative API**
|
|
575
|
+
- [Workflow Quick Reference](./docs/TSX_WORKFLOW_QUICK_REF.md) - Quick syntax reference
|
|
576
|
+
- [Migration Guide](./docs/MIGRATION.md) - Migrating from imperative API
|
|
577
|
+
- [Best Practices](./docs/BEST_PRACTICES.md) - Design patterns and tips
|
|
578
|
+
- [Examples](./docs/EXAMPLES.md) - Real-world examples
|
|
438
579
|
|
|
439
|
-
##
|
|
580
|
+
## 🔀 Declarative Workflows (NEW in 4.0)
|
|
440
581
|
|
|
441
|
-
|
|
582
|
+
Deity 4.0 introduces **Declarative Workflow API** - build complex multi-agent workflows with function composition:
|
|
583
|
+
|
|
584
|
+
**Note:** Despite the name "TSX Workflow", these use **function calls** (`.ts` files), not JSX tags. Only Agent definitions support true JSX/TSX syntax.
|
|
442
585
|
|
|
443
586
|
```typescript
|
|
444
|
-
|
|
445
|
-
id: 'search',
|
|
446
|
-
tools: [{
|
|
447
|
-
name: 'search_code',
|
|
448
|
-
description: 'Search codebase',
|
|
449
|
-
inputSchema: z.object({ query: z.string() }),
|
|
450
|
-
async execute(input) {
|
|
451
|
-
return { results: await searchCode(input.query) };
|
|
452
|
-
}
|
|
453
|
-
}],
|
|
454
|
-
// ...
|
|
455
|
-
};
|
|
456
|
-
```
|
|
587
|
+
import { Workflow, Sequence, Parallel, Conditional, runTSXWorkflow } from '@limo-labs/deity';
|
|
457
588
|
|
|
458
|
-
|
|
589
|
+
const workflow = Workflow({
|
|
590
|
+
name: 'code-analysis',
|
|
591
|
+
defaultModel: { adapter: llmAdapter },
|
|
592
|
+
children: Sequence({
|
|
593
|
+
children: [
|
|
594
|
+
// Step 1: Classify code
|
|
595
|
+
ClassifierAgent,
|
|
596
|
+
|
|
597
|
+
// Step 2: Branch based on complexity
|
|
598
|
+
Conditional({
|
|
599
|
+
condition: (ctx) => ctx.getOutput('classifier').isComplex,
|
|
600
|
+
children: [
|
|
601
|
+
// Complex: parallel deep analysis
|
|
602
|
+
Parallel({
|
|
603
|
+
children: [
|
|
604
|
+
SecurityAnalyzer,
|
|
605
|
+
PerformanceAnalyzer,
|
|
606
|
+
QualityAnalyzer,
|
|
607
|
+
],
|
|
608
|
+
}),
|
|
609
|
+
// Simple: quick summary
|
|
610
|
+
QuickSummary,
|
|
611
|
+
],
|
|
612
|
+
}),
|
|
613
|
+
|
|
614
|
+
// Step 3: Generate report
|
|
615
|
+
ReportGenerator,
|
|
616
|
+
],
|
|
617
|
+
}),
|
|
618
|
+
});
|
|
459
619
|
|
|
460
|
-
|
|
461
|
-
const
|
|
462
|
-
id: 'component',
|
|
463
|
-
retry: {
|
|
464
|
-
maxAttempts: 5,
|
|
465
|
-
feedbackOnError: true,
|
|
466
|
-
backoff: 'exponential'
|
|
467
|
-
},
|
|
468
|
-
validate(output, ctx) {
|
|
469
|
-
// 自定义验证逻辑
|
|
470
|
-
if (output.quality < 0.8) {
|
|
471
|
-
return {
|
|
472
|
-
valid: false,
|
|
473
|
-
errors: ['Quality too low'],
|
|
474
|
-
feedback: 'Please improve quality by focusing on...'
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
return { valid: true };
|
|
478
|
-
}
|
|
479
|
-
};
|
|
620
|
+
// Execute
|
|
621
|
+
const result = await runTSXWorkflow(workflow, { code: '...' });
|
|
480
622
|
```
|
|
481
623
|
|
|
482
|
-
###
|
|
624
|
+
### Workflow Components
|
|
483
625
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
626
|
+
- **`Sequence`** - Execute children in order (function call)
|
|
627
|
+
- **`Parallel`** - Execute children concurrently (function call)
|
|
628
|
+
- **`Conditional`** - Branch based on condition (function call)
|
|
629
|
+
- **`Loop`** - Execute child N times (function call)
|
|
630
|
+
- **`ForEach`** - Execute child for each item in array (function call)
|
|
631
|
+
|
|
632
|
+
**[➡️ Full TSX Workflow Guide](./docs/TSX_WORKFLOW.md)**
|
|
633
|
+
|
|
634
|
+
## 🔗 Integration
|
|
635
|
+
|
|
636
|
+
### LLM Adapters
|
|
494
637
|
|
|
495
|
-
|
|
638
|
+
Deity works with any LLM adapter that implements the `LLMAdapter` interface:
|
|
496
639
|
|
|
497
640
|
```typescript
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
641
|
+
interface LLMAdapter {
|
|
642
|
+
generate(
|
|
643
|
+
messages: Message[],
|
|
644
|
+
tools?: Tool[],
|
|
645
|
+
config?: GenerationConfig,
|
|
646
|
+
ctx?: ExecutionContext
|
|
647
|
+
): Promise<LLMResponse>;
|
|
648
|
+
}
|
|
502
649
|
```
|
|
503
650
|
|
|
504
|
-
|
|
651
|
+
Example adapters:
|
|
652
|
+
- `@limo-labs/deity-adapter-openai` - OpenAI GPT models
|
|
653
|
+
- `@limo-labs/deity-adapter-anthropic` - Claude models
|
|
654
|
+
- `@limo-labs/deity-adapter-copilot` - GitHub Copilot SDK
|
|
655
|
+
|
|
656
|
+
### Framework Integration
|
|
505
657
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
| **会话持久化** | ❌ | ✅ 自动保存/恢复 |
|
|
511
|
-
| **UI 集成** | ❌ | ✅ 事件驱动更新 |
|
|
512
|
-
| **性能** | ~100 ops/sec | 678,532 ops/sec |
|
|
513
|
-
| **类型安全** | ✅ | ✅ 增强 |
|
|
514
|
-
| **工作流节点** | 基础 | ✅ 条件/循环/并行 |
|
|
658
|
+
- **Express/Fastify** - Use as API handlers
|
|
659
|
+
- **Next.js** - Server actions and API routes
|
|
660
|
+
- **Electron** - Desktop app agents
|
|
661
|
+
- **CLI Tools** - Command-line AI agents
|
|
515
662
|
|
|
516
|
-
## 🤝
|
|
663
|
+
## 🤝 Contributing
|
|
517
664
|
|
|
518
|
-
|
|
665
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
519
666
|
|
|
520
|
-
## 📄
|
|
667
|
+
## 📄 License
|
|
521
668
|
|
|
522
669
|
MIT © [Limo Labs](https://github.com/limo-labs)
|
|
523
670
|
|
|
524
|
-
## 🔗
|
|
671
|
+
## 🔗 Links
|
|
525
672
|
|
|
526
|
-
- [GitHub](https://github.com/
|
|
527
|
-
- [
|
|
528
|
-
- [
|
|
529
|
-
- [
|
|
673
|
+
- [GitHub](https://github.com/Limo-Labs/Limo-Deity)
|
|
674
|
+
- [npm](https://www.npmjs.com/package/@limo-labs/deity)
|
|
675
|
+
- [Documentation](https://deity.limo.run)
|
|
676
|
+
- [Issues](https://github.com/Limo-Labs/Limo-Deity/issues)
|
|
677
|
+
- [Changelog](./CHANGELOG.md)
|
|
530
678
|
|
|
531
679
|
---
|
|
532
680
|
|
|
533
|
-
|
|
681
|
+
**Built with ❤️ by Limo Labs**
|