boosterarena-mcp 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LEEME.md CHANGED
@@ -20,7 +20,7 @@ Hace falta **Node 20 o más nuevo**.
20
20
  npx boosterarena-mcp entrar
21
21
  ```
22
22
 
23
- Te pregunta cómo entras: Enter para Google, o tu correo si tu cuenta es de correo y contraseña (te llega un enlace). También directo:
23
+ Te pregunta cómo entras: Enter para Google, o tu correo si tu cuenta es de correo y contraseña (te llega un enlace). Si lo corre un agente (sin terminal), **tiene que pasar el correo**: sin `--correo` se detiene y nunca abre Google. Directo:
24
24
  `npx boosterarena-mcp entrar --correo tu@correo.com`.
25
25
 
26
26
  La credencial se guarda en `~/.booster/credenciales.json`, solo en tu equipo. Para comprobar a
@@ -57,7 +57,7 @@ borrador y tú decides cuándo se publica.
57
57
 
58
58
  **Contenido** — poner texto, imágenes, figuras y dibujos de la biblioteca (más de 3.000
59
59
  ilustraciones y 280 fondos, que se buscan por nombre en español o inglés), y animaciones Lottie
60
- (`poner_lottie`: de la galería de Booster o por URL). El fondo puede ser una imagen tuya
60
+ (`poner_lottie`: de la galería de Booster o por URL) y videos de YouTube, Vimeo, Drive o Loom (`poner_video`, con el enlace normal). El fondo puede ser una imagen tuya
61
61
  (`poner_fondo` con `url`), y cada capa puede llevar el suyo (`capa` en `poner_fondo`, o `fondo`
62
62
  en `nueva_capa`).
63
63
 
package/cli.mjs CHANGED
@@ -25,7 +25,7 @@ function ayuda() {
25
25
  console.log(`
26
26
  El MCP de Booster — tu agente trabajando dentro de boosterarena.com
27
27
 
28
- boosterarena-mcp entrar te pregunta si entras con Google o con correo
28
+ boosterarena-mcp entrar te pregunta si entras con Google o con correo (sin terminal: exige --correo)
29
29
  boosterarena-mcp entrar --correo tu@correo entrar con un enlace por correo
30
30
  boosterarena-mcp quien a nombre de quién estoy
31
31
  boosterarena-mcp salir borrar la credencial de este equipo
package/dist/nucleo.mjs CHANGED
@@ -1738,6 +1738,18 @@ function conLoDelMcp(lista2, fn) {
1738
1738
  url: str("En vez de `busca`: la URL https:// de un Lottie .json (lottie.host, o uno subido).")
1739
1739
  }, ["ref", "x", "y", "w"])
1740
1740
  ));
1741
+ lista2.splice(i + 2, 0, fn(
1742
+ "poner_video",
1743
+ "Pone un VIDEO embebido en el slide: el enlace normal de YouTube (watch, youtu.be, shorts), Vimeo, Google Drive, Loom o Dailymotion, o un .mp4 subido. Se convierte solo al formato embebido y entra en 16:9. El maestro le da play en el \u25B6 Player. No lo cambies por un QR ni un bot\xF3n.",
1744
+ obj({
1745
+ ref: REF,
1746
+ x: X,
1747
+ y: Y,
1748
+ w: W,
1749
+ capa: CAPA,
1750
+ url: str("El enlace del video tal como lo copias del navegador (https://www.youtube.com/watch?v=\u2026), o el c\xF3digo <iframe> del sitio.")
1751
+ }, ["ref", "x", "y", "w", "url"])
1752
+ ));
1741
1753
  return lista2;
1742
1754
  }
1743
1755
 
@@ -1821,6 +1833,31 @@ function abreEnBucle(slide, desde, t) {
1821
1833
  return false;
1822
1834
  }
1823
1835
 
