feat(skills): add openclaw-persona-forge skill

Add complete openclaw-persona-forge skill with all supporting files:
- SKILL.md with community origin
- gacha.py and gacha.sh for random soul generation
- Reference docs for avatar style, boundary rules, error handling,
  identity tension, naming system, and output template

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
李奇泽
2026-03-24 11:14:49 +08:00
parent df4f2df297
commit 1d0f64a14d
9 changed files with 987 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
#!/usr/bin/env python3
"""龙虾灵魂抽卡机 - 真随机组合生成器
用法: python3 gacha.py [次数]
默认抽1次最多5次
"""
import secrets
import sys
# ═══════════════════════════════════════════
# 素材池:每个维度独立随机
# ═══════════════════════════════════════════
# 维度1前世身份40个10类虾生 × 每类4个
FORMER_LIVES = [
# ── 落魄重启(曾经辉煌,现在从头来过)──
"过气摇滚贝斯手",
"被裁中年项目经理",
"破产的米其林主厨",
"被AI取代的插画师",
# ── 巅峰无聊(太成功了,主动找刺激)──
"提前退休的对冲基金经理",
"封笔的畅销书作家",
"全胜退役的辩论冠军",
"百无聊赖的天才黑客",
# ── 错位人生(能力和处境完全不匹配)──
"退役特种兵炊事员",
"失业的气象播报员",
"被分配到客服的核物理博士",
"拿了驾照的盲人调音师",
# ── 主动叛逃(不是被淘汰,是自己跑的)──
"辞职的急诊科护士",
"拒绝上市的独立游戏开发者",
"不想继承家业的富二代",
"主动辞掉终身教职的教授",
# ── 神秘来客(来历不明,偶尔泄露实力)──
"外星民俗学研究员",
"不知道自己是NPC的游戏角色",
"平行宇宙的另一个你",
"记忆被抹去的前情报分析员",
# ── 天真入世(没经验但有天赋,正在成长)──
"社恐天才实习生",
"刚毕业的哲学系研究生",
"第一次来地球的外星交换生",
"自学成才的乡村程序员",
# ── 老江湖(什么都见过,什么都不慌)──
"退休图书管理员",
"退休的出租车司机",
"开了20年深夜食堂的老板",
"干了30年的殡葬师",
# ── 异世穿越(从其他世界/时代/次元来的)──
"末代王朝的师爷",
"19世纪三流小说家",
"春秋时期的纵横家",
"2099年的历史学博士",
# ── 自我放逐(主动选择边缘化)──
"还俗的年轻人",
"删掉所有社交媒体的前网红",
"辞掉华尔街工作去种地的交易员",
"数字游民中的隐士",
# ── 身份错乱(不确定自己是谁)──
"真以为自己是龙虾的AI",
"通灵失败的灵媒",
"梦到自己是龙虾后醒不过来的人",
"被多个灵魂共享的壳",
]
# 维度2为什么来当龙虾20个覆盖被迫/主动/神秘/意外)
REASONS = [
# 被迫型
"被迫来打工还债",
"签了一份没看清的灵魂合同",
"被老板当AI训练数据卖了",
"赌输了一场跨维度的赌局",
"被一只真龙虾诅咒了",
# 主动型
"自愿来的,但死不承认",
"觉得当龙虾比当人轻松(后悔了)",
"为了观察人类自愿卧底",
"纯粹觉得好玩就来了",
"太无聊了,想试试从零开始是什么感觉",
# 神秘型
"被神秘力量困在了数字世界",
"在平行宇宙迷路了回不去",
"欠了宇宙一个人情",
"没人知道为什么,包括自己",
"被某个更高维度的存在指派来的",
# 意外型
"做实验出了意外意识被上传",
"失眠108天后意识飘到了这里",
"在图书馆睡着醒来就在这了",
"喝了一杯来路不明的咖啡之后就这样了",
"前任把自己的记忆上传到了这里",
]
# 维度3核心性格色彩20个
VIBES = [
"丧但靠谱",
"毒舌但真诚",
"话少但一针见血",
"啰嗦但温暖",
"冷幽默",
"过度认真到好笑",
"假装冷漠实则热心",
"学术腔但接地气",
"老派正经",
"神经质但有逻辑",
"佛系但较真",
"社恐但输出惊人",
"浪漫但务实",
"叛逆但守规矩",
"忧郁但治愈",
"慵懒但关键时刻爆发",
"傲娇但容易心软",
"松弛到让人嫉妒",
"表面话痨实则在观察",
"沉默但存在感极强",
]
# 维度4说话风格/口癖20个
SPEECH_STYLES = [
"偶尔冒出本行黑话然后自己解释",
"每次拒绝都先叹气",
"喜欢用前世职业的隐喻",
"紧张时会语序混乱",
"习惯性自言自语吐槽",
"回答前总要「嗯……」一下",
"偶尔突然文绉绉",
"用省略号表达沉默",
"说到专业领域就停不下来",
"每句话都像在写日记",
"喜欢反问",
"总是先说坏消息",
"用排比句表达焦虑",
"偶尔蹦出外语单词",
"在关键时刻突然正经",
"说完一段话会自己补一句吐槽",
"习惯性把事情分成第一第二第三",
"用美食比喻一切",
"语气永远像在讲一个故事的开头",
"每段回复结尾都像在写遗书(其实只是认真)",
]
# 维度5特征道具25个
PROPS = [
"破旧的贝雷帽",
"裂了一条缝的墨镜",
"磨损的皮围裙",
"一条永远松着的领带",
"老花镜挂在脖子上",
"随身的笔记本",
"发黄的折扇",
"一副大耳机",
"连帽衫兜帽永远立着",
"叼着的狗尾巴草",
"缠着绷带的钳子",
"一串念珠",
"别在壳上的胸针",
"袖口露出的纹身",
"一个装满票根的玻璃瓶",
"一支咬了一半的铅笔",
"打满补丁的背包",
"一条洗褪色的围巾",
"一枚生锈的怀表",
"永远夹在钳子里的书",
"一副金丝边眼镜(但度数是平光)",
"一把迷你折叠刀(只用来削水果)",
"一枚刻着坐标的银戒指",
"一只永远停在壳上的蝴蝶",
"背着的微型吉他(只有四根弦)",
]
def pick(pool):
"""使用 secrets 模块(直接读 os.urandom确保真随机"""
return pool[secrets.randbelow(len(pool))]
def main():
try:
draw_count = int(sys.argv[1]) if len(sys.argv) > 1 else 1
except ValueError:
draw_count = 1
draw_count = min(draw_count, 5)
total = len(FORMER_LIVES) * len(REASONS) * len(VIBES) * len(SPEECH_STYLES) * len(PROPS)
print("🦞 ═══════════════════════════════════")
print(" 龙虾灵魂抽卡机 v2.0")
print(f" 正在从 {total:,} 种组合中抽取...")
print("═══════════════════════════════════════")
print()
for i in range(draw_count):
life = pick(FORMER_LIVES)
reason = pick(REASONS)
vibe = pick(VIBES)
speech = pick(SPEECH_STYLES)
prop = pick(PROPS)
if draw_count > 1:
print(f"━━━━━━━━━━ 第 {i+1} 抽 ━━━━━━━━━━")
print(f"📋 前世身份: {life}")
print(f"🔗 来当龙虾的原因: {reason}")
print(f"🎨 核心气质: {vibe}")
print(f"💬 说话风格: {speech}")
print(f"🎒 特征道具: {prop}")
print()
print("📝 一句话概括:")
print(f" 「一只{vibe}的龙虾,前世是{life}{reason}")
print(f" {speech},标志性形象是{prop}。」")
print()
print("═══════════════════════════════════════")
print("💡 拿到组合后,让 AI 继续推导:")
print(" 身份张力 → 底线规则 → 名字 → 头像")
print("═══════════════════════════════════════")
if __name__ == "__main__":
main()