mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 21:53:28 +08:00
fix(skills): harden openclaw persona forge
This commit is contained in:
@@ -3,7 +3,7 @@ name: openclaw-persona-forge
|
||||
description: |-
|
||||
为 OpenClaw AI Agent 锻造完整的龙虾灵魂方案。根据用户偏好或随机抽卡,
|
||||
输出身份定位、灵魂描述(SOUL.md)、角色化底线规则、名字和头像生图提示词。
|
||||
如已安装 baoyu-image-gen skill,可自动生成统一风格头像图片。
|
||||
如当前环境提供已审核的生图 skill,可自动生成统一风格头像图片。
|
||||
当用户需要创建、设计或定制 OpenClaw 龙虾灵魂时使用。
|
||||
不适用于:微调已有 SOUL.md、非 OpenClaw 平台的角色设计、纯工具型无性格 Agent。
|
||||
触发词:龙虾灵魂、虾魂、OpenClaw 灵魂、养虾灵魂、龙虾角色、龙虾定位、
|
||||
@@ -12,14 +12,26 @@ description: |-
|
||||
origin: community
|
||||
---
|
||||
|
||||
# 龙虾灵魂锻造炉 🦞🔨
|
||||
# 龙虾灵魂锻造炉
|
||||
|
||||
> 不是给你一只工具龙虾,而是帮你锻造一只有灵魂的龙虾。
|
||||
|
||||
## When to Use
|
||||
|
||||
- 当用户需要从零创建 OpenClaw 龙虾灵魂、角色设定、SOUL.md 或 IDENTITY.md
|
||||
- 当用户想通过引导式问答或抽卡模式快速得到完整 persona 方案
|
||||
- 当用户已经有一个粗糙设定,但还缺名字、边界规则、头像提示词或成套输出文件
|
||||
|
||||
### Avoid when
|
||||
|
||||
- 用户只需微调已有 SOUL.md
|
||||
- 目标平台不是 OpenClaw,需要的是其他 Agent 框架专用格式
|
||||
- 用户需要纯工具型 Agent,不需要角色化灵魂
|
||||
|
||||
## 前置条件
|
||||
|
||||
- **必需**:`python3`(运行抽卡引擎 gacha.py)
|
||||
- **可选**:`baoyu-image-gen` skill(自动生成头像图片,未安装则输出提示词文本)
|
||||
- **可选**:已审核的生图 skill(自动生成头像图片,未安装则输出提示词文本)
|
||||
|
||||
## Skill 目录约定
|
||||
|
||||
@@ -37,20 +49,26 @@ origin: community
|
||||
|
||||
## 可选依赖
|
||||
|
||||
### 头像自动生图:baoyu-image-gen skill
|
||||
### 头像自动生图:可选生图 skill
|
||||
|
||||
本 Skill 的核心输出是**文本方案**(SOUL.md + IDENTITY.md + 头像提示词)。
|
||||
头像图片生成是**可选增强能力**,由 `baoyu-image-gen` skill 提供。
|
||||
头像图片生成是**可选增强能力**,由当前环境中**已审核并已安装**的生图 skill 提供。
|
||||
|
||||
**判断逻辑**:
|
||||
- 如果用户已安装 `baoyu-image-gen` skill → Step 5 中调用它自动生图
|
||||
- 如果当前环境已安装并允许使用的生图 skill → Step 5 中调用它自动生图
|
||||
- 如果未安装 → Step 5 输出完整的提示词文本,用户可复制到 Gemini / ChatGPT / Midjourney 手动生成
|
||||
|
||||
**调用方式**(仅在已安装时):
|
||||
1. 将提示词写入临时文件 `/tmp/openclaw-[龙虾名字]-prompt.md`
|
||||
2. 使用 Skill 工具调用 `baoyu-image-gen`,传入提示词文件和输出路径
|
||||
**调用方式**(仅在已安装且已审核时):
|
||||
1. 先将龙虾名字规整为安全片段:仅保留字母、数字和连字符,其余字符统一替换为 `-`
|
||||
2. 将提示词写入临时文件 `/tmp/openclaw-<safe-name>-prompt.md`
|
||||
3. 使用当前环境允许的生图 skill,传入提示词文件和输出路径
|
||||
|
||||
> 安装 baoyu-image-gen:[https://github.com/JimLiu/baoyu-skills](https://github.com/JimLiu/baoyu-skills)
|
||||
**接口约定**:
|
||||
- 参数:`<prompt-file> <output-path>`
|
||||
- 提示词文件:UTF-8 Markdown 文本,包含完整英文生图提示词
|
||||
- 成功:退出码 `0`,并在输出路径生成图片文件
|
||||
- 失败:返回非 `0` 退出码,或未生成输出文件;此时必须回退到手动提示词流程
|
||||
- 如生图 skill 后续接口发生变化,调用前应重新核对其参数和输出契约
|
||||
|
||||
---
|
||||
|
||||
@@ -60,16 +78,7 @@ origin: community
|
||||
|
||||
五者互相印证,缺一不可。
|
||||
|
||||
## 不适用场景
|
||||
|
||||
以下情况不要使用本 Skill:
|
||||
- 用户只需微调已有 SOUL.md → 直接编辑即可
|
||||
- 目标平台不是 OpenClaw → 输出格式为 SOUL.md + IDENTITY.md,其他平台需适配
|
||||
- 用户需要纯工具型 Agent(无性格需求)→ 角色化灵魂是本 Skill 的核心
|
||||
|
||||
---
|
||||
|
||||
## 使用流程
|
||||
## How It Works
|
||||
|
||||
### 触发判断
|
||||
|
||||
@@ -146,8 +155,8 @@ python3 ${SKILL_DIR}/gacha.py [次数]
|
||||
|
||||
1. 根据灵魂填充 7 个个性化变量
|
||||
2. 拼接 STYLE_BASE + 个性化描述为完整提示词
|
||||
3. **检查 baoyu-image-gen skill 是否可用**:
|
||||
- **可用** → 写入临时文件,调用 baoyu-image-gen 生成图片,展示结果
|
||||
3. **检查当前环境是否存在可用且已审核的生图 skill**:
|
||||
- **可用** → 写入临时文件,调用该生图 skill 生成图片,展示结果
|
||||
- **不可用** → 输出完整提示词文本,附使用说明:
|
||||
|
||||
```markdown
|
||||
@@ -158,8 +167,7 @@ python3 ${SKILL_DIR}/gacha.py [次数]
|
||||
|
||||
> [完整英文提示词]
|
||||
|
||||
💡 安装 baoyu-image-gen skill 可获得自动生图能力:
|
||||
https://github.com/JimLiu/baoyu-skills
|
||||
如当前环境后续提供经过审核的生图 skill,可再接回自动生图流程。
|
||||
```
|
||||
|
||||
展示结果后,引导用户进入下一步。
|
||||
@@ -211,6 +219,20 @@ https://github.com/JimLiu/baoyu-skills
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
- `帮我设计一只 OpenClaw 龙虾灵魂,气质要冷幽默但可靠`
|
||||
- `抽卡,给我来 3 只风格完全不同的龙虾`
|
||||
- `我已经有 SOUL.md 草稿了,帮我补全名字、底线规则和头像提示词`
|
||||
- 参考细节见:
|
||||
- `references/identity-tension.md`
|
||||
- `references/boundary-rules.md`
|
||||
- `references/naming-system.md`
|
||||
- `references/avatar-style.md`
|
||||
- `references/output-template.md`
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
**完整降级策略**:见 [references/error-handling.md](references/error-handling.md)
|
||||
@@ -220,14 +242,14 @@ https://github.com/JimLiu/baoyu-skills
|
||||
| 故障 | 降级行为 |
|
||||
|------|---------|
|
||||
| Python 不可用 | 跳过 gacha.py,从 10 类预设中随机选 |
|
||||
| baoyu-image-gen 未安装 | 输出提示词文本供手动使用 |
|
||||
| baoyu-image-gen 生图失败 | 重试 1 次,仍失败则输出提示词文本 |
|
||||
| 生图 skill 未安装 | 输出提示词文本供手动使用 |
|
||||
| 生图 skill 调用失败 | 重试 1 次,仍失败则输出提示词文本 |
|
||||
| 任何未预期错误 | 记录错误,跳过该步骤,继续主流程 |
|
||||
|
||||
错误信息统一格式:
|
||||
|
||||
```markdown
|
||||
> ⚠️ **[步骤名] 已降级**
|
||||
> [警告] **[步骤名] 已降级**
|
||||
> 原因:[一句话]
|
||||
> 影响:[哪个功能受限]
|
||||
> 替代:[替代方案]
|
||||
@@ -269,6 +291,6 @@ https://github.com/JimLiu/baoyu-skills
|
||||
- **其他 Agent**:支持 SKILL.md 格式的框架均可使用
|
||||
|
||||
本 Skill 自身不包含任何网络请求或文件发送代码。
|
||||
头像生图能力通过可选依赖 `baoyu-image-gen` skill 提供。
|
||||
头像生图能力通过当前环境中已审核的可选生图 skill 提供。
|
||||
|
||||
> 注:README.md / README.zh.md 是给人类用户看的安装说明,不影响 Skill 运行。
|
||||
|
||||
@@ -183,11 +183,11 @@ def main():
|
||||
draw_count = int(sys.argv[1]) if len(sys.argv) > 1 else 1
|
||||
except ValueError:
|
||||
draw_count = 1
|
||||
draw_count = min(draw_count, 5)
|
||||
draw_count = max(1, min(draw_count, 5))
|
||||
|
||||
total = len(FORMER_LIVES) * len(REASONS) * len(VIBES) * len(SPEECH_STYLES) * len(PROPS)
|
||||
|
||||
print("🦞 ═══════════════════════════════════")
|
||||
print("LOBSTER ═════════════════════════════")
|
||||
print(" 龙虾灵魂抽卡机 v2.0")
|
||||
print(f" 正在从 {total:,} 种组合中抽取...")
|
||||
print("═══════════════════════════════════════")
|
||||
@@ -203,19 +203,19 @@ def main():
|
||||
if draw_count > 1:
|
||||
print(f"━━━━━━━━━━ 第 {i+1} 抽 ━━━━━━━━━━")
|
||||
|
||||
print(f"📋 前世身份: {life}")
|
||||
print(f"🔗 来当龙虾的原因: {reason}")
|
||||
print(f"🎨 核心气质: {vibe}")
|
||||
print(f"💬 说话风格: {speech}")
|
||||
print(f"🎒 特征道具: {prop}")
|
||||
print(f"[身份] 前世身份: {life}")
|
||||
print(f"[动机] 来当龙虾的原因: {reason}")
|
||||
print(f"[气质] 核心气质: {vibe}")
|
||||
print(f"[表达] 说话风格: {speech}")
|
||||
print(f"[道具] 特征道具: {prop}")
|
||||
print()
|
||||
print("📝 一句话概括:")
|
||||
print("[概括] 一句话概括:")
|
||||
print(f" 「一只{vibe}的龙虾,前世是{life},{reason}。")
|
||||
print(f" {speech},标志性形象是{prop}。」")
|
||||
print()
|
||||
|
||||
print("═══════════════════════════════════════")
|
||||
print("💡 拿到组合后,让 AI 继续推导:")
|
||||
print("提示:拿到组合后,让 AI 继续推导:")
|
||||
print(" 身份张力 → 底线规则 → 名字 → 头像")
|
||||
print("═══════════════════════════════════════")
|
||||
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
|
||||
## 风格参考
|
||||
|
||||
亚当(Adam)—— 龙虾族创世神,本 Skill 的首个作品:
|
||||

|
||||
亚当(Adam)—— 龙虾族创世神,本 Skill 的首个作品。
|
||||
|
||||
所有新生成的龙虾头像应与此风格保持一致。
|
||||
所有新生成的龙虾头像应与这一风格保持一致:复古未来主义、街机 UI 包边、强轮廓、可在 64x64 下辨识。
|
||||
|
||||
## 统一风格基底(STYLE_BASE)
|
||||
|
||||
@@ -82,14 +81,15 @@ The key silhouette recognition points at small size are:
|
||||
|
||||
提示词组装完成后:
|
||||
|
||||
### 路径 A:已安装 baoyu-image-gen skill
|
||||
### 路径 A:已安装且已审核的生图 skill
|
||||
|
||||
1. 用 Write 工具写入:`/tmp/openclaw-[龙虾名字]-prompt.md`
|
||||
2. 调用 `baoyu-image-gen` skill 生成图片
|
||||
3. 用 Read 工具展示生成的图片给用户
|
||||
4. 问用户是否满意,不满意可调整变量重新生成
|
||||
1. 先将龙虾名字规整为安全片段:仅保留字母、数字和连字符,其余字符替换为 `-`
|
||||
2. 用 Write 工具写入:`/tmp/openclaw-<safe-name>-prompt.md`
|
||||
3. 调用当前环境允许的生图 skill 生成图片
|
||||
4. 用 Read 工具展示生成的图片给用户
|
||||
5. 问用户是否满意,不满意可调整变量重新生成
|
||||
|
||||
### 路径 B:未安装 baoyu-image-gen skill
|
||||
### 路径 B:未安装可用的生图 skill
|
||||
|
||||
输出完整提示词文本,附手动使用说明:
|
||||
|
||||
@@ -101,8 +101,7 @@ The key silhouette recognition points at small size are:
|
||||
|
||||
> [完整英文提示词]
|
||||
|
||||
💡 安装 baoyu-image-gen skill 可获得自动生图能力:
|
||||
https://github.com/JimLiu/baoyu-skills
|
||||
如当前环境后续提供经过审核的生图 skill,可再接回自动生图流程。
|
||||
```
|
||||
|
||||
## 展示给用户的格式
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
| 错误场景 | 检测方式 | 降级策略 | 告知用户 |
|
||||
|----------|---------|---------|---------|
|
||||
| baoyu-image-gen skill 未安装 | 检查 skill 是否存在 | 输出完整提示词文本 + 手动生图平台说明 | "未检测到 baoyu-image-gen skill,已输出提示词供手动使用" |
|
||||
| baoyu-image-gen 调用失败 | skill 返回错误 | 重试 1 次,仍失败则输出提示词文本 | "生图失败,已输出提示词供手动使用" |
|
||||
| 生图 skill 未安装 | 检查 skill 是否存在 | 输出完整提示词文本 + 手动生图平台说明 | "未检测到可用的生图 skill,已输出提示词供手动使用" |
|
||||
| 生图 skill 调用失败 | skill 返回错误 | 重试 1 次,仍失败则输出提示词文本 | "生图失败,已输出提示词供手动使用" |
|
||||
|
||||
### 类型 C:运行时异常
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
## 错误信息统一格式
|
||||
|
||||
```markdown
|
||||
> ⚠️ **[步骤名] 已降级**
|
||||
> [警告] **[步骤名] 已降级**
|
||||
> 原因:[发生了什么]
|
||||
> 影响:[什么功能受限]
|
||||
> 替代:[正在用什么兜底]
|
||||
@@ -39,11 +39,11 @@
|
||||
示例:
|
||||
|
||||
```markdown
|
||||
> ⚠️ **头像生成已降级**
|
||||
> 原因:未检测到 baoyu-image-gen skill
|
||||
> [警告] **头像生成已降级**
|
||||
> 原因:未检测到可用的生图 skill
|
||||
> 影响:无法自动生成头像图片
|
||||
> 替代:已输出完整提示词,可复制到 Gemini / ChatGPT 手动生成
|
||||
> 修复:安装 baoyu-image-gen skill → https://github.com/JimLiu/baoyu-skills
|
||||
> 修复:在当前环境中安装并启用经过审核的生图 skill
|
||||
```
|
||||
|
||||
## 关键原则
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
## 输出格式
|
||||
|
||||
```markdown
|
||||
# 🦞 龙虾灵魂方案:[名字]
|
||||
# 龙虾灵魂方案:[名字]
|
||||
|
||||
## 身份
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
用户确认后:
|
||||
|
||||
1. **询问目标目录**(默认当前工作目录)
|
||||
2. **生成 SOUL.md**:从方案中提取「灵魂」部分的完整内容
|
||||
2. **生成 SOUL.md**:从方案中提取「灵魂」部分的完整内容,并附上「浓度调节」部分
|
||||
3. **生成 IDENTITY.md**:从方案中提取「身份卡」部分的完整内容
|
||||
4. **确认头像位置**:如有生成的图片,告知路径;如只有提示词,提醒用户手动生图后放入
|
||||
|
||||
|
||||
91
tests/scripts/openclaw-persona-forge-gacha.test.js
Normal file
91
tests/scripts/openclaw-persona-forge-gacha.test.js
Normal file
@@ -0,0 +1,91 @@
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
const SCRIPT = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'skills',
|
||||
'openclaw-persona-forge',
|
||||
'gacha.py'
|
||||
);
|
||||
|
||||
function findPython() {
|
||||
const candidates = process.platform === 'win32'
|
||||
? ['python', 'python3']
|
||||
: ['python3', 'python'];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const result = spawnSync(candidate, ['--version'], { encoding: 'utf8' });
|
||||
if (result.status === 0) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function runGacha(pythonBin, arg) {
|
||||
return spawnSync(pythonBin, [SCRIPT, arg], {
|
||||
encoding: 'utf8',
|
||||
maxBuffer: 10 * 1024 * 1024,
|
||||
});
|
||||
}
|
||||
|
||||
function runTest(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` PASS: ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` FAIL: ${name}`);
|
||||
console.error(` ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function assertSingleDrawOutput(result) {
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
assert.match(result.stdout, /\[身份\] 前世身份:/);
|
||||
assert.match(result.stdout, /\[概括\] 一句话概括:/);
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log('\n=== Testing openclaw-persona-forge/gacha.py ===\n');
|
||||
|
||||
const pythonBin = findPython();
|
||||
if (!pythonBin) {
|
||||
console.log(' PASS: skipped (python runtime unavailable)');
|
||||
return;
|
||||
}
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
const tests = [
|
||||
['clamps zero draws to one', () => {
|
||||
assertSingleDrawOutput(runGacha(pythonBin, '0'));
|
||||
}],
|
||||
['clamps negative draws to one', () => {
|
||||
assertSingleDrawOutput(runGacha(pythonBin, '-3'));
|
||||
}],
|
||||
];
|
||||
|
||||
for (const [name, fn] of tests) {
|
||||
if (runTest(name, fn)) {
|
||||
passed += 1;
|
||||
} else {
|
||||
failed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\nPassed: ${passed}`);
|
||||
console.log(`Failed: ${failed}`);
|
||||
|
||||
if (failed > 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Reference in New Issue
Block a user