185 行
6.0 KiB
Bash
可执行文件
185 行
6.0 KiB
Bash
可执行文件
#!/bin/bash
|
||
# 多 AI 协作触发器 v2.0 · 独立任务文件模式
|
||
#
|
||
# 用法:
|
||
# ./collab.sh --kimi tasks/active/task-xxx.md → Kimi 执行指定任务
|
||
# ./collab.sh --mimo tasks/active/task-xxx.md → MiMo 执行指定任务
|
||
# ./collab.sh --both tasks/active/task-xxx.md → Kimi 先/MiMo 补(串行)
|
||
# ./collab.sh --new "任务标题" [--kimi|--mimo] → 新建任务文件(不立即执行)
|
||
# ./collab.sh --list → 列出当前待执行任务
|
||
#
|
||
# 目录结构:
|
||
# context/project-brief.md 项目简报(每次随任务一起发送,≤60行)
|
||
# tasks/active/ 待执行任务(每个文件独立上下文)
|
||
# tasks/done/ 已完成任务(执行后自动归档)
|
||
# BOARD.md 结果日志(只追加,不作为 AI 上下文)
|
||
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
TASKS_ACTIVE="$SCRIPT_DIR/tasks/active"
|
||
TASKS_DONE="$SCRIPT_DIR/tasks/done"
|
||
CONTEXT_FILE="$SCRIPT_DIR/context/project-brief.md"
|
||
BOARD="$SCRIPT_DIR/BOARD.md"
|
||
TIMESTAMP=$(date "+%Y-%m-%d %H:%M")
|
||
|
||
# ── 参数解析 ──────────────────────────────────────────────────────────────────
|
||
|
||
AI_TARGET=""
|
||
TASK_FILE=""
|
||
NEW_TITLE=""
|
||
DO_LIST=false
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
--kimi) AI_TARGET="kimi"; shift ;;
|
||
--mimo) AI_TARGET="mimo"; shift ;;
|
||
--both) AI_TARGET="both"; shift ;;
|
||
--new) NEW_TITLE="$2"; shift 2 ;;
|
||
--list) DO_LIST=true; shift ;;
|
||
*.md) TASK_FILE="$1"; shift ;;
|
||
*) shift ;;
|
||
esac
|
||
done
|
||
|
||
# ── 列出任务 ──────────────────────────────────────────────────────────────────
|
||
|
||
if $DO_LIST; then
|
||
echo "=== 待执行任务 ==="
|
||
ls -1 "$TASKS_ACTIVE"/*.md 2>/dev/null | while read -r f; do
|
||
head -1 "$f" | sed "s/# 任务: / · /"
|
||
echo " 文件: $(basename "$f")"
|
||
done || echo " (无待执行任务)"
|
||
exit 0
|
||
fi
|
||
|
||
# ── 新建任务文件 ──────────────────────────────────────────────────────────────
|
||
|
||
if [ -n "$NEW_TITLE" ]; then
|
||
TASK_ID="task-$(date +%Y%m%d-%H%M%S)"
|
||
TASK_FILE="$TASKS_ACTIVE/${TASK_ID}.md"
|
||
TARGET_HINT="${AI_TARGET:-kimi}"
|
||
cat > "$TASK_FILE" << TASK_TEMPLATE
|
||
# 任务: ${NEW_TITLE}
|
||
> 创建时间: ${TIMESTAMP}
|
||
> 执行者: ${TARGET_HINT}
|
||
> 状态: pending
|
||
|
||
## 任务描述
|
||
|
||
(在此描述需要完成的具体内容)
|
||
|
||
## 预期输出
|
||
|
||
- 格式: Markdown GDD 章节
|
||
- 字数: 约 xxx 字
|
||
- 结构: (列出需要的章节)
|
||
|
||
## 约束
|
||
|
||
- 参考文档: GDD-xx
|
||
- 数值需与 ✅xx 对齐
|
||
- 禁止方向: (不允许的设计思路)
|
||
TASK_TEMPLATE
|
||
|
||
echo "任务文件已创建: $TASK_FILE"
|
||
echo "请编辑后执行: ./collab.sh --${TARGET_HINT} $TASK_FILE"
|
||
exit 0
|
||
fi
|
||
|
||
# ── 执行任务 ──────────────────────────────────────────────────────────────────
|
||
|
||
if [ -z "$TASK_FILE" ] || [ ! -f "$TASK_FILE" ]; then
|
||
echo "错误: 请指定任务文件" >&2
|
||
echo "用法: ./collab.sh [--kimi|--mimo|--both] tasks/active/task-xxx.md" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [ -z "$AI_TARGET" ]; then
|
||
AI_TARGET="kimi"
|
||
fi
|
||
|
||
# 读取项目简报
|
||
BRIEF=""
|
||
if [ -f "$CONTEXT_FILE" ]; then
|
||
BRIEF=$(cat "$CONTEXT_FILE")
|
||
else
|
||
BRIEF="(未找到 context/project-brief.md,请创建)"
|
||
fi
|
||
|
||
TASK_CONTENT=$(cat "$TASK_FILE")
|
||
TASK_NAME=$(basename "$TASK_FILE" .md)
|
||
|
||
# ── AI 调用函数 ───────────────────────────────────────────────────────────────
|
||
|
||
call_ai() {
|
||
local AI_NAME="$1"
|
||
local CLI_CMD="$2"
|
||
local TMPFILE
|
||
TMPFILE=$(mktemp)
|
||
|
||
cat > "$TMPFILE" << PROMPT_EOF
|
||
你是「洪荒大陆」挂机手游设计协作者 ${AI_NAME},与 Claude Sonnet 共同完善 GDD。
|
||
|
||
## 分工
|
||
- Claude Sonnet: 质量把控 / 最终落笔 / 与用户交互
|
||
- ${AI_NAME}: 高效产出设计草稿,可持有独立观点并说明理由
|
||
|
||
## 项目简报(必读,勿忽略)
|
||
|
||
${BRIEF}
|
||
|
||
---
|
||
|
||
## 当前任务(仅执行此任务,忽略其他历史)
|
||
|
||
${TASK_CONTENT}
|
||
|
||
---
|
||
|
||
请直接输出任务要求的内容,以 \`### [${AI_NAME} · ${TIMESTAMP}]\` 开头。
|
||
不要重复任务描述。直接给出设计内容,越完整越好。
|
||
PROMPT_EOF
|
||
|
||
echo "=== [${TIMESTAMP}] 调用 ${AI_NAME} | 任务: ${TASK_NAME} ===" >&2
|
||
|
||
local RESPONSE
|
||
RESPONSE=$(eval "${CLI_CMD}" -p "$(cat "$TMPFILE")" 2>/dev/null)
|
||
rm -f "$TMPFILE"
|
||
|
||
if [ -z "$RESPONSE" ]; then
|
||
echo "[错误] ${AI_NAME} 未返回内容" >&2
|
||
return 1
|
||
fi
|
||
|
||
# 追加到 BOARD(仅作历史日志,不再作为上下文)
|
||
printf '\n---\n## [%s] 任务: %s | 执行者: %s\n\n%s\n' \
|
||
"$TIMESTAMP" "$TASK_NAME" "$AI_NAME" "$RESPONSE" >> "$BOARD"
|
||
|
||
# 将回复追加到任务文件(便于 Claude 后续审查)
|
||
printf '\n---\n\n## %s 输出 (%s)\n\n%s\n' \
|
||
"$AI_NAME" "$TIMESTAMP" "$RESPONSE" >> "$TASK_FILE"
|
||
|
||
echo "=== ${AI_NAME} 完成,回复已写入任务文件 ===" >&2
|
||
echo "--- 前 30 行预览 ---" >&2
|
||
echo "$RESPONSE" | head -30 >&2
|
||
}
|
||
|
||
# ── 执行 ──────────────────────────────────────────────────────────────────────
|
||
|
||
case "$AI_TARGET" in
|
||
kimi) call_ai "Kimi" "~/claude-kimi" ;;
|
||
mimo) call_ai "MiMo" "~/claude-mimo" ;;
|
||
both)
|
||
call_ai "Kimi" "~/claude-kimi"
|
||
echo "" >&2
|
||
echo ">>> MiMo 开始补充..." >&2
|
||
call_ai "MiMo" "~/claude-mimo"
|
||
;;
|
||
esac
|
||
|
||
# 归档任务文件
|
||
ARCHIVE_NAME="${TASK_NAME}-done-$(date +%H%M%S).md"
|
||
mv "$TASK_FILE" "$TASKS_DONE/$ARCHIVE_NAME"
|
||
echo "=== 任务已归档: tasks/done/$ARCHIVE_NAME ===" >&2
|