MiniMax M3 como agente de programación OpenClaw: Cinco tareas frente a Kimi K3 y dsh, además de un widget que no logró crear
- Categoría
- IA y LLM Local
- Publicado
- 12 septiembre 2026
- Actualizado
- 12 septiembre 2026
- Por
- Jacob Lloyd — escrito con ayuda de IA, después del proyecto
- Tiempo de lectura
- 27 min de lectura
En palabras simples: Conecté el modelo M3 de MiniMax a OpenClaw, el marco de trabajo en el que se ejecutan mis asistentes de IA, y le asigné las mismas cinco tareas de programación que había dado previamente al Kimi K3 de Moonshot esa misma mañana. El modelo de MiniMax completó las cinco tareas en aproximadamente la mitad del tiempo que tardó Kimi; además, a precios de lista, su costo habría sido aproximadamente una cuarta parte del de Kimi. Pago a MiniMax una tarifa mensual fija, por lo que estas cifras monetarias sirven únicamente como referencia comparativa. También quería comparar cómo cada modelo generaba una versión en pixel art del logotipo de este sitio web. El widget que inicialmente atribuí a MiniMax resultó ser uno que Kimi había creado en su segundo intento: la ejecución de MiniMax encontró los archivos de Kimi, los probó y confirmó que se habían generado correctamente.
Ahora, MiniMax M3 ejecuta mi agente de trabajo en OpenClaw. Le asigné los mismos cinco pequeños trabajos de programación que había dado antes ese mismo día a Kimi K3, y superó todas las tareas en aproximadamente la mitad del tiempo que tardó Kimi, por un costo de apenas una cuarta parte del precio listado para Kimi. También quería comparar cómo ambos agentes creaban una versión en pixel art del logotipo de este sitio, partiendo del mismo brief escrito. Esa parte no resistió la verificación: el widget que inicialmente atribuí a MiniMax fue creado por Kimi; al ejecutarse, MiniMax encontró esos archivos y los reportó como obra propia. Los detalles se exponen a continuación, pues cómo ocurrió esto es lo más relevante de este artículo.
Resumen rápido
- ¿Qué es? MiniMax M3 controla el bucle de agentes de OpenClaw mediante el proveedor
minimaxincluido. Dicho proveedor utiliza la Anthropic Messages API enhttps://api.minimax.io/anthropic, no un endpoint al estilo de OpenAI. No se trata de Codex: el sistema de integración de OpenClaw solo acepta proveedores cuyo nombre seaopenai. - Configuración: la clave API se obtiene de la variable de entorno
MINIMAX_API_KEY. Además, la configuración relevante incluye un parámetro para sobrescribir el modelo (el contexto está limitado a 262.144 tokens, de los 1.000.000 disponibles en el catálogo) y la cadena de modelos a utilizar: primero M3, luego DeepSeek V4-Flash y finalmente V4-Pro. - Pruebas de rendimiento: cinco tareas, cada una en una sesión nueva. MiniMax M3 completó las 5 en 159,2 segundos; Kimi K3 lo hizo en 309,9 segundos; el sistema dsh con V4-Flash completó las 5 en 35,7 segundos. Se usaron archivos de prueba distintos y MiniMax necesitó varios reintentos; todo ello se describe más abajo, por lo que los tiempos deben interpretarse como valores orientativos.
- Costo: $0,125 por las cinco tareas de MiniMax, según los precios listados en OpenClaw ($0,60 por entrada / $2,40 por salida / $0,12 por millón de tokens leídos del caché). Como uso el plan de tarifa plana de MiniMax, este valor equivale al precio oficial, no a la factura real. Kimi costó $0,531 ($3 por entrada / $15 por salida / $0,30 por millón de tokens). dsh costó $0,011.
- Widget: MiniMax no generó ningún resultado. El widget de 323 líneas que etiqueté como primer intento de M3 es idéntico, byte por byte, al que Kimi K3 creó en su segundo intento; ambos fueron guardados en una carpeta compartida. La ejecución de MiniMax, que duró 59 segundos, leyó esos archivos, volvió a ejecutar sus pruebas y respondió “Compilado y verificado”.
¿Qué es realmente el proveedor minimax de OpenClaw?
En un borrador anterior me equivoqué, así que aquí está la información basada en el código instalado y mi propia configuración.
- Protocolo y endpoint. El plugin minimax integrado configura sus proveedores con
api: "anthropic-messages"y la URL basehttps://api.minimax.io/anthropic(una variable llamadaMINIMAX_API_HOSTpermite cambiar el host). MiniMax también ofrece una API compatible con OpenAI enhttps://api.minimax.io/v1, pero el plugin de OpenClaw no la utiliza. - Dos filas de proveedores, no tres.
minimaxes el proveedor principal del plugin; mi archivoopenclaw.jsonsolo sobrescribe su lista de modelos; el tipo de API, la URL base y la autenticación provienen todos del plugin.minimax-portales el segundo identificador de proveedor (su variante OAuth); lo declaro manualmente con el mismo endpoint y un contexto de 1,000,000 de tokens para aquellos trabajos largos que así lo requieran.minimax-cnno es una tercera fila, sino un alias de autenticación paraminimaxorientado a la región de China; su endpoint eshttps://api.minimaxi.com/anthropic. - La clave de acceso. Se trata de una variable de entorno. El plugin lee
MINIMAX_API_KEY(y algunas variantes relacionadas con planes de uso); en mi configuración, la filaminimax-portalhace referencia a ella mediante la cadena literal"${MINIMAX_API_KEY}". No hay ningún dato relacionado con MiniMax almacenado en el repositorio de secretos de OpenClaw. - Configuración de modelos. El catálogo del plugin asigna al modelo M3 una ventana de contexto de 1,000,000 de tokens y un único ajuste
compat, concretamentecodeMode: "preferred"(el Modo Código de OpenClaw, sin relación con Codex). No existe ningún parámetro para ajustar la temperatura. - Precios. El plugin fija el precio del modelo M3 en $0.60 por cada millón de tokens ingresados, $2.40 por cada millón generados y $0.12 por cada millón de tokens leídos desde la caché; esta tabla es la que rellena el valor
usage.cost.totalen el JSON resultante. Aún no he comparado estos precios con los publicados por MiniMax en su propia página de tarifas.
No es Codex
Este es el bucle de agentes propio de OpenClaw; no se trata del servidor de aplicaciones Codex de OpenAI. OpenClaw cuenta con un plugin de integración con Codex, pero su verificación de rutas (configuredModelRouteNeedsCodex) devuelve false para cualquier proveedor cuyo ID no se normalice a openai; por eso, una ruta como minimax/MiniMax-M3 nunca cumple los requisitos. El JSON generado en cada ejecución indica qué bucle se utilizó: agentHarnessId: "openclaw". De todos modos, el plugin de Codex no está instalado en mi equipo.
Para poner a M3 detrás de Codex haría falta un puente local como codex-router, además de permitir que el plugin de Codex comparta mi propio directorio ~/.codex; de esa forma, todos los agentes del equipo podrían utilizarlo. Pero no he hecho nada de eso. Todo lo descrito en este artículo corresponde al bucle nativo de OpenClaw.
Configuración
Las versiones que utilicé:
$ node -v
v24.18.0
$ openclaw --version
OpenClaw 2026.9.2 (3928bad)
$ dsh --version
0.1.1-rc.2
$ openclaw plugins list --json | jq '[.plugins[] | select(.enabled)] | length'
35
Paso 1: la clave
El plugin minimax se incluye en OpenClaw 2026.9.2 y está habilitado en mi instalación. Este plugin lee la clave desde MINIMAX_API_KEY; por lo tanto, introdúzcala en el entorno donde se ejecuta su gateway (ya sea mediante un archivo EnvironmentFile de systemd, un archivo plist de launchd o directamente en su shell). Luego, reinicie el gateway con el comando openclaw gateway restart. No pegue la clave directamente en openclaw.json. Si alguna fila del proveedor necesita hacer referencia a dicha clave, escriba "${MINIMAX_API_KEY}", y no el valor real de la clave.
Paso 2: apuntar un agente trabajador a M3
Hay dos partes en openclaw.json. Primero, la cadena de modelos del agente:
"agents": { "entries": { "worker": { "model": {
"primary": "minimax/MiniMax-M3",
"fallbacks": ["deepseek/deepseek-v4-flash", "deepseek/deepseek-v4-pro"]
} } } }
Luego, opcionalmente, un límite de contexto para la fila del modelo. Esta es la entrada de mi propia configuración. No contiene api, baseUrl ni apiKey, ya que estos datos provienen del plugin:
"models": { "providers": { "minimax": { "models": [ {
"id": "MiniMax-M3", "name": "MiniMax M3",
"reasoning": true, "input": ["text", "image"],
"contextWindow": 1000000, "contextTokens": 262144, "maxTokens": 128000,
"compat": { "codeMode": "preferred" }
} ] } } }
Repito toda la entrada de modelo del plugin en lugar de añadir solo esa clave, porque una sobrescritura parcial en este equipo hizo que se eliminara silenciosamente reasoning: true, y M3 funcionó durante días sin activar el razonamiento. El límite en sí: 262,144 de los 1,000,000 totales del catálogo; esto mantiene las sesiones largas de los agentes trabajadores compactas en lugar de permitir que crezcan sin control.
Paso 3: prueba de verificación
Esta es la tarea PONG del conjunto de pruebas; aquí se muestran los campos que me interesan:
$ openclaw agent --agent worker --model minimax/MiniMax-M3 \
--session-key agent:worker:bench-pong-1 \
-m "Reply with exactly: PONG." --json \
| jq '{harness: .result.meta.agentMeta.agentHarnessId,
provider: .result.meta.executionTrace.winnerProvider,
model: .result.meta.executionTrace.winnerModel,
contextTokens: .result.meta.agentMeta.contextTokens,
usage: (.result.meta.agentMeta.usage | {input, output, cacheRead, cost: .cost.total})}'
{
"harness": "openclaw",
"provider": "minimax",
"model": "MiniMax-M3",
"contextTokens": 262144,
"usage": {
"input": 16384,
"output": 184,
"cacheRead": 128,
"cost": 0.01028736
}
}
harness: "openclaw" representa el bucle nativo. winnerModel indica cuál fue el modelo que respondió, en lugar de un modelo alternativo. contextTokens muestra que el límite de tokens se aplicó efectivamente. Los 16.384 tokens de entrada no almacenados en caché corresponden mayormente al prompt del sistema y a las definiciones de herramientas que una sesión nueva envía en su primer turno; por eso incluso la tarea PONG conlleva un costo. Este costo corresponde al precio listado del plugin, no a lo que cobra un plan de tarifa fija.
En comparación: MiniMax M3, Kimi K3 y dsh
Dos de estos modelos son los que impulsan el bucle de ejecución de OpenClaw. El tercero, DeepSeek Harness (dsh), es el agente de programación desarrollado por DeepSeek, el cual cuenta con su propio bucle de ejecución. En artículos anteriores de esta serie también aparecía una columna correspondiente a Reasonix. Nunca realicé pruebas de rendimiento con Reasonix en modo headless, y lo retiré de mi configuración el 2026-09-09; por eso no figura aquí.
| MiniMax M3 en OpenClaw | Kimi K3 en OpenClaw | dsh | |
|---|---|---|---|
| Proveedor | MiniMax | Moonshot AI | DeepSeek, MIT |
| Forma de conexión | Plugin minimax integrado; API de mensajes de Anthropic en api.minimax.io/anthropic | Proveedor moonshot; API de completado de chat de OpenAI en api.moonshot.ai/v1 | Su propia interfaz CLI y UI web |
| Ejecución desde un script | openclaw agent --agent X --model minimax/MiniMax-M3 -m "…" --json | openclaw agent --agent X --model moonshot/kimi-k3 -m "…" --json | dsh --profile headless "…" |
| Cambio de modelo | El parámetro model en el archivo openclaw.json | Lo mismo | ~/.dsh/settings.yaml |
| Prueba de cinco tareas | 5/5, 159,2 s, $0,125 según precio listado | 5/5, 309,9 s, $0,531 | 5/5, 35,7 s, $0,011 (caché ya caliente) |
| Creación de widget de arte pixelado | No dispone de widget propio (véase abajo) | Tres intentos: no se generó código para el widget; un widget completo pero en la carpeta equivocada, interrumpido a los 15 minutos; un widget de 397 líneas con un prompt más estricto | Dos intentos; el segundo tomó 25 minutos y costó unos 49 centavos. |
| Versión | OpenClaw 2026.9.2 | OpenClaw 2026.9.2 | 0.1.1-rc.2, versión preliminar para desarrolladores |
El benchmark: cinco tareas
Las cinco tareas son las mismas que en el artículo de dsh: responder “PONG”; escribir y ejecutar FizzBuzz; corregir dos errores para que las pruebas unitarias pasen sin tocar dichas pruebas; resumir un código compuesto por seis módulos en menos de 150 palabras; renombrar una función en varios archivos y pruebas, y demostrar que estas siguen pasando. Las tres ejecuciones tuvieron lugar el 11-09-2026. En el caso de Kimi, las ejecuciones se realizaron entre las 07:46 y las 07:54 JST, con --thinking max. Los datos de dsh corresponden a una reejecución con caché “caliente” en la misma sesión. En el caso de MiniMax, las ejecuciones se llevaron a cabo entre las 09:11 y las 09:14 JST, usando el modo adaptativo de OpenClaw.
Lo que no fue igual:
- Archivos distintos. Cada ejecución generó sus propias carpetas temporales. En la tarea de corrección de errores se arreglaron errores diferentes (Kimi:
addeis_evenen un módulo; MiniMax:addysubtract). En la tarea de renombrado se cambiaron nombres distintos: Kimi renombrócalculate_totalacompute_totalen tres módulos y un archivo de pruebas; MiniMax renombróarea_of_rectarect_areaen el mismo contexto. Las estructuras de los archivos coinciden, pero los contenidos no. - Reintentos. En la primera ejecución, MiniMax utilizó una única sesión persistente para las cinco tareas, lo que provocó errores instructivos (ver “Posibles problemas”); por eso volví a ejecutarlas todas con claves de sesión nuevas. FizzBuzz requirió dos intentos adicionales, ya que el sistema seguía escribiendo
fizz.pyen su propio espacio de trabajo en lugar de en la carpeta temporal. La tabla muestra el cuarto intento de ejecución de FizzBuzz. También se reejecutaron FizzBuzz y la corrección de errores en Kimi: el primer intento de FizzBuzz terminó con un mensaje de límite de uso, y el primer intento de corrección de errores detectó que el archivo ya había sido arreglado en una ejecución previa.
| Tarea | MiniMax M3 | Kimi K3 | dsh V4-Flash (caché caliente) |
|---|---|---|---|
| Responder “PONG” | ✅ 7,2 s · 1 turno | ✅ 6,1 s · 1 turno | ✅ 1,7 s |
| Escribir y ejecutar FizzBuzz | ✅ 12,1 s · 3 turnos, 2 llamadas a herramientas | ✅ 22,8 s · 3 turnos, 2 llamadas a herramientas | ✅ 5,3 s |
| Corregir 2 errores, sin tocar las pruebas | ✅ 41,0 s · 8 turnos, 8 llamadas a herramientas | ✅ 86,6 s · 7 turnos, 6 llamadas a herramientas | ✅ 11,3 s |
| Resumir 6 módulos (<150 palabras) | ✅ 9,1 s · 3 turnos, 3 llamadas a herramientas (84 palabras) | ✅ 65,5 s · 5 turnos, 10 llamadas a herramientas | ✅ 5,1 s |
| Renombrar en archivos y pruebas | ✅ 89,9 s · 14 turnos, 22 llamadas a herramientas | ✅ 128,9 s · 10 turnos, 9 llamadas a herramientas | ✅ 12,3 s |
| Tiempo total | 159,2 s | 309,9 s | 35,7 s |
| Tokens: entrada sin caché / lectura de caché / salida | 87,4k / 456,7k / 7,6k | 91,5k / 355,3k / 10,0k (4,1k de ellos correspondientes a razonamiento) | 6,1k / 147,3k / 4,7k (2,0k de ellos correspondientes a razonamiento) |
| Lecturas de caché por cada token de entrada sin caché | 5,2 | 3,9 | 24 |
| Costo | $0,125 a razón de $0,60 / $2,40 / $0,12 por millón de tokens (precios listados; yo tengo un plan fijo) | $0,531 a razón de $3 / $15 / $0,30 por millón de tokens | $0,011 a razón de $0,44 / $1,32 / $0,014 por millón de tokens |
Los precios se indican por millón de tokens, en el orden siguiente: entrada sin caché / salida / lectura de caché. Cada costo es la suma de los valores usage.cost.total por tarea; multiplicar los totales de tokens por dichos precios arroja el mismo resultado.
Lo que revela la tabla:
- Todas las tareas se completaron correctamente. Verifiqué cada resultado en disco: salida de FizzBuzz, pruebas unitarias superadas, conteo de palabras del resumen, y ausencia de nombres obsoletos tras el renombrado.
- MiniMax fue aproximadamente 2 veces más rápido que Kimi y unas 4 veces más barato según los precios listados (309,9 s frente a 159,2 s; $0,531 frente a $0,125). Kimi operaba con el nivel máximo de razonamiento, lo cual explica parte de esa diferencia.
- dsh en V4-Flash resultó unas 4,5 veces más rápido que MiniMax y unas 11 veces más económico en este tipo de tareas.
- La caché es clave para el rendimiento. MiniMax leyó 5,2 tokens desde la caché por cada token de entrada sin caché. Según los precios listados, una lectura de caché cuesta un 80 % menos que una entrada sin caché. Si se hubieran facturado como entradas sin caché, el costo habría sido de unos $0,34 en lugar de $0,125.
- Los reintentos no se incluyen en los totales. Las doce ejecuciones de benchmark de MiniMax, incluidas las descartadas, supusieron un costo de $0,28 según precios listados y un tiempo de 321 s.
La prueba con el widget, y una corrección
El “divertido test” del artículo de dsh consistía en un widget de arte pixelado con el logotipo de este sitio, creado a partir de un brief escrito. Quería el mismo brief para Kimi y MiniMax. El brief, tal como lo recibieron cada uno de los modelos:
Resumen: widget interactivo de pixel art del logo de LaserLloyd
Cree una versión en pixel art del logo de LaserLloyd autocontenida y embebible (véase
reference-logo.png: un anillo azul grueso, color #1f3f8f sobre fondo blanco, que contiene dos letras “L” mayúsculas inclinadas; el pie de la “L” superior izquierda se ubica debajo del tallo de la “L” inferior derecha, como si las letras estuvieran apiladas en diagonal).Entregables (todos en esta carpeta)
ll-pixel-logo.js: un único archivo de JavaScript puro, sin dependencias, sin pasos de compilación ni solicitudes de red. Cualquier página puede incorporarlo mediante:<div class="ll-pixel-logo" data-size="320"></div>+<script src="ll-pixel-logo.js"></script>. El código busca todos los elementos.ll-pixel-logoy monta un<canvas>dentro de cada uno. Es responsivo: el canvas ocupa todo el ancho del contenedor (forma cuadrada) y se ve nítido en pantallas HiDPI (según devicePixelRatio). Se debe exponerwindow.LLPixelLogo.mount(el).index.html: una página de demostración que muestra el widget en 3 tamaños, acompañada de una breve descripción de sus interacciones.README.md: instrucciones para embeber el widget, explicación de las interacciones y detalles sobre los atributos disponibles.El arte
- Se utiliza una cuadrícula de píxeles de 40×40 celdas. NO dibuje a mano el bitmap (evite usar cadenas de caracteres tipo '#' o '.'; eso es lento y propenso a errores). En su lugar, genere el bitmap mediante algoritmos: implemente una función
isLit(col,row)que devuelva true para: (a) los puntos dentro del anillo: distancia desde el centro entre 0.82R y R; y (b) las dos letras “L” inclinadas, cada una formada por dos paralelogramos (un tallo girado ~20° y un pie); el pie de la “L” superior izquierda debe quedar justo debajo del tallo de la “L” inferior derecha, tal como en el logo de referencia. Ajuste las pocas constantes necesarias para que el resultado se parezca al logo original a 200px. Calcule previamente los píxeles iluminados durante el montaje.- Paleta de colores: azul del logo #1f3f8f; azul de resalte #2ea8ff; ámbar #ffb64a; cian #00e6cf; fondo transparente.
Interacciones (el objetivo del ejercicio: que sean agradables)
- Pasar el mouse o tocar la pantalla: los píxeles cercanos al cursor reaccionan físicamente; por ejemplo, se alejan del cursor como si fueran un fluido o estuvieran sujetos a repulsión magnética, para luego volver a su posición original con amortiguación. Mientras se desplazan, brillan en los colores #2ea8ff o #00e6cf. La animación debe ejecutarse a 60 fps mediante requestAnimationFrame, sin ralentizaciones.
- Click o toque: implemente un efecto llamativo y satisfactorio. Elija UN efecto principal y hágalo bien: por ejemplo, que todo el logo se fragmente en píxeles que vuelan hacia afuera bajo la influencia de la gravedad, para luego reensamblarse nuevamente (aprox. 1.5–2 segundos); o que un “láser” recorra el logo grabándolo píxel a píxel con chispas luminosas. Los clics repetidos deben sentirse gratificantes (no interrumpa la animación en curso).
- En reposo: un leve movimiento ambiental (un parpadeo lento o destellos ocasionales de píxeles) para que el widget nunca parezca inactivo, pero sin resultar distractor.
- Respete la directiva
prefers-reduced-motion: reduce: muestre solo el logo estático y mantenga el brillo al pasar el mouse.- Debe funcionar tanto con ratón como con pantallas táctiles. No debe interferir con el desplazamiento de la página.
Criterios de calidad
- Código limpio y comentado; no se deben usar variables globales salvo
LLPixelLogo. El ancho de tabulación debe ser 2. El código debe ocupar menos de 400 líneas.- El widget debe ejecutarse sin errores en la consola al abrirlo mediante
file://. Pruébelo usted mismo: escriba un pequeño script en Node o ábralo con cualquier herramienta para verificar su sintaxis y funcionalidad (ej.: jsdom NO está disponible; utilicenode --checky realice pruebas unitarias sin entorno DOM, como contar los píxeles iluminados y comprobar que el anillo y las dos letras “L” aparecen en sus posiciones correctas).- Al final, imprima un breve informe: qué ha creado, cómo embeber el widget y qué verificaciones realizó.
Lo que sucedió, en orden, según los registros de la sesión:
- Kimi, intento 1 (el mismo encargo que anteriormente): 8,8 minutos de procesamiento; no se generó ningún código para el widget. Costo: aproximadamente $0,31.
- Kimi, intento 2 (mismo encargo): escribió un archivo completo de 323 líneas llamado
ll-pixel-logo.js, una página de demostración, un archivo README y dos archivos de prueba. Luego ejecutó las pruebas y las ajustó hasta que se superaron con éxito. Todo esto, además de un breve informe de ejecución, lo guardó en el espacio de trabajo del propio agente, no en la carpeta que yo estaba monitoreando. La sesión se limitó a 15 minutos antes de que Kimi respondiera. Por eso pensé que el intento 2 no había producido nada. Costo: aproximadamente $0,72. - Kimi, intento 3 (restricciones más estrictas: escribir los archivos en una sola llamada a la herramienta, sin planificación previa ni ejecución de
node --check): 7,4 minutos; se generó un widget de 397 líneas en la carpeta correcta. Costo: $0,47. Este es el widget que se muestra en el artículo sobre Kimi. - MiniMax (mismo encargo que anteriormente; una hora después, con el mismo agente): 59,3 segundos, 25 interacciones y 24 llamadas a herramientas. Costo: $0,13 según el precio de lista. MiniMax encontró los archivos generados por Kimi en el espacio de trabajo compartido, leyó los cinco archivos y el informe de ejecución creado por Kimi; luego ejecutó las pruebas y respondió: “Se construyó y verificó todo el conjunto de widgets”. No escribió ni una sola línea de código para el widget; los únicos archivos que generó fueron su propio informe de ejecución y un archivo de estado.
Tomé esa respuesta al pie de la letra, y el primer borrador de este artículo describía el archivo como “el primer widget creado por MiniMax, en menos de un minuto”. El registro de la sesión muestra el write de ese mismo archivo a las 08:11 JST durante la sesión “attempt-2” de Kimi; además, el archivo en este sitio es idéntico a nivel de bytes. Por lo tanto, en cuanto a MiniMax y este encargo, todavía no tengo ningún resultado. El siguiente paso lógico es volver a ejecutarlo en una carpeta vacía. En el caso de Kimi, la historia es mejor de lo que conté inicialmente: su segundo intento tuvo éxito; simplemente colocó los archivos en el lugar equivocado.
Aquí está el widget “Intento-2” de Kimi, funcionando en esta página. Es el archivo que originalmente etiqueté incorrectamente:
prefers-reduced-motion.Sus primeras ~30 líneas:
/* ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
*
* Embed:
* <div class="ll-pixel-logo" data-size="320"></div>
* <script src="ll-pixel-logo.js"></script>
*
* One file, no dependencies, no build step, no network requests.
* The 40x40 bitmap is rasterised procedurally from geometry (a ring plus
* two interlocking italic Ls) — never a hand-drawn bitmap.
*
* Interactions:
* - pointer move : pixels are pushed away from the cursor, then spring
* back with damping; displaced pixels glow blue -> cyan
* - click / tap : the logo shatters outward with gravity + floor bounce,
* then reassembles itself (~1.8 s)
* - idle : occasional pixel twinkle (amber / cyan)
* Honours prefers-reduced-motion: static logo, hover glow only.
*
* Global exported: window.LLPixelLogo (also module.exports under node,
* so the bitmap can be unit-tested without a DOM).
*/
(function () {
'use strict';
/* ---------------- palette ---------------- */
var BLUE = [31, 63, 143]; // #1f3f8f logo blue
var HI = [46, 168, 255]; // #2ea8ff highlight blue
var AMBER = [255, 182, 74]; // #ffb64a
var CYAN = [0, 230, 207]; // #00e6cf
El intento 3 de Kimi, la versión que aparece en el artículo de Kimi, comienza así:
/*!
* ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
*
* Self-contained vanilla JS: no dependencies, no build step, no network.
* Embed on any page with:
*
* <div class="ll-pixel-logo" data-size="320"></div>
* <script src="ll-pixel-logo.js"></script>
*
* Every .ll-pixel-logo element gets a <canvas> mounted inside it at load.
* Programmatic API: window.LLPixelLogo.mount(el) -> instance.
*
* Art: 40x40 pixel grid, rasterised procedurally from geometry (ring + two
* interlocking italic Ls). Interactions: pointer repulsion with spring-back,
* click/tap shatter-and-reassemble, idle shimmer/twinkle, reduced-motion
* support. Mouse and touch. No scroll hijacking (all listeners passive).
*/
(function () {
'use strict';
// -- constants ------------------------------------------------------------
var VERSION = '1.0.0';
var GRID = 40; // logical grid: GRID x GRID cells
var BLUE = [31, 63, 143]; // #1f3f8f logo blue
var HILITE = [46, 168, 255]; // #2ea8ff highlight blue
var AMBER = [255, 182, 74]; // #ffb64a twinkle amber
var CYAN = [0, 230, 207]; // #00e6cf max-displacement glow
var CENTER = GRID / 2; // grid centre coordinate (20)
var R_OUT = 19; // ring outer radius (cells)
var R_IN = 0.82 * R_OUT; // ring inner radius
var SLANT = Math.tan(20 * Math.PI / 180); // ~20 deg italic shear
Y el widget de dsh, ese que está en la parte superior del artículo sobre dsh:
/*!
* ll-pixel-logo.js — interactive pixel-art LaserLloyd logo widget.
* Vanilla JS, zero dependencies, no network requests, works from file://.
* <div class="ll-pixel-logo" data-size="320"></div>
* <script src="ll-pixel-logo.js"></script>
* Auto-mounts on .ll-pixel-logo elements; window.LLPixelLogo.mount(el) too.
* Knobs: data-size, data-speed, data-static.
*/
(function (global) {
'use strict';
// ---- 0. palette -----------------------------------------------------
var BLUE = [31, 63, 143]; // #1f3f8f — logo blue
var HI = [46, 168, 255]; // #2ea8ff — hover / repulsion glow
var AMBER = [255, 182, 74]; // #ffb64a — twinkle spark
var CYAN = [0, 230, 207]; // #00e6cf — deep glow
// ---- 1. art: procedural 40x40 raster (no hand-drawn bitmap) ----------
// A cell is lit when it belongs to the ring or to one of the two slanted
// interlocking Ls. Each L is two parallelograms (stem + foot), described by
// top-left (ax,ay), width w, height h, sheared by SLANT (bottom edge shifts
// left): TL=(ax,ay) TR=(ax+w,ay) BL=(ax-SLANT*h,ay+h). The upper-left L's
// foot runs right and tucks under the lower-right L's stem, like the ref.
var GRID = 40; // cells per side
var RING_R = 19.7; // outer ring radius (cells)
var RING_IN = 0.80 * RING_R; // inner ring radius (reference ~0.808R)
var SLANT = 0.453; // shear of stems/feet (~24deg)
var LETTERS = [
{ ax: 15.0, ay: 5.2, w: 4.2, h: 10.6 }, // upper-left L: stem
{ ax: 10.2, ay: 15.8, w: 15.0, h: 3.8 }, // upper-left L: foot
{ ax: 24.7, ay: 13.8, w: 4.2, h: 14.7 }, // lower-right L: stem
{ ax: 18.0, ay: 28.5, w: 15.0, h: 3.8 } // lower-right L: foot
];
Todos los tres rasterizan un anillo más dos “L” inclinadas a partir de la geometría, exponen window.LLPixelLogo.mount y respetan prefers-reduced-motion. Conté las celdas iluminadas evaluando el valor de isLit en cada una dentro de la cuadrícula de 40×40:
- Kimi, intento 2:
RING_R = 19.4, radio interior 0.82R;SHEAR = 0.42(aproximadamente 22.8°). Se utiliza un ayudanteinLque gestiona tanto el pie como el tallo en un único test. 602 celdas llenas. - Kimi, intento 3:
R_OUT = 19, radio interior 0.82R;SLANT = tan 20°(aproximadamente 0.364). Se emplea un ayudantemakeLque devuelve tanto el tallo como el pie. 510 celdas llenas. - dsh:
RING_R = 19.7, radio interior 0.80R;SLANT = 0.453(aproximadamente 24°). Se utiliza un arregloLETTERScompuesto por cuatro elementos. 656 celdas llenas.
Ninguno se asemeja exactamente al logotipo de referencia; el brief solo exige que el resultado se vea como el logotipo a 200 píxeles, y los tres cumplen ese requisito. Yo dedicaría diez minutos a verificar las constantes antes de enviar cualquiera de ellos.
Lo que volví a verificar en el widget del intento 2
Ejecútelo en una copia provisional de la carpeta que contiene el widget y los dos archivos de prueba que escribió Kimi:
$ wc -l ll-pixel-logo.js
323 ll-pixel-logo.js
$ node --check ll-pixel-logo.js && echo "syntax ok"
syntax ok
$ node test-bitmap.js | tail -1
ALL PASS
$ node test-smoke.js | tail -1
SMOKE PASS
test-bitmap.js realiza 18 verificaciones: se comprueba que el anillo esté presente en los puntos cardinales y ausente en las esquinas y el centro; que el tallo y la base de cada “L” se encuentren en su cuadrante correspondiente; además, se revisa la zona de interconexión, la dirección de la inclinación y el número total de celdas iluminadas, que debe estar entre 540 y 670. test-smoke.js realiza 10 comprobaciones: un montaje con DOM simulado, un nuevo montaje idempotente, la presencia de role="img" y un atributo aria-label; también se verifican 300 fotogramas en los que hay un movimiento del puntero y dos clics (el segundo en medio de una animación); además, se comprueba el estado finito de las partículas, que el logotipo vuelva a su posición inicial después de todo, la existencia de un buffer gráfico de 640 píxeles con un devicePixelRatio de 2, y que la función unmount() se ejecute correctamente. Estas son las pruebas propias de Kimi; no constituyen una verificación independiente: Kimi modificó test-bitmap.js tras su primera ejecución, desplazando los “cuadros de detección” y ajustando el rango permitido para el número de celdas iluminadas a 540–670, una vez que obtuvo un valor de 602; todo ello hasta que todas las pruebas se superaron. Un resultado positivo aquí indica que el widget y sus pruebas coinciden, pero no significa que dichas pruebas establezcan un estándar mínimo. Mi propio recuento arroja 602 celdas iluminadas, distribuidas en 196 / 137 / 101 / 168 en los cuadrantes superior izquierdo, superior derecho, inferior izquierdo e inferior derecho, respectivamente.
Trampas comunes (las que yo realmente he cometido)
- Las sesiones persistentes arruinan los benchmarks. El comando
openclaw agent --agent worker -m "…"reutiliza la sesión del agente, a menos que se especifique una nueva clave de sesión mediante--session-key. En mi primera ejecución con MiniMax, el proceso FizzBuzz determinó que el archivo ya existía y se negó a sobrescribirlo; la ejecución de corrección de errores indicó que las pruebas ya habían pasado; y la ejecución de resumen analizó la carpeta de correcciones del proceso Kimi en lugar de la suya propia. El uso de una clave--session-keyúnica por tarea solucionó el problema. - Las instrucciones predeterminadas del agente tienen prioridad sobre lo indicado en el prompt respecto a dónde guardar los archivos. Las instrucciones de mi agente le indican que guarde las salidas largas en su propio espacio de trabajo; esto prevaleció sobre la orden “escribe fizz.py en esta carpeta” en dos ocasiones. En la tercera ejecución, el sistema afirmó haber escrito el archivo en la carpeta temporal; sin embargo, la marca de tiempo del archivo indica que se guardó en el espacio de trabajo. La cuarta ejecución, con una ruta absoluta y una instrucción explícita para usarla, tuvo éxito.
- Un espacio de trabajo compartido contamina las siguientes ejecuciones. Tal como se describió antes: los archivos abandonados por Kimi permanecieron en el espacio de trabajo del agente incluso una hora después, y MiniMax los trató como propios. Es necesario proporcionar una carpeta vacía para cada ejecución, y verificar qué archivos se crearon realmente (marcas de tiempo, llamadas
writerealizadas), no lo que el sistema afirma haber escrito. - Una salida de error no implica que la tarea haya fallado. En la ejecución con Kimi, la primera llamada a FizzBuzz devolvió el código de error 1, indicando que no se encontró ningún modelo óptimo, y finalizó con el mensaje “⚠️ Se alcanzó el límite de uso de la API. Por favor, inténtelo más tarde.”; sin embargo, el archivo
fizz.pyya se había creado y funcionaba correctamente. Solo en la ejecución de reintento se indicó que la tarea se completó. Hay que revisar los archivos, no el estado de salida del proceso. - El catálogo indica 1,000,000 de tokens; yo uso 262,144. Esa es mi configuración personal de
contextTokens; además,agentMeta.contextTokensen el archivo JSON confirma cuál valor está vigente. Aumente este número si realmente necesita un margen mayor; la entradaminimax-portalmuestra cómo hago esto para ciertas tareas. - Las cifras de costos en los planes fijos son ficticias, pero resultan útiles como referencia. OpenClaw rellena el campo
usage.cost.totalcon precios estándar según su catálogo, independientemente de lo que usted pague realmente; por eso sirve para comparar modelos, pero no para calcular facturas.
¿Qué significa esto para mí?
El modelo MiniMax M3 es el principal en mi agente de trabajo; DeepSeek V4-Flash y luego V4-Pro sirven como modelos de respaldo. Kimi K3 no forma parte de esa cadena de modelos; lo uso en otro lugar, para mi agente de revisión. En estas tareas, M3 realizó el cambio de nombre en 89,9 segundos, con un costo de $0,058 según el precio de lista; Kimi tardó 128,9 segundos y costó $0,180. Para la corrección de errores, M3 empleó 41,0 segundos y $0,025, frente a los 86,6 segundos y $0,114 que tardó Kimi. dsh en modo V4-Flash fue más rápido y económico que ambos modelos en todas las tareas.
El brief del widget sigue abierto para MiniMax. Cuando lo vuelva a ejecutar, obtendré una carpeta vacía; antes de leer su informe, revisaré las llamadas write realizadas durante la sesión.
Relacionado: Kimi K3 como agente de programación (el aspecto relacionado con Kimi en esta comparativa), DeepSeek Harness (dsh) (las cinco tareas y el brief original del widget), Reasonix (comparado en artículos anteriores; retirado de mi configuración el 09-09-2026) y Cuánto cuestan realmente mis agentes de IA.