1836
+ // ../src/canvas/videoSrc.ts
1837
+ function parseVideoInput(code) {
1838
+ const t = code.trim();
1839
+ const fromIframe = t.match(/<iframe[^>]*\ssrc=["']([^"']+)["']/i)?.[1];
1840
+ const raw = fromIframe ?? (/^https?:\/\//i.test(t) ? t : null);
1841
+ if (!raw) return null;
1842
+ let m = raw.match(/(?:youtube(?:-nocookie)?\.com\/(?:watch\?[^#]*?v=|shorts\/|live\/|embed\/)|youtu\.be\/)([\w-]{6,})/i);
1843
+ if (m) {
1844
+ const start = raw.match(/[?&](?:t|start)=(\d+)/)?.[1];
1845
+ return `https://www.youtube.com/embed/${m[1]}${start ? `?start=${start}` : ""}`;
1846
+ }
1847
+ m = raw.match(/vimeo\.com\/(?:video\/)?(\d+)(?:\/([a-f0-9]+))?/i);
1848
+ if (m) {
1849
+ const h = m[2] ?? raw.match(/[?&]h=([a-z0-9]+)/i)?.[1];
1850
+ return `https://player.vimeo.com/video/${m[1]}${h ? `?h=${h}` : ""}`;
1851
+ }
1852
+ m = raw.match(/drive\.google\.com\/file\/d\/([\w-]+)/i);
1853
+ if (m) return `https://drive.google.com/file/d/${m[1]}/preview`;
1854
+ m = raw.match(/loom\.com\/(?:share|embed)\/([a-f0-9]+)/i);
1855
+ if (m) return `https://www.loom.com/embed/${m[1]}`;
1856
+ m = raw.match(/dailymotion\.com\/video\/(\w+)/i);
1857
+ if (m) return `https://www.dailymotion.com/embed/video/${m[1]}`;
1858
+ return raw;
1859
+ }
1860
+
1824
1861
  // ../src/shared/fontsAncho.ts
1825
1862
  var ANCHO_LETRA = {
1826
1863
  "Poppins": { 100: [712, 689], 200: [724, 692], 300: [736, 696], 400: [747, 699], 500: [760, 703], 600: [770, 708], 700: [782, 715], 800: [793, 723], 900: [805, 731] },
@@ -3437,6 +3474,26 @@ El ref "${refBase}" es el rengl\xF3n grande; cada uno es tambi\xE9n "${refBase}_
3437
3474
  const otros = hallada.parecidos.length ? ` Otras parecidas: ${hallada.parecidos.map((x) => `"${x}"`).join(", ")}.` : "";
3438
3475
  return hallada.exacto ? `Animaci\xF3n "${hallada.nombre}" puesta (id ${el.id}, exacto: true).${otros}` : `Animaci\xF3n "${hallada.nombre}" puesta (id ${el.id}, exacto: false). \u26A0\uFE0F OJO: no hay ninguna que sea "${busca}"; es la m\xE1s cercana.${otros}`;
3439
3476
  }
3477
+ // Solo lo ofrece el MCP. Mismo elemento que Insertar → Video del editor.
3478
+ case "poner_video": {
3479
+ const src = parseVideoInput(txt(args.url));
3480
+ if (!src) {
3481
+ return no(b, "La `url` tiene que ser el enlace https:// del video (YouTube, Vimeo, Drive, Loom, Dailymotion o un .mp4 subido) o el c\xF3digo <iframe> del sitio.");
3482
+ }
3483
+ const w = pct(args.w, 44);
3484
+ const el = encajar({
3485
+ id: nid("video"),
3486
+ kind: "video",
3487
+ x: pct(args.x, 28),
3488
+ y: pct(args.y, 24),
3489
+ w,
3490
+ h: w,
3491
+ src
3492
+ });
3493
+ const { dentroDe } = plantar(b, el, args.ref, args.capa);
3494
+ b.bitacora.push(`\u{1F3AC} Video${dentroDe ? ` en la capa \xAB${dentroDe}\xBB` : ""}`);
3495
+ return `Video puesto (id ${el.id}, ${src}).`;
3496
+ }
3440
3497
  case "poner_audio": {
3441
3498
  const url = txt(args.url).trim();
3442
3499
  if (!/^https?:\/\//i.test(url)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "boosterarena-mcp",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "El MCP de Booster: tu agente crea y edita presentaciones dentro de boosterarena.com",
5
5
  "keywords": [
6
6
  "mcp",
package/sesion.mjs CHANGED
@@ -199,11 +199,17 @@ function abrirNavegador(url) {
199
199
  * CINCO MINUTOS esperando hasta «Nadie volvió del navegador», sin decir por qué (2026-09-16). De 8
200
200
  * cuentas, 5 son de correo: Google por defecto era la opción equivocada para la mayoría.
201
201
  *
202
- * Solo se pregunta con una persona delante (terminal). Sin terminal no hay a quién preguntarle, y
203
- * se sigue con Google como antes, pero avisando de la salida.
202
+ * Solo se pregunta con una persona delante (terminal). Sin terminal (lo corre un AGENTE) NO se
203
+ * abre Google: un agente lo corría a secas, caía en Google y le abría a la coach una pestaña que su
204
+ * cuenta de correo nunca iba a pasar (2026-10-13). Se corta con la instrucción exacta.
205
+ * Con una persona delante se sigue preguntando (Enter = Google).
204
206
  */
205
207
  async function elegirPuerta() {
206
- if (!process.stdin.isTTY) return null;
208
+ if (!process.stdin.isTTY) {
209
+ throw new Error('Falta el correo. Pregúntale a la persona con qué CORREO entra a boosterarena.com y corre: '
210
+ + '`npx -y boosterarena-mcp entrar --correo <su-correo>`. Le llega un enlace de noreply@boosterarena.com '
211
+ + 'que tiene que abrir EN ESTE EQUIPO. No abras Google ni otra pestaña de inicio de sesión.');
212
+ }
207
213
  const rl = createInterface({ input: process.stdin, output: process.stdout });
208
214
  try {
209
215
  console.log('\n ¿Cómo entras a boosterarena.com?');