foliko 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/.claude/settings.local.json +30 -0
- package/22.txt +10 -0
- package/README.md +218 -0
- package/SPEC.md +452 -0
- package/cli/bin/foliko.js +12 -0
- package/cli/src/commands/chat.js +75 -0
- package/cli/src/index.js +64 -0
- package/cli/src/ui/chat-ui.js +272 -0
- package/cli/src/utils/ansi.js +40 -0
- package/cli/src/utils/markdown.js +296 -0
- package/docs/quick-reference.md +131 -0
- package/docs/user-manual.md +1205 -0
- package/examples/basic.js +110 -0
- package/examples/bootstrap.js +93 -0
- package/examples/mcp-example.js +53 -0
- package/examples/skill-example.js +49 -0
- package/examples/workflow.js +158 -0
- package/package.json +36 -0
- package/plugins/ai-plugin.js +89 -0
- package/plugins/audit-plugin.js +187 -0
- package/plugins/default-plugins.js +412 -0
- package/plugins/file-system-plugin.js +344 -0
- package/plugins/install-plugin.js +93 -0
- package/plugins/python-executor-plugin.js +331 -0
- package/plugins/rules-plugin.js +292 -0
- package/plugins/scheduler-plugin.js +426 -0
- package/plugins/session-plugin.js +343 -0
- package/plugins/shell-executor-plugin.js +196 -0
- package/plugins/storage-plugin.js +237 -0
- package/plugins/subagent-plugin.js +395 -0
- package/plugins/think-plugin.js +329 -0
- package/plugins/tools-plugin.js +114 -0
- package/skills/mcp-usage/SKILL.md +198 -0
- package/skills/vb-agent-dev/AGENTS.md +162 -0
- package/skills/vb-agent-dev/SKILL.md +370 -0
- package/src/capabilities/index.js +11 -0
- package/src/capabilities/skill-manager.js +319 -0
- package/src/capabilities/workflow-engine.js +401 -0
- package/src/core/agent-chat.js +311 -0
- package/src/core/agent.js +573 -0
- package/src/core/framework.js +255 -0
- package/src/core/index.js +19 -0
- package/src/core/plugin-base.js +205 -0
- package/src/core/plugin-manager.js +392 -0
- package/src/core/provider.js +108 -0
- package/src/core/tool-registry.js +134 -0
- package/src/core/tool-router.js +216 -0
- package/src/executors/executor-base.js +58 -0
- package/src/executors/mcp-executor.js +728 -0
- package/src/index.js +37 -0
- package/src/utils/event-emitter.js +97 -0
- package/test-chat.js +129 -0
- package/test-mcp.js +79 -0
- package/test-reload.js +61 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 基础示例
|
|
3
|
+
* 展示如何使用 Framework 和 Agent
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Framework } = require('../src')
|
|
7
|
+
const { AIPlugin } = require('../plugins/ai-plugin')
|
|
8
|
+
const { z } = require('zod')
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
// 创建框架实例
|
|
12
|
+
const framework = new Framework({ debug: true })
|
|
13
|
+
|
|
14
|
+
// 加载 AI 插件
|
|
15
|
+
await framework.loadPlugin(new AIPlugin({
|
|
16
|
+
provider: 'deepseek',
|
|
17
|
+
model: 'deepseek-chat',
|
|
18
|
+
apiKey: process.env.DEEPSEEK_API_KEY || 'your-api-key'
|
|
19
|
+
}))
|
|
20
|
+
|
|
21
|
+
// 注册自定义工具(使用 inputSchema 格式)
|
|
22
|
+
framework.registerTool({
|
|
23
|
+
name: 'hello',
|
|
24
|
+
description: '打招呼工具',
|
|
25
|
+
inputSchema: z.object({
|
|
26
|
+
name: z.string().optional().describe('姓名')
|
|
27
|
+
}),
|
|
28
|
+
execute: async (args) => {
|
|
29
|
+
return `Hello, ${args.name || 'World'}!`
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
// 注册计算器工具
|
|
34
|
+
framework.registerTool({
|
|
35
|
+
name: 'calculate',
|
|
36
|
+
description: '简单的计算器',
|
|
37
|
+
inputSchema: z.object({
|
|
38
|
+
expression: z.string().describe('数学表达式,如 2+3*4')
|
|
39
|
+
}),
|
|
40
|
+
execute: async (args) => {
|
|
41
|
+
try {
|
|
42
|
+
// 安全计算(仅支持基本运算)
|
|
43
|
+
const result = Function(`"use strict"; return (${args.expression})`)()
|
|
44
|
+
return { result }
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return { error: e.message }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
console.log('[Framework] Ready!')
|
|
52
|
+
console.log('[Tools]', framework.getTools().map(t => t.name))
|
|
53
|
+
|
|
54
|
+
// 创建 Agent
|
|
55
|
+
const agent = framework.createAgent({
|
|
56
|
+
name: 'MyAgent',
|
|
57
|
+
systemPrompt: '你是一个有帮助的助手。当需要计算时,使用 calculate 工具。'
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// 监听事件
|
|
61
|
+
agent.on('tool-call', (tool) => {
|
|
62
|
+
console.log('[Agent] Tool call:', tool.name, tool.args)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
agent.on('tool-result', (result) => {
|
|
66
|
+
console.log('[Agent] Tool result:', result.name, result.result)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// AI 对话示例
|
|
70
|
+
console.log('\n=== AI Chat Example ===')
|
|
71
|
+
try {
|
|
72
|
+
const response = await agent.chat('你好!')
|
|
73
|
+
console.log('[Agent] Response:', response.message)
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error('[Agent] Error:', err.message)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 使用工具的对话示例
|
|
79
|
+
console.log('\n=== AI Chat with Tool Call ===')
|
|
80
|
+
try {
|
|
81
|
+
const response = await agent.chat('请帮我计算 (15 + 25) * 2 等于多少?')
|
|
82
|
+
console.log('[Agent] Response:', response.message)
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.error('[Agent] Error:', err.message)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 流式对话示例
|
|
88
|
+
console.log('\n=== Streaming Chat ===')
|
|
89
|
+
try {
|
|
90
|
+
for await (const chunk of agent.chatStream('请用中文介绍一下你自己')) {
|
|
91
|
+
if (chunk.type === 'text') {
|
|
92
|
+
process.stdout.write(chunk.text)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
console.log('\n')
|
|
96
|
+
} catch (err) {
|
|
97
|
+
console.error('[Agent] Stream Error:', err.message)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 热重载示例
|
|
101
|
+
console.log('\n=== Hot Reload ===')
|
|
102
|
+
await framework.reloadPlugin('ai')
|
|
103
|
+
console.log('AI plugin reloaded!')
|
|
104
|
+
|
|
105
|
+
// 清理
|
|
106
|
+
await framework.destroy()
|
|
107
|
+
console.log('\n[Done]')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
main().catch(console.error)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstrap 示例
|
|
3
|
+
* 使用 framework.bootstrap() 自动加载 .agent/ 目录配置
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Framework } = require('../src')
|
|
7
|
+
const { z } = require('zod')
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log('=== Bootstrap Example ===\n')
|
|
11
|
+
|
|
12
|
+
// 创建框架
|
|
13
|
+
const framework = new Framework({ debug: true })
|
|
14
|
+
|
|
15
|
+
// 使用 bootstrap 自动加载所有默认插件
|
|
16
|
+
// 会自动检测 .agent/ 目录下的配置
|
|
17
|
+
await framework.bootstrap({
|
|
18
|
+
agentDir: './.agent', // 配置目录
|
|
19
|
+
aiConfig: { // 可选:覆盖 AI 配置
|
|
20
|
+
provider: 'deepseek',
|
|
21
|
+
model: 'deepseek-chat',
|
|
22
|
+
apiKey: process.env.DEEPSEEK_API_KEY || 'your-api-key'
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// 注册 hello 工具(演示用)
|
|
27
|
+
framework.registerTool({
|
|
28
|
+
name: 'hello',
|
|
29
|
+
description: '打招呼',
|
|
30
|
+
inputSchema: z.object({
|
|
31
|
+
name: z.string().optional().describe('姓名')
|
|
32
|
+
}),
|
|
33
|
+
execute: async (args) => `Hello, ${args.name || 'World'}!`
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
console.log('\n--- Framework Ready ---')
|
|
37
|
+
console.log('Plugins:', framework.pluginManager.getAll().map(p => p.name))
|
|
38
|
+
console.log('Tools:', framework.getTools().map(t => t.name))
|
|
39
|
+
|
|
40
|
+
// 创建 Agent (支持 sharedPrompt 和 metadata)
|
|
41
|
+
const agent = framework.createAgent({
|
|
42
|
+
name: 'MyAgent',
|
|
43
|
+
systemPrompt: '你是一个有帮助的助手。',
|
|
44
|
+
sharedPrompt: '工作目录: {{WORK_DIR}}\n用户名: {{USER_NAME}}\n当前时间: {{TIME}}',
|
|
45
|
+
metadata: {
|
|
46
|
+
projectName: 'VB-Agent',
|
|
47
|
+
version: '1.0.0'
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
console.log('\n--- Agent Context ---')
|
|
52
|
+
console.log(agent.systemPrompt)
|
|
53
|
+
|
|
54
|
+
// 测试对话
|
|
55
|
+
console.log('\n--- AI Chat Test ---')
|
|
56
|
+
// try {
|
|
57
|
+
// const response = await agent.chat('帮我开发一个获取系统信息的插件')
|
|
58
|
+
// console.log('Agent:', response.message)
|
|
59
|
+
// } catch (err) {
|
|
60
|
+
// console.error('Chat error:', err.message)
|
|
61
|
+
// }
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
for await (const chunk of agent.chatStream('帮我开发一个获取系统信息的插件')) {
|
|
65
|
+
if (chunk.type === 'text') {
|
|
66
|
+
process.stdout.write(chunk.text)
|
|
67
|
+
}else if (chunk?.type === 'tool-call') {
|
|
68
|
+
console.log(`\n[工具调用: ${chunk.toolName}]`);
|
|
69
|
+
} else if (chunk?.type === 'tool-result') {
|
|
70
|
+
console.log(`\n[工具结果: ${chunk.toolName}]`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
console.log('\n')
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error('[Agent] Stream Error:', err.message)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 测试工具调用
|
|
79
|
+
console.log('\n--- Tool Call Test ---')
|
|
80
|
+
const result = await framework.executeTool('hello', { name: 'Bootstrap' })
|
|
81
|
+
console.log('Tool result:', result)
|
|
82
|
+
|
|
83
|
+
// 测试内置工具
|
|
84
|
+
console.log('\n--- Built-in Tools Test ---')
|
|
85
|
+
const listResult = await framework.executeTool('list_plugins', {})
|
|
86
|
+
console.log('list_plugins:', listResult)
|
|
87
|
+
|
|
88
|
+
// 清理
|
|
89
|
+
await framework.destroy()
|
|
90
|
+
console.log('\n[Done]')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
main().catch(console.error)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP 执行器示例
|
|
3
|
+
* 展示如何连接 MCP 服务器
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Framework } = require('../src')
|
|
7
|
+
const { MCPExecutorPlugin } = require('../src/executors/mcp-executor')
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log('=== MCP Executor Example ===\n')
|
|
11
|
+
|
|
12
|
+
// 创建框架
|
|
13
|
+
const framework = new Framework({ debug: true })
|
|
14
|
+
|
|
15
|
+
// 创建 MCP 执行器插件
|
|
16
|
+
const mcpPlugin = new MCPExecutorPlugin({
|
|
17
|
+
servers: [
|
|
18
|
+
// 示例:添加一个 MCP 服务器
|
|
19
|
+
// {
|
|
20
|
+
// name: 'example',
|
|
21
|
+
// command: 'uvx',
|
|
22
|
+
// args: ['example-mcp-server'],
|
|
23
|
+
// env: {}
|
|
24
|
+
// }
|
|
25
|
+
]
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// 加载插件
|
|
29
|
+
await framework.loadPlugin(mcpPlugin)
|
|
30
|
+
|
|
31
|
+
// 列出服务器
|
|
32
|
+
console.log('\n--- MCP Servers ---')
|
|
33
|
+
const servers = mcpPlugin.getServers()
|
|
34
|
+
console.log('Servers:', servers)
|
|
35
|
+
|
|
36
|
+
// 列出所有 MCP 工具
|
|
37
|
+
console.log('\n--- MCP Tools ---')
|
|
38
|
+
const tools = framework.getTools().filter(t => t.name.startsWith('mcp_'))
|
|
39
|
+
console.log('MCP tools:', tools.map(t => t.name))
|
|
40
|
+
|
|
41
|
+
// 如果有配置的服务器,可以这样调用:
|
|
42
|
+
// const result = await framework.executeTool('mcp_call', {
|
|
43
|
+
// server: 'example',
|
|
44
|
+
// tool: 'tool_name',
|
|
45
|
+
// args: { /* tool arguments */ }
|
|
46
|
+
// })
|
|
47
|
+
|
|
48
|
+
// 清理
|
|
49
|
+
await framework.destroy()
|
|
50
|
+
console.log('\n[Done]')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
main().catch(console.error)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill 管理器示例
|
|
3
|
+
* 展示如何加载和使用 Skill
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Framework } = require('../src')
|
|
7
|
+
const { SkillManagerPlugin } = require('../src/capabilities/skill-manager')
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log('=== Skill Manager Example ===\n')
|
|
11
|
+
|
|
12
|
+
// 创建框架
|
|
13
|
+
const framework = new Framework({ debug: true })
|
|
14
|
+
|
|
15
|
+
// 创建 skills 目录(如果没有)
|
|
16
|
+
const fs = require('fs')
|
|
17
|
+
const skillsDir = './skills'
|
|
18
|
+
if (!fs.existsSync(skillsDir)) {
|
|
19
|
+
fs.mkdirSync(skillsDir, { recursive: true })
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 加载 Skill 管理器插件
|
|
23
|
+
const skillPlugin = new SkillManagerPlugin({
|
|
24
|
+
skillsDir: skillsDir
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
await framework.loadPlugin(skillPlugin)
|
|
28
|
+
|
|
29
|
+
// 列出所有加载的 skills
|
|
30
|
+
console.log('\n--- Loaded Skills ---')
|
|
31
|
+
const skills = skillPlugin.getAllSkills()
|
|
32
|
+
console.log(`Found ${skills.length} skills:`)
|
|
33
|
+
for (const skill of skills) {
|
|
34
|
+
console.log(` - ${skill.name}: ${skill.metadata.description}`)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 获取单个 skill
|
|
38
|
+
if (skillPlugin.hasSkill('hello-skill')) {
|
|
39
|
+
console.log('\n--- Hello Skill ---')
|
|
40
|
+
const helloSkill = skillPlugin.getSkill('hello-skill')
|
|
41
|
+
console.log('Content preview:', helloSkill.content.substring(0, 100) + '...')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 清理
|
|
45
|
+
await framework.destroy()
|
|
46
|
+
console.log('\n[Done]')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
main().catch(console.error)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 工作流示例
|
|
3
|
+
* 展示如何使用工作流引擎
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Framework } = require('../src')
|
|
7
|
+
const { WorkflowPlugin } = require('../src/capabilities/workflow-engine')
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log('=== Workflow Example ===\n')
|
|
11
|
+
|
|
12
|
+
// 创建框架
|
|
13
|
+
const framework = new Framework({ debug: true })
|
|
14
|
+
|
|
15
|
+
// 加载工作流插件
|
|
16
|
+
await framework.loadPlugin(new WorkflowPlugin())
|
|
17
|
+
|
|
18
|
+
console.log('\n--- Testing Script Step ---')
|
|
19
|
+
|
|
20
|
+
// 直接执行工作流
|
|
21
|
+
const result1 = await framework.executeTool('execute_workflow', {
|
|
22
|
+
workflow: JSON.stringify({
|
|
23
|
+
steps: [
|
|
24
|
+
{
|
|
25
|
+
type: 'script',
|
|
26
|
+
name: 'Calculate',
|
|
27
|
+
script: `
|
|
28
|
+
const a = 10;
|
|
29
|
+
const b = 20;
|
|
30
|
+
context.variables.sum = a + b;
|
|
31
|
+
return a + b;
|
|
32
|
+
`
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: 'script',
|
|
36
|
+
name: 'Multiply',
|
|
37
|
+
script: `
|
|
38
|
+
const sum = context.variables.sum;
|
|
39
|
+
context.variables.product = sum * 2;
|
|
40
|
+
return sum * 2;
|
|
41
|
+
`
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}),
|
|
45
|
+
input: {}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
console.log('Result:', result1)
|
|
49
|
+
|
|
50
|
+
console.log('\n--- Testing Loop Step ---')
|
|
51
|
+
|
|
52
|
+
const result2 = await framework.executeTool('execute_workflow', {
|
|
53
|
+
workflow: JSON.stringify({
|
|
54
|
+
steps: [
|
|
55
|
+
{
|
|
56
|
+
type: 'loop',
|
|
57
|
+
name: 'Loop 3 times',
|
|
58
|
+
maxIterations: 3,
|
|
59
|
+
loopVariable: 'i',
|
|
60
|
+
steps: [
|
|
61
|
+
{
|
|
62
|
+
type: 'script',
|
|
63
|
+
name: 'Log iteration',
|
|
64
|
+
script: `
|
|
65
|
+
console.log('Iteration ' + context.variables.i);
|
|
66
|
+
return context.variables.i;
|
|
67
|
+
`
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}),
|
|
73
|
+
input: {}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
console.log('Result:', result2)
|
|
77
|
+
|
|
78
|
+
console.log('\n--- Testing Condition Step ---')
|
|
79
|
+
|
|
80
|
+
const result3 = await framework.executeTool('execute_workflow', {
|
|
81
|
+
workflow: JSON.stringify({
|
|
82
|
+
steps: [
|
|
83
|
+
{
|
|
84
|
+
type: 'script',
|
|
85
|
+
name: 'Set value',
|
|
86
|
+
outputVariable: 'value',
|
|
87
|
+
script: `
|
|
88
|
+
context.variables.value = 15;
|
|
89
|
+
return 15;
|
|
90
|
+
`
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'condition',
|
|
94
|
+
name: 'Check value',
|
|
95
|
+
branches: [
|
|
96
|
+
{
|
|
97
|
+
name: 'Greater than 10',
|
|
98
|
+
condition: 'context.variables.value > 10',
|
|
99
|
+
steps: [
|
|
100
|
+
{
|
|
101
|
+
type: 'script',
|
|
102
|
+
name: 'Log greater',
|
|
103
|
+
script: `console.log('Value is greater than 10'); return 'greater';`
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'Less than or equal 10',
|
|
109
|
+
condition: 'context.variables.value <= 10',
|
|
110
|
+
steps: [
|
|
111
|
+
{
|
|
112
|
+
type: 'script',
|
|
113
|
+
name: 'Log less',
|
|
114
|
+
script: `console.log('Value is less than or equal 10'); return 'less-or-equal';`
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}),
|
|
122
|
+
input: {}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
console.log('Result:', result3)
|
|
126
|
+
|
|
127
|
+
console.log('\n--- Testing Delay ---')
|
|
128
|
+
|
|
129
|
+
const startTime = Date.now()
|
|
130
|
+
const result4 = await framework.executeTool('execute_workflow', {
|
|
131
|
+
workflow: JSON.stringify({
|
|
132
|
+
steps: [
|
|
133
|
+
{
|
|
134
|
+
type: 'delay',
|
|
135
|
+
name: 'Wait 500ms',
|
|
136
|
+
delayMs: 500
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: 'script',
|
|
140
|
+
name: 'Check elapsed',
|
|
141
|
+
script: `
|
|
142
|
+
const elapsed = Date.now() - context.variables.startTime;
|
|
143
|
+
return { elapsed: elapsed, expected: 500 };
|
|
144
|
+
`
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}),
|
|
148
|
+
input: {}
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
console.log('Result:', result4)
|
|
152
|
+
|
|
153
|
+
// 清理
|
|
154
|
+
await framework.destroy()
|
|
155
|
+
console.log('\n[Done]')
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
main().catch(console.error)
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "foliko",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "简约的插件化 Agent 框架",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"foliko": "./cli/bin/foliko.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node examples/basic.js",
|
|
11
|
+
"chat": "node cli/bin/foliko.js chat",
|
|
12
|
+
"test": "echo \"No tests yet\""
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"agent",
|
|
16
|
+
"ai",
|
|
17
|
+
"framework",
|
|
18
|
+
"plugin"
|
|
19
|
+
],
|
|
20
|
+
"author": "",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@ai-sdk/anthropic": "^3.0.58",
|
|
24
|
+
"@ai-sdk/mcp": "^1.0.25",
|
|
25
|
+
"@ai-sdk/openai": "^3.0.41",
|
|
26
|
+
"@ai-sdk/openai-compatible": "^2.0.35",
|
|
27
|
+
"@anthropic-ai/sdk": "^0.39.0",
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
29
|
+
"ai": "^6.0.116",
|
|
30
|
+
"dotenv": "^17.3.1",
|
|
31
|
+
"marked": "^11.2.0",
|
|
32
|
+
"marked-terminal": "6",
|
|
33
|
+
"node-cron": "^4.2.1",
|
|
34
|
+
"zod": "^4.3.6"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI 插件
|
|
3
|
+
* 提供 AI 对话能力
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Plugin } = require('../src/core/plugin-base')
|
|
7
|
+
const { createAI } = require('../src/core/provider')
|
|
8
|
+
|
|
9
|
+
class AIPlugin extends Plugin {
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
super()
|
|
12
|
+
this.name = 'ai'
|
|
13
|
+
this.version = '1.0.0'
|
|
14
|
+
this.description = 'AI 对话能力插件'
|
|
15
|
+
this.priority = 1 // 最先加载
|
|
16
|
+
|
|
17
|
+
this.config = {
|
|
18
|
+
provider: config.provider || 'deepseek',
|
|
19
|
+
model: config.model || 'deepseek-chat',
|
|
20
|
+
apiKey: config.apiKey,
|
|
21
|
+
baseURL: config.baseURL,
|
|
22
|
+
maxSteps: config.maxSteps || 20
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this._aiClient = null
|
|
26
|
+
this._framework = null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
install(framework) {
|
|
30
|
+
this._framework = framework
|
|
31
|
+
return this
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
start(framework) {
|
|
35
|
+
this._initAIClient()
|
|
36
|
+
return this
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_initAIClient() {
|
|
40
|
+
if (!this.config.apiKey) {
|
|
41
|
+
console.warn('[AIPlugin] No API key provided, AI features disabled')
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const provider = createAI({
|
|
47
|
+
provider: this.config.provider,
|
|
48
|
+
model: this.config.model,
|
|
49
|
+
apiKey: this.config.apiKey,
|
|
50
|
+
baseURL: this.config.baseURL
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// 创建模型实例
|
|
54
|
+
this._aiClient = provider(this.config.model)
|
|
55
|
+
console.log(`[AIPlugin] Initialized ${this.config.provider}/${this.config.model}`)
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error('[AIPlugin] Failed to initialize AI client:', err.message)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 获取 AI 客户端
|
|
63
|
+
* @returns {Object} AI 模型客户端
|
|
64
|
+
*/
|
|
65
|
+
getAIClient() {
|
|
66
|
+
return this._aiClient
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 获取配置
|
|
71
|
+
* @returns {Object}
|
|
72
|
+
*/
|
|
73
|
+
getConfig() {
|
|
74
|
+
return { ...this.config }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
reload(framework) {
|
|
78
|
+
console.log('[AIPlugin] Reloading...')
|
|
79
|
+
this._framework = framework
|
|
80
|
+
this._initAIClient()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
uninstall(framework) {
|
|
84
|
+
this._aiClient = null
|
|
85
|
+
this._framework = null
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = { AIPlugin }
|