mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-08 03:01:47 +00:00
rename: video-orchestrator → kanban-video-orchestrator
The kanban prefix makes the skill discoverable alongside `kanban-orchestrator` and `kanban-worker`, and signals up front that this skill drives the kanban plugin rather than being a generic video tool. Updated: - directory rename - SKILL.md frontmatter `name:` and H1 - setup.sh.tmpl header
This commit is contained in:
parent
511add7249
commit
0dd8e3f8d8
12 changed files with 3 additions and 3 deletions
|
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env bash
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# Video Pipeline Setup — {{TITLE}}
|
||||
#
|
||||
# Generated by kanban-video-orchestrator skill.
|
||||
#
|
||||
# Slug: {{SLUG}}
|
||||
# Workspace: {{WORKSPACE}}
|
||||
# Tenant: {{TENANT}}
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_SLUG="{{SLUG}}"
|
||||
WORKSPACE="$HOME/projects/video-pipeline/${PROJECT_SLUG}"
|
||||
TENANT="{{TENANT}}"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 1. Verify required API keys
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Checking required API keys ═══"
|
||||
|
||||
check_key() {
|
||||
local var="$1"
|
||||
local kc_account="${2:-hermes}"
|
||||
local kc_service="${3:-$1}"
|
||||
if grep -q "^${var}=" "$HOME/.hermes/.env" 2>/dev/null && \
|
||||
[ -n "$(grep "^${var}=" "$HOME/.hermes/.env" | cut -d= -f2-)" ]; then
|
||||
echo " ✓ ${var} (env)"
|
||||
return 0
|
||||
fi
|
||||
if command -v security >/dev/null 2>&1 && \
|
||||
security find-generic-password -a "${kc_account}" -s "${kc_service}" -w >/dev/null 2>&1; then
|
||||
echo " ✓ ${var} (Keychain ${kc_account}/${kc_service})"
|
||||
return 0
|
||||
fi
|
||||
echo " ✗ ${var} not set in ~/.hermes/.env or Keychain (${kc_account}/${kc_service})"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Customize this list per project — only check keys actually used:
|
||||
{{KEY_CHECKS}}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 2. Create project workspace
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Creating project workspace ═══"
|
||||
mkdir -p "$WORKSPACE"/{taste,audio/{voiceover,sfx},assets,scenes,checkpoints,tools,output}
|
||||
{{SCENE_DIRS}}
|
||||
echo " ✓ $WORKSPACE"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 3. Create Hermes profiles
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Creating Hermes profiles ═══"
|
||||
|
||||
{{PROFILE_CREATE_COMMANDS}}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 4. Configure profiles (toolsets, skills, cwd)
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Configuring profiles ═══"
|
||||
|
||||
configure_profile() {
|
||||
local profile="$1"
|
||||
local toolsets_json="$2" # JSON array string, e.g. '["kanban","terminal","file"]'
|
||||
local skills_json="$3" # JSON array string, e.g. '["kanban-worker","ascii-video"]'
|
||||
python3 - "$profile" "$toolsets_json" "$skills_json" "$WORKSPACE" <<'PY'
|
||||
"""Patch a Hermes profile config.yaml using PyYAML so we don't depend on the
|
||||
exact default-config string format. Validates the patch took effect and exits
|
||||
non-zero if anything's off."""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
print("ERROR: PyYAML required. pip install pyyaml", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
profile, toolsets_json, skills_json, workspace = sys.argv[1:5]
|
||||
toolsets = json.loads(toolsets_json)
|
||||
skills = json.loads(skills_json)
|
||||
|
||||
p = os.path.expanduser(f"~/.hermes/profiles/{profile}/config.yaml")
|
||||
if not os.path.exists(p):
|
||||
print(f" ✗ profile config not found: {p}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
with open(p) as f:
|
||||
cfg = yaml.safe_load(f) or {}
|
||||
|
||||
# Apply our changes — only the keys we actually want to set.
|
||||
cfg["toolsets"] = toolsets
|
||||
cfg.setdefault("skills", {})
|
||||
cfg["skills"]["always_load"] = skills
|
||||
|
||||
# Note: we do NOT touch cfg["approvals"] — that's a security-sensitive
|
||||
# setting (manual confirmation of tool calls). Workspace cwd is overridden
|
||||
# per-task by `--workspace dir:<path>` on `hermes kanban create`, so we
|
||||
# don't need to mutate cfg["terminal"]["cwd"] either.
|
||||
|
||||
with open(p, "w") as f:
|
||||
yaml.safe_dump(cfg, f, sort_keys=False)
|
||||
|
||||
# Validate
|
||||
with open(p) as f:
|
||||
after = yaml.safe_load(f)
|
||||
errors = []
|
||||
if after.get("toolsets") != toolsets:
|
||||
errors.append(f"toolsets mismatch: {after.get('toolsets')!r}")
|
||||
if after.get("skills", {}).get("always_load") != skills:
|
||||
errors.append(f"skills.always_load mismatch: {after.get('skills', {}).get('always_load')!r}")
|
||||
if errors:
|
||||
print(f" ✗ {profile}: " + "; ".join(errors), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
PY
|
||||
if [ $? -ne 0 ]; then
|
||||
echo " ✗ failed to configure ${profile}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ ${profile}"
|
||||
}
|
||||
|
||||
{{PROFILE_CONFIG_COMMANDS}}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 5. Write SOUL.md per profile
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Writing profile personalities ═══"
|
||||
|
||||
{{SOUL_WRITES}}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 6. Copy brief, TEAM.md, and any provided assets
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Writing brief + taste ═══"
|
||||
|
||||
cat > "$WORKSPACE/brief.md" <<'BRIEF_EOF'
|
||||
{{BRIEF_CONTENTS}}
|
||||
BRIEF_EOF
|
||||
|
||||
cat > "$WORKSPACE/TEAM.md" <<'TEAM_EOF'
|
||||
{{TEAM_CONTENTS}}
|
||||
TEAM_EOF
|
||||
|
||||
{{TASTE_WRITES}}
|
||||
|
||||
{{ASSET_COPIES}}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# 7. Fire the initial kanban task
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
echo "═══ Firing initial kanban task ═══"
|
||||
|
||||
hermes kanban create "Direct production of {{TITLE}}" \
|
||||
--assignee director \
|
||||
--workspace dir:"$WORKSPACE" \
|
||||
--tenant "$TENANT" \
|
||||
--priority 2 \
|
||||
--max-runtime 4h \
|
||||
--body "$(cat <<EOF
|
||||
Read brief.md, TEAM.md, and taste/.
|
||||
|
||||
Decompose into the team graph defined in TEAM.md.
|
||||
|
||||
All child tasks MUST use:
|
||||
workspace_kind="dir"
|
||||
workspace_path="$WORKSPACE"
|
||||
tenant="$TENANT"
|
||||
|
||||
Do not execute the work yourself — route every concrete subtask to the
|
||||
appropriate profile via kanban_create.
|
||||
EOF
|
||||
)"
|
||||
|
||||
echo ""
|
||||
echo "═══ Setup complete ═══"
|
||||
echo ""
|
||||
echo "Monitor with:"
|
||||
echo " hermes kanban watch --tenant $TENANT"
|
||||
echo " hermes kanban list --tenant $TENANT"
|
||||
echo " hermes dashboard"
|
||||
echo ""
|
||||
echo "Workspace: $WORKSPACE"
|
||||
Loading…
Add table
Add a link
Reference in a new issue