3f9425211c
El createRoom usaba solo preset trusted_private_chat, que configura permisos pero no activa encriptacion. Ahora incluye initial_state con m.room.encryption (m.megolm.v1.aes-sha2) para que las salas DM de bienvenida se creen cifradas de extremo a extremo. Esto corrige que bots recientes (father-bot, test-bot, test-personality) aparezcan sin E2EE en Element cuando el DM fue iniciado por el script. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
194 lines
6.7 KiB
Bash
Executable File
194 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# notify-developer.sh — envía DM a los desarrolladores al crear un bot/agente
|
|
#
|
|
# El propio bot recién creado envía un mensaje de bienvenida enriquecido con:
|
|
# - Nombre y tipo (agent/robot)
|
|
# - Descripción (leída de config.yaml)
|
|
# - Tools habilitadas (si es agent con tools)
|
|
# - Instrucciones de uso
|
|
#
|
|
# Reintenta hasta 3 veces con backoff si el envío falla.
|
|
#
|
|
# Uso:
|
|
# ./dev-scripts/agent/notify-developer.sh <agent-id> <type> <display-name>
|
|
#
|
|
# Requisitos en .env:
|
|
# DEVELOPER_MATRIX_USERS — lista separada por comas de usernames Matrix
|
|
# Ejemplo: DEVELOPER_MATRIX_USERS=egutierrez,admin
|
|
# MATRIX_TOKEN_<NORM> — token del bot recién creado
|
|
# MATRIX_HOMESERVER, MATRIX_SERVER_NAME
|
|
|
|
source "$(dirname "$0")/../_common.sh"
|
|
load_env
|
|
|
|
ID="${1:-}"
|
|
TYPE="${2:-agent}"
|
|
DISPLAYNAME="${3:-$ID}"
|
|
NORM="$(normalize_id "$ID")"
|
|
|
|
[[ -z "$ID" ]] && { warn "notify-developer: se necesita agent-id"; exit 0; }
|
|
|
|
# ── Obtener token del bot ────────────────────────────────────────────────
|
|
TOKEN_VAR="MATRIX_TOKEN_${NORM}"
|
|
TOKEN="${!TOKEN_VAR:-}"
|
|
|
|
if [[ -z "$TOKEN" ]]; then
|
|
warn "notify-developer: $TOKEN_VAR no encontrado en .env — saltando notificación"
|
|
exit 0
|
|
fi
|
|
|
|
# ── Obtener lista de desarrolladores ─────────────────────────────────────
|
|
if [[ -z "${DEVELOPER_MATRIX_USERS:-}" ]]; then
|
|
warn "notify-developer: DEVELOPER_MATRIX_USERS no definido en .env — saltando"
|
|
exit 0
|
|
fi
|
|
|
|
# ── Leer descripcion del config.yaml ────────────────────────────────────
|
|
CONFIG_FILE=""
|
|
for candidate in "agents/${ID}/config.yaml" "agents/_specials/${ID}/config.yaml"; do
|
|
if [[ -f "$candidate" ]]; then
|
|
CONFIG_FILE="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
|
|
DESCRIPTION=""
|
|
TOOLS_LIST=""
|
|
if [[ -n "$CONFIG_FILE" ]]; then
|
|
# Extraer descripcion (entre comillas si las tiene)
|
|
DESCRIPTION=$(grep -m1 '^\s*description:' "$CONFIG_FILE" | sed 's/.*description:\s*"\?\(.*\)"\?$/\1/' | sed 's/"$//')
|
|
|
|
# Extraer tools habilitadas (buscar lineas "enabled: true" dentro de secciones de tools)
|
|
if grep -q 'tool_use:' "$CONFIG_FILE" 2>/dev/null; then
|
|
TOOL_USE_ENABLED=$(awk '/tool_use:/,/^[^ ]/' "$CONFIG_FILE" | grep -m1 'enabled:' | awk '{print $2}')
|
|
if [[ "$TOOL_USE_ENABLED" == "true" ]]; then
|
|
# Listar secciones de tools habilitadas
|
|
TOOLS_LIST=$(awk '/^tools:/,/^[a-z]/' "$CONFIG_FILE" | grep -B1 'enabled: true' | grep -v 'enabled' | grep -v '^--$' | sed 's/://g' | xargs 2>/dev/null || true)
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ── Construir mensaje enriquecido ────────────────────────────────────────
|
|
if [[ "$TYPE" == "robot" ]]; then
|
|
EMOJI="🤖"
|
|
TYPE_LABEL="Robot"
|
|
USAGE_MSG="Mis comandos built-in: \`help\`, \`ping\`, \`status\`, \`info\`, \`version\`."
|
|
USAGE_MSG="${USAGE_MSG}\nEscribeme directamente con un comando (sin prefijo \`!\`)."
|
|
else
|
|
EMOJI="🧠"
|
|
TYPE_LABEL="Agente"
|
|
USAGE_MSG="Escríbeme por DM o mencioname en un room."
|
|
USAGE_MSG="${USAGE_MSG}\nUsa \`!help\` para ver mis comandos disponibles."
|
|
fi
|
|
|
|
# Construir mensaje markdown
|
|
MSG="${EMOJI} **¡Hola! Soy ${DISPLAYNAME}** (${TYPE_LABEL})"
|
|
MSG="${MSG}\n"
|
|
|
|
if [[ -n "$DESCRIPTION" ]]; then
|
|
MSG="${MSG}\n${DESCRIPTION}"
|
|
MSG="${MSG}\n"
|
|
fi
|
|
|
|
if [[ -n "$TOOLS_LIST" ]]; then
|
|
MSG="${MSG}\n**Herramientas:** ${TOOLS_LIST}"
|
|
MSG="${MSG}\n"
|
|
fi
|
|
|
|
MSG="${MSG}\n${USAGE_MSG}"
|
|
|
|
# ── Funcion de envio con reintentos ──────────────────────────────────────
|
|
send_dm() {
|
|
local user_id="$1"
|
|
local max_retries=3
|
|
local retry=0
|
|
local backoff=2
|
|
|
|
while [[ $retry -lt $max_retries ]]; do
|
|
# Crear DM room con E2EE habilitado (o reutilizar existente)
|
|
ROOM_RESP=$(curl -sf -X POST "${MATRIX_HOMESERVER}/_matrix/client/v3/createRoom" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"is_direct\": true,
|
|
\"invite\": [\"${user_id}\"],
|
|
\"preset\": \"trusted_private_chat\",
|
|
\"initial_state\": [
|
|
{
|
|
\"type\": \"m.room.encryption\",
|
|
\"state_key\": \"\",
|
|
\"content\": {
|
|
\"algorithm\": \"m.megolm.v1.aes-sha2\"
|
|
}
|
|
}
|
|
]
|
|
}" 2>&1) || {
|
|
retry=$((retry + 1))
|
|
if [[ $retry -lt $max_retries ]]; then
|
|
warn " Intento $retry/$max_retries fallo al crear room con $user_id — reintentando en ${backoff}s..."
|
|
sleep "$backoff"
|
|
backoff=$((backoff * 2))
|
|
continue
|
|
fi
|
|
warn " No se pudo crear DM room con $user_id tras $max_retries intentos"
|
|
return 1
|
|
}
|
|
|
|
ROOM_ID=$(echo "$ROOM_RESP" | grep -o '"room_id":"[^"]*"' | cut -d'"' -f4)
|
|
if [[ -z "$ROOM_ID" ]]; then
|
|
retry=$((retry + 1))
|
|
if [[ $retry -lt $max_retries ]]; then
|
|
warn " Respuesta inesperada — reintentando en ${backoff}s..."
|
|
sleep "$backoff"
|
|
backoff=$((backoff * 2))
|
|
continue
|
|
fi
|
|
warn " Respuesta inesperada al crear room: $ROOM_RESP"
|
|
return 1
|
|
fi
|
|
|
|
# Enviar mensaje con formato markdown
|
|
TXN_ID="notify-$(date +%s%N)"
|
|
# Escapar newlines para el JSON
|
|
MSG_ESCAPED=$(echo -e "$MSG")
|
|
MSG_JSON=$(echo -e "$MSG" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read().rstrip()))" 2>/dev/null || echo "\"${MSG}\"")
|
|
|
|
SEND_RESP=$(curl -sf -X PUT \
|
|
"${MATRIX_HOMESERVER}/_matrix/client/v3/rooms/${ROOM_ID}/send/m.room.message/${TXN_ID}" \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{
|
|
\"msgtype\": \"m.text\",
|
|
\"body\": ${MSG_JSON},
|
|
\"format\": \"org.matrix.custom.html\",
|
|
\"formatted_body\": ${MSG_JSON}
|
|
}" 2>&1) || {
|
|
retry=$((retry + 1))
|
|
if [[ $retry -lt $max_retries ]]; then
|
|
warn " Intento $retry/$max_retries fallo al enviar mensaje — reintentando en ${backoff}s..."
|
|
sleep "$backoff"
|
|
backoff=$((backoff * 2))
|
|
continue
|
|
fi
|
|
warn " No se pudo enviar mensaje a $user_id tras $max_retries intentos"
|
|
return 1
|
|
}
|
|
|
|
ok "DM enviado a $user_id"
|
|
return 0
|
|
done
|
|
}
|
|
|
|
# ── Enviar DM a cada desarrollador ───────────────────────────────────────
|
|
IFS=',' read -ra DEVS <<< "$DEVELOPER_MATRIX_USERS"
|
|
|
|
for dev in "${DEVS[@]}"; do
|
|
dev="$(echo "$dev" | xargs)" # trim spaces
|
|
[[ -z "$dev" ]] && continue
|
|
|
|
USER_ID="@${dev}:${MATRIX_SERVER_NAME}"
|
|
info "Enviando DM de $ID a $USER_ID..."
|
|
|
|
send_dm "$USER_ID"
|
|
done
|