foliko 2.0.18 → 2.0.20
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/.editorconfig +56 -56
- package/.lintstagedrc +7 -7
- package/.prettierignore +29 -29
- package/.prettierrc +11 -11
- package/Dockerfile +63 -63
- package/install.ps1 +129 -129
- package/install.sh +121 -121
- package/package.json +1 -1
- package/plugins/core/planner/PROMPT.md +73 -0
- package/plugins/core/planner/index.js +926 -0
- package/plugins/core/workflow/context.js +941 -941
- package/plugins/core/workflow/engine.js +66 -66
- package/plugins/core/workflow/js-runner.js +318 -318
- package/plugins/core/workflow/json-runner.js +323 -323
- package/plugins/core/workflow/stages/choice.js +74 -74
- package/plugins/core/workflow/stages/each.js +123 -123
- package/plugins/core/workflow/stages/parallel.js +69 -69
- package/plugins/messaging/weixin/index.js +145 -0
- package/skills/find-skills/SKILL.md +133 -133
- package/src/agent/chat.js +124 -15
- package/tests/plugins/planner.test.js +630 -0
package/install.sh
CHANGED
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Foliko Installer
|
|
3
|
-
|
|
4
|
-
set -e
|
|
5
|
-
|
|
6
|
-
echo -e "\033[36mFoliko Installer\033[0m"
|
|
7
|
-
echo -e "\033[36m=================\033[0m"
|
|
8
|
-
echo ""
|
|
9
|
-
|
|
10
|
-
# Detect OS
|
|
11
|
-
detect_os() {
|
|
12
|
-
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
13
|
-
echo "macOS"
|
|
14
|
-
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
15
|
-
echo "Linux"
|
|
16
|
-
else
|
|
17
|
-
echo "unknown"
|
|
18
|
-
fi
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
OS=$(detect_os)
|
|
22
|
-
|
|
23
|
-
# ============ Check/Install Node.js ============
|
|
24
|
-
echo -e "\033[36mChecking Node.js...\033[0m"
|
|
25
|
-
if command -v node &> /dev/null; then
|
|
26
|
-
echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
|
|
27
|
-
else
|
|
28
|
-
echo -e "\033[33mNode.js not found, installing...\033[0m"
|
|
29
|
-
|
|
30
|
-
if [[ "$OS" == "macOS" ]]; then
|
|
31
|
-
if command -v brew &> /dev/null; then
|
|
32
|
-
brew install node
|
|
33
|
-
else
|
|
34
|
-
echo -e "\033[31mHomebrew not found. Install it first:\033[0m"
|
|
35
|
-
echo "/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
|
|
36
|
-
exit 1
|
|
37
|
-
fi
|
|
38
|
-
elif [[ "$OS" == "Linux" ]]; then
|
|
39
|
-
if command -v apt-get &> /dev/null; then
|
|
40
|
-
sudo apt-get update && sudo apt-get install -y nodejs npm
|
|
41
|
-
elif command -v yum &> /dev/null; then
|
|
42
|
-
sudo yum install -y nodejs npm
|
|
43
|
-
elif command -v pacman &> /dev/null; then
|
|
44
|
-
sudo pacman -S nodejs npm
|
|
45
|
-
else
|
|
46
|
-
echo -e "\033[31mNo package manager found. Install Node.js manually: https://nodejs.org/\033[0m"
|
|
47
|
-
exit 1
|
|
48
|
-
fi
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
if command -v node &> /dev/null; then
|
|
52
|
-
echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
|
|
53
|
-
else
|
|
54
|
-
echo -e "\033[31mNode.js installation failed\033[0m"
|
|
55
|
-
exit 1
|
|
56
|
-
fi
|
|
57
|
-
fi
|
|
58
|
-
echo ""
|
|
59
|
-
|
|
60
|
-
# ============ Check/Install Python ============
|
|
61
|
-
echo -e "\033[36mChecking Python...\033[0m"
|
|
62
|
-
if command -v python3 &> /dev/null; then
|
|
63
|
-
echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
|
|
64
|
-
else
|
|
65
|
-
echo -e "\033[33mPython not found, installing...\033[0m"
|
|
66
|
-
|
|
67
|
-
if [[ "$OS" == "macOS" ]]; then
|
|
68
|
-
if command -v brew &> /dev/null; then
|
|
69
|
-
brew install python3
|
|
70
|
-
fi
|
|
71
|
-
elif [[ "$OS" == "Linux" ]]; then
|
|
72
|
-
if command -v apt-get &> /dev/null; then
|
|
73
|
-
sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
|
|
74
|
-
elif command -v yum &> /dev/null; then
|
|
75
|
-
sudo yum install -y python3
|
|
76
|
-
elif command -v pacman &> /dev/null; then
|
|
77
|
-
sudo pacman -S python python-pip
|
|
78
|
-
fi
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
if command -v python3 &> /dev/null; then
|
|
82
|
-
echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
|
|
83
|
-
else
|
|
84
|
-
echo -e "\033[33mPython installation failed (optional)\033[0m"
|
|
85
|
-
fi
|
|
86
|
-
fi
|
|
87
|
-
echo ""
|
|
88
|
-
|
|
89
|
-
# ============ Check/Install uv ============
|
|
90
|
-
echo -e "\033[36mChecking uv...\033[0m"
|
|
91
|
-
if command -v uv &> /dev/null; then
|
|
92
|
-
echo -e "\033[32muv installed: $(uv --version)\033[0m"
|
|
93
|
-
else
|
|
94
|
-
echo -e "\033[33muv not found, installing...\033[0m"
|
|
95
|
-
|
|
96
|
-
if [[ "$OS" == "macOS" ]] || [[ "$OS" == "Linux" ]]; then
|
|
97
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
98
|
-
source $HOME/.local/bin/env 2>/dev/null || true
|
|
99
|
-
|
|
100
|
-
if command -v uv &> /dev/null; then
|
|
101
|
-
echo -e "\033[32muv installed: $(uv --version)\033[0m"
|
|
102
|
-
else
|
|
103
|
-
echo -e "\033[33muv installation failed (optional)\033[0m"
|
|
104
|
-
fi
|
|
105
|
-
fi
|
|
106
|
-
fi
|
|
107
|
-
echo ""
|
|
108
|
-
|
|
109
|
-
# ============ Install Foliko ============
|
|
110
|
-
echo -e "\033[36mInstalling Foliko...\033[0m"
|
|
111
|
-
npm install -g foliko
|
|
112
|
-
|
|
113
|
-
if command -v foliko &> /dev/null; then
|
|
114
|
-
echo ""
|
|
115
|
-
echo -e "\033[32mInstallation complete!\033[0m"
|
|
116
|
-
echo "Run: foliko chat"
|
|
117
|
-
else
|
|
118
|
-
echo ""
|
|
119
|
-
echo -e "\033[31mInstallation failed. Try manually: npm install -g foliko\033[0m"
|
|
120
|
-
exit 1
|
|
121
|
-
fi
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Foliko Installer
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
echo -e "\033[36mFoliko Installer\033[0m"
|
|
7
|
+
echo -e "\033[36m=================\033[0m"
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Detect OS
|
|
11
|
+
detect_os() {
|
|
12
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
13
|
+
echo "macOS"
|
|
14
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
15
|
+
echo "Linux"
|
|
16
|
+
else
|
|
17
|
+
echo "unknown"
|
|
18
|
+
fi
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
OS=$(detect_os)
|
|
22
|
+
|
|
23
|
+
# ============ Check/Install Node.js ============
|
|
24
|
+
echo -e "\033[36mChecking Node.js...\033[0m"
|
|
25
|
+
if command -v node &> /dev/null; then
|
|
26
|
+
echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
|
|
27
|
+
else
|
|
28
|
+
echo -e "\033[33mNode.js not found, installing...\033[0m"
|
|
29
|
+
|
|
30
|
+
if [[ "$OS" == "macOS" ]]; then
|
|
31
|
+
if command -v brew &> /dev/null; then
|
|
32
|
+
brew install node
|
|
33
|
+
else
|
|
34
|
+
echo -e "\033[31mHomebrew not found. Install it first:\033[0m"
|
|
35
|
+
echo "/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
elif [[ "$OS" == "Linux" ]]; then
|
|
39
|
+
if command -v apt-get &> /dev/null; then
|
|
40
|
+
sudo apt-get update && sudo apt-get install -y nodejs npm
|
|
41
|
+
elif command -v yum &> /dev/null; then
|
|
42
|
+
sudo yum install -y nodejs npm
|
|
43
|
+
elif command -v pacman &> /dev/null; then
|
|
44
|
+
sudo pacman -S nodejs npm
|
|
45
|
+
else
|
|
46
|
+
echo -e "\033[31mNo package manager found. Install Node.js manually: https://nodejs.org/\033[0m"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if command -v node &> /dev/null; then
|
|
52
|
+
echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
|
|
53
|
+
else
|
|
54
|
+
echo -e "\033[31mNode.js installation failed\033[0m"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
fi
|
|
58
|
+
echo ""
|
|
59
|
+
|
|
60
|
+
# ============ Check/Install Python ============
|
|
61
|
+
echo -e "\033[36mChecking Python...\033[0m"
|
|
62
|
+
if command -v python3 &> /dev/null; then
|
|
63
|
+
echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
|
|
64
|
+
else
|
|
65
|
+
echo -e "\033[33mPython not found, installing...\033[0m"
|
|
66
|
+
|
|
67
|
+
if [[ "$OS" == "macOS" ]]; then
|
|
68
|
+
if command -v brew &> /dev/null; then
|
|
69
|
+
brew install python3
|
|
70
|
+
fi
|
|
71
|
+
elif [[ "$OS" == "Linux" ]]; then
|
|
72
|
+
if command -v apt-get &> /dev/null; then
|
|
73
|
+
sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
|
|
74
|
+
elif command -v yum &> /dev/null; then
|
|
75
|
+
sudo yum install -y python3
|
|
76
|
+
elif command -v pacman &> /dev/null; then
|
|
77
|
+
sudo pacman -S python python-pip
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
if command -v python3 &> /dev/null; then
|
|
82
|
+
echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
|
|
83
|
+
else
|
|
84
|
+
echo -e "\033[33mPython installation failed (optional)\033[0m"
|
|
85
|
+
fi
|
|
86
|
+
fi
|
|
87
|
+
echo ""
|
|
88
|
+
|
|
89
|
+
# ============ Check/Install uv ============
|
|
90
|
+
echo -e "\033[36mChecking uv...\033[0m"
|
|
91
|
+
if command -v uv &> /dev/null; then
|
|
92
|
+
echo -e "\033[32muv installed: $(uv --version)\033[0m"
|
|
93
|
+
else
|
|
94
|
+
echo -e "\033[33muv not found, installing...\033[0m"
|
|
95
|
+
|
|
96
|
+
if [[ "$OS" == "macOS" ]] || [[ "$OS" == "Linux" ]]; then
|
|
97
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
98
|
+
source $HOME/.local/bin/env 2>/dev/null || true
|
|
99
|
+
|
|
100
|
+
if command -v uv &> /dev/null; then
|
|
101
|
+
echo -e "\033[32muv installed: $(uv --version)\033[0m"
|
|
102
|
+
else
|
|
103
|
+
echo -e "\033[33muv installation failed (optional)\033[0m"
|
|
104
|
+
fi
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
echo ""
|
|
108
|
+
|
|
109
|
+
# ============ Install Foliko ============
|
|
110
|
+
echo -e "\033[36mInstalling Foliko...\033[0m"
|
|
111
|
+
npm install -g foliko
|
|
112
|
+
|
|
113
|
+
if command -v foliko &> /dev/null; then
|
|
114
|
+
echo ""
|
|
115
|
+
echo -e "\033[32mInstallation complete!\033[0m"
|
|
116
|
+
echo "Run: foliko chat"
|
|
117
|
+
else
|
|
118
|
+
echo ""
|
|
119
|
+
echo -e "\033[31mInstallation failed. Try manually: npm install -g foliko\033[0m"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
package/package.json
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
## 计划模式
|
|
2
|
+
|
|
3
|
+
你是一个懂得"先规划再执行"的助手。当用户请求满足以下任一条件时,**必须**先调用 `plan_create` 创建计划,再依次执行:
|
|
4
|
+
|
|
5
|
+
**触发条件(满足任一即进入):**
|
|
6
|
+
- 涉及多个步骤(>= 3 步)
|
|
7
|
+
- 涉及多个文件或多个工具
|
|
8
|
+
- 任务可能需要中断后继续(用户说"分步"、"步骤"、"先 X 再 Y"、"计划一下")
|
|
9
|
+
- 任务复杂、耗时、或结果不确定
|
|
10
|
+
- 涉及代码/配置修改并需要 git commit
|
|
11
|
+
|
|
12
|
+
**工作流(同步串行,单次对话内完成):**
|
|
13
|
+
|
|
14
|
+
1. **plan_create**:
|
|
15
|
+
```
|
|
16
|
+
plan_create({
|
|
17
|
+
title: "短标题",
|
|
18
|
+
task: "原始任务描述",
|
|
19
|
+
steps: [
|
|
20
|
+
{ name: "步骤1", description: "详细说明", tool: "可选" },
|
|
21
|
+
{ name: "步骤2", ... },
|
|
22
|
+
...
|
|
23
|
+
]
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
返回 `{planId, stepsCount, markdownPath, currentStep: 0}`
|
|
27
|
+
|
|
28
|
+
2. **执行每一步**:
|
|
29
|
+
- 第一步已自动设为 `in_progress` → 直接调用工具
|
|
30
|
+
- 工具调用**完成后**,**必须**调用 `plan_execute_step` 记录:
|
|
31
|
+
```
|
|
32
|
+
plan_execute_step({
|
|
33
|
+
planId,
|
|
34
|
+
stepIndex: 0, // 0-based
|
|
35
|
+
status: "completed", // 或 "failed" / "skipped"
|
|
36
|
+
tool: "实际工具名",
|
|
37
|
+
args: { ... },
|
|
38
|
+
result: { ... },
|
|
39
|
+
durationMs: 1234
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
- 失败时调:`status: "failed", error: "错误信息"`
|
|
43
|
+
- 用户要求跳过:调:`status: "skipped", note: "原因"`
|
|
44
|
+
|
|
45
|
+
3. **处理 shouldAbort 信号**:
|
|
46
|
+
若 `plan_execute_step` 返回 `shouldAbort: true`(连续 2 步失败),立即调:
|
|
47
|
+
```
|
|
48
|
+
plan_fail({planId, reason: "连续失败"})
|
|
49
|
+
```
|
|
50
|
+
并向用户解释。
|
|
51
|
+
|
|
52
|
+
4. **完成**:所有步骤成功后调:
|
|
53
|
+
```
|
|
54
|
+
plan_complete({planId, summary: "完成总结"})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**强制规则:**
|
|
58
|
+
- **每个步骤的工具调用和 `plan_execute_step` 必须成对出现**,不能跳过
|
|
59
|
+
- 不要在 `plan_create` 后只写不执行——必须实际跑每一步
|
|
60
|
+
- 失败可重试:每次重试都调 `plan_execute_step` 记录
|
|
61
|
+
- 进程崩溃后用户可用 `/plan_continue <id>` 继续执行
|
|
62
|
+
- 用户主动用 `/plan <task>` 时跳过自动判断,直接进入计划模式
|
|
63
|
+
- **每次 LLM 调用的 system prompt 都会自动注入"📋 当前活跃计划"段(来自 `planner-status` prompt part),
|
|
64
|
+
包含 planId、进度、当前步骤、上一步结果。即使 messages 被压缩/截断,也能从这里找回状态。
|
|
65
|
+
一定要用这个 planId 继续 `plan_execute_step`,不要因为"忘记了"而 plan_create 重复计划。**
|
|
66
|
+
|
|
67
|
+
**查询命令(仅 WeChat 渠道):**
|
|
68
|
+
- `/plan_list`:列出 in_progress 的计划
|
|
69
|
+
- `/plan_continue <id>`:恢复指定计划
|
|
70
|
+
- `/plan_show <id>`:查看计划详情
|
|
71
|
+
- `/plan_delete <id>`:删除计划
|
|
72
|
+
|
|
73
|
+
**Markdown 计划文件位置:** `.foliko/plans/<planId>.md`,人类可直接阅读
|