@botmesh/core 2.0.0, los demás paquetes públicos 1.0.0)
congela la API pública. La beta (@botmesh/core 2.0.0-beta, los demás paquetes
públicos 1.0.0-beta) ya la incluye, así que estas páginas también sirven para
pasar de una alpha a la beta. Si vienes de una alpha de 2.0, casi todo tu código
sigue funcionando: las APIs renombradas conservan un alias @deprecated (tu
editor las tacha), y las pocas rupturas reales están marcadas como Ruptura
en estas páginas.
Checklist de actualización
Síguelo en orden; cada paso enlaza a los detalles.- Actualiza todos los paquetes
@botmesh/*a la vez, a la misma línea de versiones. No se soporta mezclar un core antiguo con paquetes de canal nuevos. - Dependencias (detalles): instala ffmpeg si tu bot de
Baileys envía notas de voz, pasa los bots de Gemini a
@google/genai, revisa el rango del peerredisy la versión de la Graph API, y actualiza los dashboards que leen métricasbotwa_*. - Pasa el verificador de tipos (
tsc --noEmit) y corrige lo que reporte (detalles abajo): imports que se movieron a@botmesh/core/spi,/testingo/internal,@botmesh/ai/testing,@botmesh/baileys/internaly las APIs eliminadas deRedisStore. - Reemplaza los nombres obsoletos (tabla):
ctx.replyen vez dectx.say,flowen vez deaddKeyword,bot.send,bot.plugpara plugins,bot.trigger,onType… Siguen funcionando, pero se eliminan en la v3. - Revisa los cambios de comportamiento (detalles). Los
dos que necesitan casi todos los bots:
lang: 'es'si tu bot habla español (los textos internos ahora están en inglés) ymaxAttempts: Ndonde una espera usabaretries: N. - Lee las notas de tus canales y plugins (detalles).
- Pasa tus tests y arranca el bot una vez con un listener
bot.on('error', …). Atento al aviso único deretriesy aConfigValidationError, que ahora nombra cualquier opción de duración inválida.
Entradas del paquete
La entrada principal (@botmesh/core) ahora solo exporta lo que necesita una
aplicación (372 nombres, antes 512). Todo lo demás pasó a un subpath:
Ruptura:
@botmesh/core ya no exporta los nombres de abajo. Cambia la ruta
del import; los valores son los mismos.
MessagingFeature y
MessagingSupport (ctx.supports()), ResolvedWaitOptions
(ConversationControlsBase.waitAny()) y JsonValue (la forma de
SerializedMediaRef.data y de los registros de los journals; también lo exporta
@botmesh/core/spi). Impórtalos de @botmesh/core, no de /internal ni de /testing.
@botmesh/core sigue reexportando las funciones de transcripciones doradas
(recordTranscript, RecordingProvider, redactTranscript,
transcriptFromStore, parseTranscript…), pero están obsoletas: impórtalas de
@botmesh/core/testing.
Un nombre por concepto
Estos alias siguen funcionando y están marcados como@deprecated:
bot.enterConversation(handler, ctx) con un handler en línea no está
obsoleto: es la forma de arrancar una conversación que no está registrada.
BotConfig.storeConfig ahora tiene tipo (file, maxMessagesPerChat,
autoSaveInterval) y el bot avisa en el log cuando se usa. Poner
durability.backend y durability.journal con dos backends distintos lanza un
ConfigValidationError.
Plugins: una instancia por nombre
Ruptura:bot.plug() lanza si ya hay enchufado un plugin con el mismo
name. Antes se instalaba también la segunda instancia y las dos ejecutaban
sus handlers. Para volver a enchufar un plugin, llama antes a su función
unplug. Un plugin pensado para correr varias veces pone multiple: true en su
spec:
Duraciones
Toda opción de duración deBotConfig acepta un texto de duración o un número
de milisegundos, incluidas todas las opciones *Ms. typing.minMs,
typing.maxMs y backoff.baseMs / backoff.capMs de la durabilidad solo
aceptaban números; ahora aceptan '800ms', '1s', etc.
Ruptura (validación más estricta): new Bot() ahora interpreta cada opción
de duración y lanza un ConfigValidationError que la nombra
(err.field === 'coordination.turnWaitMs') cuando un valor no se puede leer.
Antes algunos valores inválidos fallaban más tarde, con un mensaje que no
nombraba la opción, y unas pocas aceptaban null.
Logger
El contratoLoggerLike no cambia, y su convención de llamada queda
documentada: los paquetes llaman logger.warn('mensaje') o
logger.warn({ err, ...contexto }, 'mensaje'), como pino. Ver
Logs.
Paquetes de canales y stores
Los paquetes públicos de canales y stores siguen la misma regla: un nombre por concepto, con el antiguo como alias@deprecated hasta v3.
El mapeador de errores de bajo nivel de cada provider se llama ahora
to<Canal>Error; los canales que eran privados durante las alphas tienen los mismos
cambios de nombre (toDiscordError, toEmailError y toTikTokError en el canal de
TikTok, que sigue siendo privado), y @botmesh/messenger y
@botmesh/instagram, públicos desde la beta, solo traen toMessengerError y
toInstagramError. Los cambios de comportamiento de estos paquetes (votos de encuestas
en Telegram, ediciones en Discord, versionado del esquema de SQLite) están en
Notas de actualización: canales y plugins.
@botmesh/baileys: entradas y tipos nativos
La entrada principal conserva lo que necesita una aplicación (BaileysProvider, sus
opciones, toJid, isEditedMessage, RateLimiter, los tipos de PollStore). El
resto pasó a @botmesh/baileys/internal, sin garantía semver; los nombres antiguos
siguen en la entrada principal como alias @deprecated hasta v3.
-
Ruptura:
@botmesh/baileysya no exportatoInboundnitoOutbound: sus firmas usan los tipos propios de Baileys. Impórtalos desde@botmesh/baileys/internal. -
Ruptura (solo tipos): los valores nativos de Baileys son opacos.
provider.socketesBaileysSocket | null,provider.authesBaileysAuthState, y elraw/nativede mensajes, refs y resultados de envío esBaileysNativeMessage; los tres son alias deunknown. En ejecución no cambia nada. UsasocketOf(provider)yauthStateOf(provider)de@botmesh/baileys/internalpara tenerlos tipados, o haz el cast con tu propio import de@whiskeysockets/baileys: -
Los predicados de JID (
isGroup,isPn,isLid,isBroadcast,isNewsletter) devuelvenbooleanen lugar deboolean | undefined(undefinedahora esfalse). -
pairingCodepasa a llamarsepairingPhoneNumber(el valor siempre fue el número de teléfono); pasar los dos con números distintos lanza unTypeError.
@botmesh/redis-store
Ruptura: los internos del layout de claves cluster pasan a un subpath nuevo sin
garantía semver, @botmesh/redis-store/internal. La opción layout, el tipo
RedisKeyLayout, migrateToClusterLayout(), inspectKeyspace(),
isRedisClusterClient() y withClusterRetry() siguen en la entrada principal.
Ruptura: se eliminan dos API deprecadas.
Entradas de @botmesh/ai
@botmesh/ai se divide igual que el core: 135 nombres en la entrada principal antes, 98 después.
@botmesh/ai sigue reexportando MockAIProvider, MockOptions y MockTurn, pero
obsoletos: impórtalos de @botmesh/ai/testing.
Ruptura: @botmesh/ai ya no exporta estos nombres. Cambia la ruta del import; los valores
son los mismos.
Los contratos de cliente no cambian de forma: sus tipos de petición y respuesta ahora van
escritos en línea, así que un cliente falso tipado
AnthropicLike (u OpenAILike,
GeminiLike…) compila igual. Para nombrar una respuesta, derívala del contrato o impórtala de
/internal:
PRESETS, DEFAULT_YES, DEFAULT_NO, AI_MESSAGES y
AI_LOCALES están congelados en profundidad y tipados readonly. Antes, modificarlos cambiaba
los valores por defecto de todos los bots del proceso; ahora lanza un TypeError en modo
estricto. Extiende una copia:
toolConfirm.yes/.no aceptan un readonly string[]).
Los constructores de proveedores reciben ahora un AIProviderConfig (model, maxTokens,
effort, thinking, baseUrl), la parte de AIConfig que lee un proveedor. Pasar un
AIConfig entero guardado en una variable sigue compilando, pero un objeto literal con
campos del plugin falla ahora la comprobación de propiedades sobrantes de TypeScript
(TS2353), porque los proveedores nunca los leen:
GenerateInput.onStreamEnd recibe un AIStreamEndInfo con
nombre; su contrato (una vez, tras el último fragmento, solo si termina con normalidad) está en
Notas de actualización: canales y plugins.
Paquetes HTTP, Graph y scaffolder
@botmesh/http: SecureFetchOptions cerrado. Las opciones de secureFetch y
fetchBuffer ya no extienden RequestInit. Llevan los campos de la petición que
el cliente respeta (method, headers, body, signal) y su política
(allowHttp, allowPrivateHosts, timeoutMs, maxBytes, maxRedirects,
resolver, fetch).
- Ruptura (solo tipos): desaparece
redirect. Siempre se sobrescribía con'manual', porque el cliente sigue las redirecciones por su cuenta y valida cada salto; usamaxRedirects(0rechaza cualquier redirección). - Los demás campos de
RequestInit(cache,keepalive,integrity…) siguen compilando con una sobrecarga@deprecated(LegacySecureFetchOptions) y se siguen pasando afetch. Dejan de aceptarse en la estable. - Las subidas en streaming no necesitan ningún campo extra: con un
bodyReadableStream(o iterable asíncrono), el cliente pone elduplex: 'half'que exige fetch. Quita elduplexexplícito junto con los demás campos deRequestInit. - Una variable con tipo
SecureFetchOptionsya no admite campos de navegador (mode,credentials,window…). Quítalos. resolvePublicHostpasa a llamarseresolveHost: resuelve cualquier host y deja el veredicto aassertSafeTarget. El nombre antiguo queda como alias@deprecated.
@botmesh/graph-core: un objeto de opciones. checkGraphSignature recibe
{ body, headers, appSecret, logger }. La forma posicional sigue funcionando como
sobrecarga @deprecated, con los mismos resultados. graph-core es un paquete
público y lo cubre semver como a los demás: un cambio incompatible en él es una
versión mayor.
@botmesh/meta: la fontanería de la ventana de sesión es experimental. Lo
que una app configura y consulta sigue siendo público y lo cubre semver:
SessionWindowManager (constructor, forScope, state, isOpen, expiresAt,
pending, clearPending), SessionWindowOptions, el contrato
SessionWindowStore y su MemorySessionWindowStore, los tipos de informe y de
reapertura, SessionWindowReopenedError y las constantes. Los ganchos que mueve
el provider (send, noteInbound, noteFailedStatus) y su tipo RawSend pasan
a @experimental: pueden cambiar en una versión menor. En ejecución no cambia
nada. Ver Estabilidad de la API.
create-botmesh: internos en /internal. La entrada principal es el
scaffolder: scaffold, sanitizeName, getTemplate y TEMPLATE_NAMES.
TEMPLATES, agentsMd, findBotMeshMonorepo y AgentsMdInfo pasan a
create-botmesh/internal (sin semver); la entrada principal los reexporta como
@deprecated hasta la estable. La CLI no cambia.
Token de la API del sandbox
@botmesh/sandbox es privado, pero los scripts que usan su API web cambian:
- Ruptura:
POST /api/<canal>/send|fault|status|resetnecesita ahora el token de la ejecución en la cabecerax-sandbox-token. Léelo desandbox.token(o de la salida de la CLI), o fíjalo constartSandbox({ token })/--token. - Las peticiones con un
Hostque no es de loopback, o con unOriginde otro sitio, reciben un 403. PasaallowedHosts/--allow-hostsi llegas al hub con otro nombre a propósito. - Una entrada incorrecta es ahora un 4xx: se rechazan los campos desconocidos,
los tipos erróneos y un cuerpo que no sea un objeto JSON, y
toUserInput()lanzaSandboxInputError.