Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion scripts/og-card/og-card.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { width: 1200px; height: 630px; }
/* Dimensiones inyectadas por scripts/og-card/render.mjs como vars CSS
antes de capturar. Defaults son los del OG card estándar (1200×630). */
html, body { width: var(--og-w, 1200px); height: var(--og-h, 630px); }

body {
position: relative;
Expand Down
99 changes: 80 additions & 19 deletions scripts/og-card/render.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
// descargar y el PNG sale con la fuente de fallback (Arial) en vez de
// Space Grotesk / JetBrains Mono.
//
// No requiere dependencias npm: localiza un Chrome/Chromium ya instalado.
// No requiere dependencias npm: localiza un Chrome/Chromium ya instalado
// en macOS, Linux (apt/snap) o vía CHROME_PATH.

import { spawn } from 'node:child_process';
import { mkdtempSync, existsSync, writeFileSync } from 'node:fs';
import { spawn, execSync } from 'node:child_process';
import { mkdtempSync, rmSync, existsSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, dirname, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
Expand All @@ -29,31 +30,82 @@ const OUT = resolve(__dirname, outArg);
const WIDTH = Number(wArg) || 1200;
const HEIGHT = Number(hArg) || 630;

function whichAll(bins) {
try {
const out = execSync('command -v ' + bins.join(' '), { encoding: 'utf8' });
return out.split('\n').map((s) => s.trim()).filter(Boolean);
} catch {
return [];
}
}

const CANDIDATES = [
// macOS
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
'/Applications/Chromium.app/Contents/MacOS/Chromium',
// Linux (apt / snap / manual install)
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
'/snap/bin/chromium',
// Fallback por PATH: útil para devtools-team installs o runtimes tipo Nix
...whichAll(['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser', 'chrome']),
// Override explícito del usuario
process.env.CHROME_PATH,
].filter(Boolean);

const chromeBin = CANDIDATES.find((p) => existsSync(p));
if (!chromeBin) {
console.error('No se encontró Chrome/Chromium. Define CHROME_PATH.');
console.error(
'No se encontró Chrome/Chromium. Define CHROME_PATH o instala uno de:\n' +
' - macOS: brew install --cask google-chrome\n' +
' - Linux: apt install chromium-browser\n'
);
process.exit(1);
}

const userDataDir = mkdtempSync(join(tmpdir(), 'og-card-'));
const port = 9333;

const chrome = spawn(chromeBin, [
'--headless=new',
`--remote-debugging-port=${port}`,
`--user-data-dir=${userDataDir}`,
`--window-size=${WIDTH},${HEIGHT}`,
'--hide-scrollbars',
'--force-color-profile=srgb',
'--no-first-run',
'--disable-extensions',
]);
const chrome = spawn(
chromeBin,
[
'--headless=new',
`--remote-debugging-port=${port}`,
`--user-data-dir=${userDataDir}`,
`--window-size=${WIDTH},${HEIGHT}`,
'--hide-scrollbars',
'--force-color-profile=srgb',
'--no-first-run',
'--disable-extensions',
],
{ stdio: ['ignore', 'inherit', 'inherit'] }
);

// Surface spawn failures (ENOENT, EACCES, libs faltantes) con un mensaje
// accionable en lugar de un timeout confuso de "DevTools no respondió".
chrome.on('error', (err) => {
console.error(`No se pudo arrancar Chrome (${chromeBin}):`, err.message);
cleanupAndExit(1);
});

let exiting = false;
function cleanupAndExit(code) {
if (exiting) return;
exiting = true;
try {
chrome.kill();
} catch {}
try {
rmSync(userDataDir, { recursive: true, force: true });
} catch {}
process.exit(code);
}

for (const sig of ['SIGINT', 'SIGTERM']) {
process.on(sig, () => cleanupAndExit(130));
}

async function waitForDevtools() {
for (let i = 0; i < 50; i++) {
Expand Down Expand Up @@ -84,7 +136,18 @@ async function main() {
sock.send(JSON.stringify({ id: msgId, method, params }));
});

await new Promise((res) => (sock.onopen = res));
await send('Emulation.setDeviceMetricsOverride', {
width: WIDTH,
height: HEIGHT,
deviceScaleFactor: 1,
mobile: false,
});
// Si el HTML define su tamaño en CSS (caso og-card.html), hay que
// sobrescribirlo en runtime para que el viewport del dispositivo coincida
// con el contenido — si no, la captura sale con scrollbars o recortada.
await send('Runtime.evaluate', {
expression: `document.documentElement.style.setProperty('--og-w', '${WIDTH}px'); document.documentElement.style.setProperty('--og-h', '${HEIGHT}px');`,
});
sock.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
if (msg.id && pending.has(msg.id)) {
Expand Down Expand Up @@ -115,12 +178,10 @@ async function main() {
console.log(`✓ og-card.png regenerada (${WIDTH}×${HEIGHT}) → ${OUT}`);

sock.close();
chrome.kill();
process.exit(0);
cleanupAndExit(0);
}

main().catch((err) => {
console.error(err);
chrome.kill();
process.exit(1);
cleanupAndExit(1);
});
5 changes: 2 additions & 3 deletions src/components/Header.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
import { NAV, SITE } from '../data/site';
import Owl from './Owl.astro';

interface Props {
activeHref?: string;
Expand All @@ -14,9 +15,7 @@ const isActive = (href: string) =>
<div class="site-header__bar">
<a class="brand" href="/" aria-label={`${SITE.nombre} — inicio`}>
<!-- búho line-art, usa currentColor para el glow -->
<svg class="brand__owl" viewBox="25940 20865 18235 13449" aria-hidden="true"><g fill="currentColor" transform="scale(69.3555)"><path d="M589.101 360.074C591.869 358.292 597.719 355.519 600.847 353.924C602.794 356.48 604.808 359.714 606.597 362.44C623.252 389.004 626.849 420.901 604.912 446.158C585.302 468.737 547.778 472.61 525.096 452.012C520.101 460.517 516.039 468.896 510.723 477.568C506.619 469.032 502.192 460.655 497.452 452.455C490.683 458.77 480.102 463.442 471.02 464.843C438.832 469.809 408.761 447.734 404.085 415.423C400.449 390.299 408.751 373.454 422.938 353.781C427.504 356.758 429.417 357.64 434.396 359.821C432.652 361.878 431.008 364.018 429.469 366.233C384.113 431.377 464.177 484.652 500.054 430.435C503.067 434.628 508.314 444.435 511.362 449.491C513.805 445.157 519.531 434.661 522.508 431.188C531.663 441.817 541.7 450.955 555.987 452.456C582.667 455.26 605.292 435.608 607.367 409.154C608.946 389.019 601.068 374.903 589.101 360.074Z"/><path d="M611.748 311.086C615.282 311.435 620.461 311.318 623.994 310.931C622.865 322.387 621.431 328.761 613.782 337.655C599.064 353.343 573.268 354.631 553.684 362.806C527.511 373.731 522.7 387.22 512.449 411.324C508.387 402.997 504.443 394.844 499.983 386.966C481.597 354.493 440.861 361.866 414.338 342.076C403.944 334.321 401.197 324.115 399.935 311.401C402.592 311.456 404.973 311.373 407.615 311.273C409.374 311.15 409.957 311.135 411.709 311.244C413.195 313.068 413.414 319.757 416.295 324.664C425.011 339.507 449.563 342.493 464.784 347.084C485.788 353.418 501.09 362.707 511.855 382.067C525.713 356.031 549.949 349.191 576.3 342.19C584.408 339.754 592.432 337.458 599.49 332.61C607.901 326.833 610.086 320.575 611.748 311.086Z"/><path d="M500.362 323.713C522.82 321.922 549.098 325.617 569.321 335.574C564.502 338.856 560.246 340.693 555.534 344.383C544.754 339.687 535.807 337.91 524.125 336.591C503.495 335.586 487.693 336.076 468.244 344.284C464.403 341.022 458.855 338.295 454.356 335.796C466.119 327.801 486.414 324.975 500.362 323.713Z"/></g>
<g fill="none" stroke="currentColor" stroke-width="470" stroke-linejoin="round" stroke-linecap="round"><circle cx="32320" cy="28010" r="1950"/><circle cx="38908" cy="28010" r="1950"/><path d="M35610 30600 L34850 31600 L35610 32850 L36370 31600 Z"/></g>
<g fill="currentColor"><circle cx="32320" cy="28010" r="560"/><circle cx="38908" cy="28010" r="560"/></g></svg>
<Owl class="brand__owl" />
<span class="brand__name">Código<b>SinSiesta</b></span>
</a>

Expand Down
38 changes: 38 additions & 0 deletions src/components/Owl.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
// Búho del brand: cabeza con cara line-art (anillos + pupila + pico).
// Usado en el header (brand__owl) y en el hero de la home (hero__owl).
// El color se hereda vía `currentColor` para que el glow del theme funcione.

interface Props {
class?: string;
}

const { class: className = '' } = Astro.props;
---

<svg
class={className}
viewBox="25940 20865 18235 13449"
aria-hidden="true"
>
<g fill="currentColor" transform="scale(69.3555)">
<path d="M589.101 360.074C591.869 358.292 597.719 355.519 600.847 353.924C602.794 356.48 604.808 359.714 606.597 362.44C623.252 389.004 626.849 420.901 604.912 446.158C585.302 468.737 547.778 472.61 525.096 452.012C520.101 460.517 516.039 468.896 510.723 477.568C506.619 469.032 502.192 460.655 497.452 452.455C490.683 458.77 480.102 463.442 471.02 464.843C438.832 469.809 408.761 447.734 404.085 415.423C400.449 390.299 408.751 373.454 422.938 353.781C427.504 356.758 429.417 357.64 434.396 359.821C432.652 361.878 431.008 364.018 429.469 366.233C384.113 431.377 464.177 484.652 500.054 430.435C503.067 434.628 508.314 444.435 511.362 449.491C513.805 445.157 519.531 434.661 522.508 431.188C531.663 441.817 541.7 450.955 555.987 452.456C582.667 455.26 605.292 435.608 607.367 409.154C608.946 389.019 601.068 374.903 589.101 360.074Z" />
<path d="M611.748 311.086C615.282 311.435 620.461 311.318 623.994 310.931C622.865 322.387 621.431 328.761 613.782 337.655C599.064 353.343 573.268 354.631 553.684 362.806C527.511 373.731 522.7 387.22 512.449 411.324C508.387 402.997 504.443 394.844 499.983 386.966C481.597 354.493 440.861 361.866 414.338 342.076C403.944 334.321 401.197 324.115 399.935 311.401C402.592 311.456 404.973 311.373 407.615 311.273C409.374 311.15 409.957 311.135 411.709 311.244C413.195 313.068 413.414 319.757 416.295 324.664C425.011 339.507 449.563 342.493 464.784 347.084C485.788 353.418 501.09 362.707 511.855 382.067C525.713 356.031 549.949 349.191 576.3 342.19C584.408 339.754 592.432 337.458 599.49 332.61C607.901 326.833 610.086 320.575 611.748 311.086Z" />
<path d="M500.362 323.713C522.82 321.922 549.098 325.617 569.321 335.574C564.502 338.856 560.246 340.693 555.534 344.383C544.754 339.687 535.807 337.91 524.125 336.591C503.495 335.586 487.693 336.076 468.244 344.284C464.403 341.022 458.855 338.295 454.356 335.796C466.119 327.801 486.414 324.975 500.362 323.713Z" />
</g>
<g
fill="none"
stroke="currentColor"
stroke-width="470"
stroke-linejoin="round"
stroke-linecap="round"
>
<circle cx="32320" cy="28010" r="1950" />
<circle cx="38908" cy="28010" r="1950" />
<path d="M35610 30600 L34850 31600 L35610 32850 L36370 31600 Z" />
</g>
<g fill="currentColor">
<circle cx="32320" cy="28010" r="560" />
<circle cx="38908" cy="28010" r="560" />
</g>
</svg>
4 changes: 2 additions & 2 deletions src/content/ensayos/agent-sprawl-gobernanza.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Agent sprawl: el problema de gobernanza que nadie ve venir"
description: "El 96% de las empresas ya ejecuta agentes de IA. Solo el 12% tiene una plataforma centralizada para gestionarlos. Y apenas el 18% sabe qué agentes están corriendo ahora mismo dentro de su organización."
fecha: 2026-06-14
fecha: 2026-06-13
tags: ["ia", "agentes", "enterprise", "gobernanza", "seguridad", "arquitectura"]
autor: "Alejandro de la Fuente"
---
Expand Down Expand Up @@ -60,7 +60,7 @@ El gateway hace cinco cosas:

5. **MCP servers con governance** — catálogo central de MCP servers disponibles, tokens encriptados con rotación automática, sin plain text en variables de entorno locales.

Databricks expandió Unity AI Gateway en abril de 2026 para incluir ejecutución on-behalf-of (el gateway actúa en nombre del usuario con sus permisos, no con los del sistema) y tracing completo con MLflow. Cada interacción tiene audit trail. Compliance deja de ser teatro.
Databricks expandió Unity AI Gateway en abril de 2026 para incluir ejecución on-behalf-of (el gateway actúa en nombre del usuario con sus permisos, no con los del sistema) y tracing completo con MLflow. Cada interacción tiene audit trail. Compliance deja de ser teatro.

---

Expand Down
Loading
Loading