chore: auto-commit (27 archivos)

- .claude/CLAUDE.md
- .claude/rules/create_agent.md
- agents/_specials/father-bot/prompts/system.md
- agents/_template/config.yaml
- agents/_template_robot/config.yaml
- cmd/agentctl/autoavatar.go
- cmd/launcher/sqlite.go
- dev-scripts/_common.sh
- dev-scripts/agent/create-full.sh
- dev-scripts/agent/delete-full.sh
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 19:38:16 +02:00
parent 072e00f305
commit fc86edd94c
27 changed files with 2199 additions and 111 deletions
+2 -1
View File
@@ -57,7 +57,8 @@ config_path_for() {
for cfg in agents/*/config.yaml agents/_specials/*/config.yaml; do
[[ -f "$cfg" ]] || continue
local id
id=$(grep -m1 '^ id:' "$cfg" | awk '{print $2}')
# Strip quotes from value: handles both `id: foo` and `id: "foo"`
id=$(grep -m1 '^ id:' "$cfg" | sed -E 's/^[^:]*:[[:space:]]*//; s/^"//; s/"$//; s/^'\''//; s/'\''$//')
if [[ "$id" == "$target_id" ]]; then
echo "$cfg"
return
+44 -9
View File
@@ -29,7 +29,8 @@
#
# Flags de personalización (opcionales, activan el Paso 8 automático):
# --description "<texto>" descripcion del agente
# --provider <openai|anthropic|...> proveedor LLM (default: auto-detect)
# --provider <claude-code|openai|anthropic> proveedor LLM (default: claude-code)
# REGLA PROYECTO: usar claude-code SIEMPRE salvo razon explicita
# --model <modelo> modelo LLM (default: segun provider)
# --tone <friendly|professional|...> tono (default: friendly)
# --prefix "<emoji>" emoji prefix (default: 🤖)
@@ -37,6 +38,8 @@
# --system-prompt-file <path> system prompt desde archivo
# --tool-use habilitar tool_use en config
# --language <es|en> idioma (default: es)
# --avatar <URL_o_ruta> imagen para el avatar (default: generador random)
# ej: https://example/pikachu.png o ./avatars/poke.png
#
# Requisitos en .env:
# MATRIX_ADMIN_TOKEN, MATRIX_HOMESERVER, MATRIX_SERVER_NAME
@@ -88,10 +91,15 @@ while [[ $# -gt 0 ]]; do
--tool-use) PERSONALIZE_TOOL_USE=true; DO_PERSONALIZE=true; shift ;;
--language) PERSONALIZE_LANGUAGE="${2:-es}"; DO_PERSONALIZE=true; shift 2 ;;
--language=*) PERSONALIZE_LANGUAGE="${1#--language=}"; DO_PERSONALIZE=true; shift ;;
--avatar) AVATAR_SOURCE="${2:-}"; shift 2 ;;
--avatar=*) AVATAR_SOURCE="${1#--avatar=}"; shift ;;
*) shift ;;
esac
done
# AVATAR_SOURCE puede ser URL (http/https) o ruta local. Vacio = generador random.
: "${AVATAR_SOURCE:=}"
if [[ "$TYPE" == "robot" ]]; then
TYPE_LABEL="robot"
TYPE_EMOJI="🤖"
@@ -165,22 +173,34 @@ if [[ "$TYPE" == "robot" ]]; then
echo ""
fi
# ── Paso auto-avatar: Generar avatar automatico ─────────────────────────
# ── Paso auto-avatar: Generar/aplicar avatar ────────────────────────────
AVATAR_STEP=$((TOTAL_STEPS - 2))
info "Paso ${AVATAR_STEP}/${TOTAL_STEPS}Generando avatar automatico..."
info "Paso ${AVATAR_STEP}/${TOTAL_STEPS}Configurando avatar del bot..."
echo ""
# Resuelve el binario de agentctl
# Resuelve el binario de agentctl como array (preserva split por espacios)
if [[ -f "$REPO_ROOT/bin/agentctl" ]]; then
CTL="$REPO_ROOT/bin/agentctl"
CTL_ARR=("$REPO_ROOT/bin/agentctl")
else
CTL="$GO run -tags goolm ./cmd/agentctl"
CTL_ARR=("$GO" run -tags goolm ./cmd/agentctl)
fi
if $CTL auto-avatar "$ID" 2>&1; then
ok "Avatar generado y aplicado"
# Si el usuario pasa --avatar, usa la URL/ruta indicada en vez del generador random.
AVATAR_CMD=("${CTL_ARR[@]}" auto-avatar "$ID")
if [[ -n "$AVATAR_SOURCE" ]]; then
if [[ "$AVATAR_SOURCE" =~ ^https?:// ]]; then
AVATAR_CMD+=(--from-url "$AVATAR_SOURCE")
info "Usando avatar personalizado desde URL: $AVATAR_SOURCE"
else
AVATAR_CMD+=(--from-file "$AVATAR_SOURCE")
info "Usando avatar personalizado desde archivo: $AVATAR_SOURCE"
fi
fi
if "${AVATAR_CMD[@]}" 2>&1; then
ok "Avatar configurado y aplicado"
else
warn "No se pudo generar avatar automatico (se puede hacer despues con: agentctl auto-avatar $ID)"
warn "No se pudo configurar avatar (se puede hacer despues con: agentctl auto-avatar $ID [--from-url <url> | --from-file <path>])"
fi
echo ""
@@ -213,6 +233,21 @@ fi
echo ""
# ── Paso 8a (robots): aplicar --description al config.yaml ──────────────
# Los robots no tienen prompts/system.md ni agent.go (no LLM), pero su
# config.yaml SI tiene un campo `description:` que personalize.sh ignora.
# Para evitar que el robot quede con la descripcion del template literal,
# parcheamos la linea aqui.
if [[ "$TYPE" == "robot" ]] && [[ -n "$PERSONALIZE_DESCRIPTION" ]]; then
CFG_FILE="agents/$ID/config.yaml"
if [[ -f "$CFG_FILE" ]]; then
# Escapar caracteres especiales del valor para sed
ESCAPED_DESC="$(printf '%s' "$PERSONALIZE_DESCRIPTION" | sed -e 's/[\/&|]/\\&/g')"
sed -i "0,/^ description:.*/s|| description: \"$ESCAPED_DESC\"|" "$CFG_FILE"
ok "Descripcion del robot aplicada al config.yaml"
fi
fi
# ── Paso 8 (automático, solo agents): Personalizar archivos ─────────────
PERSONALIZE_DONE=false
if $DO_PERSONALIZE && [[ "$TYPE" != "robot" ]]; then
+6 -4
View File
@@ -78,14 +78,16 @@ fi
AGENT_DESC=""
AGENT_TYPE="agent"
if [[ -f "$CFG_PATH" ]]; then
AGENT_DESC=$(grep -m1 'description:' "$CFG_PATH" | cut -d'"' -f2)
TYPE_LINE=$(grep -m1 'type:' "$CFG_PATH" | awk '{print $2}')
[[ -n "$TYPE_LINE" ]] && AGENT_TYPE="$TYPE_LINE"
AGENT_DESC=$(grep -m1 'description:' "$CFG_PATH" | cut -d'"' -f2 || true)
TYPE_LINE=$(grep -m1 'type:' "$CFG_PATH" | awk '{print $2}' || true)
if [[ -n "${TYPE_LINE:-}" ]]; then
AGENT_TYPE="$TYPE_LINE"
fi
fi
ok "Agente $ID encontrado en $AGENT_DIR/"
dim " Tipo: $AGENT_TYPE"
[[ -n "$AGENT_DESC" ]] && dim " Descripcion: $AGENT_DESC"
if [[ -n "$AGENT_DESC" ]]; then dim " Descripcion: $AGENT_DESC"; fi
echo ""
# ── Confirmacion interactiva ────────────────────────────────────────────────
+21 -11
View File
@@ -2,37 +2,47 @@
# detect-provider.sh — detecta el proveedor LLM disponible desde .env
#
# Salida: dos palabras en stdout — "<provider> <model>"
# openai gpt-4o
# anthropic claude-sonnet-4-20250514
# claude-code sonnet (DEFAULT)
# openai gpt-4o
# anthropic claude-sonnet-4-20250514
#
# Orden de detección:
# 1. OPENAI_API_KEY → openai gpt-4o
# 2. ANTHROPIC_API_KEY → anthropic claude-sonnet-4-20250514
# Fallback: openai gpt-4o (con warning en stderr)
# Orden de detección (claude-code primero — REGLA DEL PROYECTO):
# 1. CLAUDE binary disponible en PATH → claude-code sonnet
# 2. OPENAI_API_KEY → openai gpt-4o
# 3. ANTHROPIC_API_KEY → anthropic claude-sonnet-4-20250514
# Fallback: claude-code sonnet (binary `claude` debe estar instalado)
#
# Uso:
# read -r PROVIDER MODEL < <(./dev-scripts/agent/detect-provider.sh)
# ./dev-scripts/agent/detect-provider.sh # imprime "openai gpt-4o"
# ./dev-scripts/agent/detect-provider.sh # imprime "claude-code sonnet"
source "$(dirname "$0")/../_common.sh"
load_env
# Default models por provider
CLAUDE_CODE_DEFAULT_MODEL="sonnet"
OPENAI_DEFAULT_MODEL="gpt-4o"
ANTHROPIC_DEFAULT_MODEL="claude-sonnet-4-20250514"
# Detectar provider disponible
# 1. claude-code (preferido) — solo requiere el binario `claude` en PATH
if command -v claude >/dev/null 2>&1; then
echo "claude-code $CLAUDE_CODE_DEFAULT_MODEL"
exit 0
fi
# 2. OpenAI API key
if [[ -n "${OPENAI_API_KEY:-}" ]]; then
echo "openai $OPENAI_DEFAULT_MODEL"
exit 0
fi
# 3. Anthropic API key
if [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
echo "anthropic $ANTHROPIC_DEFAULT_MODEL"
exit 0
fi
# Fallback con warning
warn "Ninguna API key configurada (OPENAI_API_KEY, ANTHROPIC_API_KEY) — usando fallback openai/gpt-4o" >&2
echo "openai $OPENAI_DEFAULT_MODEL"
# Fallback: claude-code (warning porque el binario falta)
warn "Ningun proveedor disponible (binary 'claude' missing, OPENAI_API_KEY/ANTHROPIC_API_KEY missing) — usando fallback claude-code/sonnet (instala claude CLI)" >&2
echo "claude-code $CLAUDE_CODE_DEFAULT_MODEL"
exit 0
+4
View File
@@ -42,6 +42,10 @@ sed -i "s/template: true/template: false/g" "$DIR/config.yaml"
sed -i "s/enabled: true/enabled: true/g" "$DIR/config.yaml"
sed -i "s/MATRIX_TOKEN_TEMPLATE/MATRIX_TOKEN_${NORM}/g" "$DIR/config.yaml"
sed -i "s/PICKLE_KEY_TEMPLATE/PICKLE_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/SSSS_RECOVERY_KEY_TEMPLATE/SSSS_RECOVERY_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/SSSS_RECOVERY_KEY_ROBOT/SSSS_RECOVERY_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/MATRIX_TOKEN_ROBOT/MATRIX_TOKEN_${NORM}/g" "$DIR/config.yaml"
sed -i "s/PICKLE_KEY_ROBOT/PICKLE_KEY_${NORM}/g" "$DIR/config.yaml"
sed -i "s/@template:matrix.example.com/@$ID:\${MATRIX_SERVER_NAME}/g" "$DIR/config.yaml"
sed -i "s|https://matrix.example.com|\${MATRIX_HOMESERVER}|g" "$DIR/config.yaml"
+9 -1
View File
@@ -186,7 +186,15 @@ for dev in "${DEVS[@]}"; do
dev="$(echo "$dev" | xargs)" # trim spaces
[[ -z "$dev" ]] && continue
USER_ID="@${dev}:${MATRIX_SERVER_NAME}"
# Acepta ambos formatos:
# - "egutierrez" (bare username)
# - "@egutierrez:matrix-...organic-machine.com" (full MXID)
if [[ "$dev" == @*:* ]]; then
USER_ID="$dev"
else
USER_ID="@${dev}:${MATRIX_SERVER_NAME}"
fi
info "Enviando DM de $ID a $USER_ID..."
send_dm "$USER_ID"