cd /news/ai-tools/messagebuilderv4-3-js · home topics ai-tools article
[ARTICLE · art-16080] src=gist.github.com pub= topic=ai-tools verified=true sentiment=· neutral

MessageBuilderV4.3.js

Developer Nixel released MessageBuilderV4.3.js, an advanced WhatsApp interactive message builder that creates buttons, carousels, native flows, and AI-rich response payloads using the Baileys library. The library features fluent chaining, flexible payload customization, and scalable architecture for modern bot development, with permission granted for personal or commercial use but prohibiting reuploading or reselling as a standalone product.

read22 min publishedMay 25, 2026

| /** | |

  • NIXCODE - Advanced WhatsApp Interactive Message Builder | |
  • Built for creating buttons, carousels, native flows, | |
  • and AI rich response payloads using Baileys with | |
  • fluent chaining, flexible payload customization, | |
  • and scalable architecture for modern bot development. | |
  • | |
  • Created by Nixel | |
  • wa.me/6282139672290 | |
  • | |
  • Copyright (c) 2026 Nixel | |
  • | |
  • Permission is granted to use and modify this library | |
  • for personal or commercial projects. | |
  • | |
  • Reup, reselling, relicensing, or redistributing | |
  • this library as a standalone product is prohibited. | |
  • | |
  • Do not claim this project as your own original work. | | */ | | | | const VERSION = '4.3'; | | | | import { generateWAMessageFromContent, prepareWAMessageMedia } from 'baileys'; | | import crypto from 'crypto'; | | import sharp from 'sharp'; | | | | function extractHyperlink(text) { | | let hyperlink = [], | | stack = [], | | result = '', | | last = 0, | | index = 1, | | entity = 0; | | for (let i = 0; i < text.length; i++) { | | if (text[i] == '[' && text[i - 1] != '\') { | | stack.push(i); | | } else if (text[i] == ']' && text[i + 1] == '(') { | | let start = stack.pop(); | | if (start == null) continue; | | let end = i + 2, | | depth = 1; | | while (end < text.length && depth) { | | if (text[end] == '(' && text[end - 1] != '\') depth++; | | else if (text[end] == ')' && text[end - 1] != '\') depth--; | | end++; | | } | | if (depth) continue; | | let txt = text.slice(start + 1, i).trim(), | | url = text.slice(i + 2, end - 1), | | reference_id = txt ? 0 : index++, | | key = IE_${entity++}, | | tag = {{${key}}}${txt || 'Nixel'}{{/${key}}}; | | result += text.slice(last, start) + tag; | | last = end; | | hyperlink.push({ | | reference_id, | | key, | | text: txt, | | url, | | }); | | i = end - 1; | | } | | } | | result += text.slice(last); | | return { | | text: result, | | hyperlink, | | }; | | } | | | | async function fetchBuffer(url, options = {}, config = {}) { | | try { | | let response = await fetch(url, options); | | if (!response.ok) throw Error(HTTP ${response.status}); | | return Buffer.from(await response.arrayBuffer()); | | } catch (error) { | | if (config.silent) return Buffer.alloc(0); | | throw error; | | } | | } | | | | class BaseBuilder { | | constructor() { | | this._title = ''; | | this._subtitle = ''; | | this._body = ''; | | this._footer = ''; | | this._contextInfo = {}; | | this._extraPayload = {}; | | } | | | | setTitle(title) { | | this._title = title; | | return this; | | } | | | | setSubtitle(subtitle) { | | this._subtitle = subtitle; | | return this; | | } | | | | setBody(body) { | | this._body = body; | | return this; | | } | | | | setFooter(footer) { | | this._footer = footer; | | return this; | | } | | | | setContextInfo(obj) { | | if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { | | throw new TypeError('ContextInfo must be a plain object'); | | } | | | | this._contextInfo = obj; | | return this; | | } | | | | addPayload(obj) { | | if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { | | throw new TypeError('Payload must be a plain object'); | | } | | | | Object.assign(this._extraPayload, obj); | | | | return this; | | } | | } | | | | class Button extends BaseBuilder { | | #client; | | | | constructor(client) { | | super(); | | if (!client) { | | throw new Error('Socket is required'); | | } | | this.#client = client; | | | | this._buttons = []; | | this._data; | | this._currentSelectionIndex = -1; | | this._currentSectionIndex = -1; | | this._params = {}; | | } | | | | setVideo(path, options = {}) { | | if (!path) throw new Error('Url or buffer needed'); | | Buffer.isBuffer(path) ? (this._data = { video: path, ...options }) : (this._data = { video: { url: path }, ...options }); | | return this; | | } | | | | setImage(path, options = {}) { | | if (!path) throw new Error('Url or buffer needed'); | | Buffer.isBuffer(path) ? (this._data = { image: path, ...options }) : (this._data = { image: { url: path }, ...options }); | | return this; | | } | | | | setDocument(path, options = {}) { | | if (!path) throw new Error('Url or buffer needed'); | | Buffer.isBuffer(path) ? (this._data = { document: path, ...options }) : (this._data = { document: { url: path }, ...options }); | | return this; | | } | | | | setMedia(obj) { | | if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { | | throw new TypeError('Media must be a plain object'); | | } | | | | this._data = obj; | | return this; | | } | | | | clearButtons() { | | this._buttons = []; | | return this; | | } | | | | setParams(obj) { | | this._params = obj; | | return this; | | } | | | | addButton(name, params) { | | this._buttons.push({ | | name, | | buttonParamsJson: typeof params === 'string' ? params : JSON.stringify(params), | | }); | | | | return this; | | } | | | | makeRow(header = '', title = '', description = '', id = crypto.randomUUID()) { | | if (this._currentSelectionIndex === -1 || this._currentSectionIndex === -1) { | | throw new Error('You need to create a selection and a section first'); | | } | | const buttonParams = JSON.parse(this._buttons[this._currentSelectionIndex].buttonParamsJson); | | buttonParams.sections[this._currentSectionIndex].rows.push({ header, title, description, id }); | | this._buttons[this._currentSelectionIndex].buttonParamsJson = JSON.stringify(buttonParams); | | return this; | | } | | | | makeSections(title = '', highlight_label = '') { | | if (this._currentSelectionIndex === -1) { | | throw new Error('You need to create a selection first'); | | } | | const buttonParams = JSON.parse(this._buttons[this._currentSelectionIndex].buttonParamsJson); | | buttonParams.sections.push({ title, highlight_label, rows: [] }); | | this._currentSectionIndex = buttonParams.sections.length - 1; | | this._buttons[this._currentSelectionIndex].buttonParamsJson = JSON.stringify(buttonParams); | | return this; | | } | | | | addSelection(title) { | | this._buttons.push({ name: 'single_select', buttonParamsJson: JSON.stringify({ title, sections: [] }) }); | | this._currentSelectionIndex = this._buttons.length - 1; | | this._currentSectionIndex = -1; | | return this; | | } | | | | addReply(display_text = '', id = crypto.randomUUID()) { | | this._buttons.push({ name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text, id }) }); | | return this; | | } | | | | addCall(display_text = '', id = crypto.randomUUID()) { | | this._buttons.push({ | | name: 'cta_call', | | buttonParamsJson: JSON.stringify({ | | display_text, | | id, | | }), | | }); | | return this; | | } | | | | addReminder(display_text = '', id = crypto.randomUUID()) { | | this._buttons.push({ | | name: 'cta_reminder', | | buttonParamsJson: JSON.stringify({ | | display_text, | | id, | | }), | | }); | | return this; | | } | | | | addCancelReminder(display_text = '', id = crypto.randomUUID()) { | | this._buttons.push({ | | name: 'cta_cancel_reminder', | | buttonParamsJson: JSON.stringify({ | | display_text, | | id, | | }), | | }); | | return this; | | } | | | | addAddress(display_text = '', id = crypto.randomUUID()) { | | this._buttons.push({ | | name: 'address_message', | | buttonParamsJson: JSON.stringify({ | | display_text, | | id, | | }), | | }); | | return this; | | } | | | | addLocation() { | | this._buttons.push({ | | name: 'send_location', | | buttonParamsJson: '', | | }); | | return this; | | } | | | | addUrl(display_text = '', url = '', webview_interaction = false) { | | this._buttons.push({ | | name: 'cta_url', | | buttonParamsJson: JSON.stringify({ | | display_text, | | url, | | webview_interaction, | | }), | | }); | | return this; | | } | | | | addCopy(display_text = '', copy_code = '', id = crypto.randomUUID()) { | | this._buttons.push({ | | name: 'cta_copy', | | buttonParamsJson: JSON.stringify({ | | display_text, | | copy_code, | | id, | | }), | | }); | | return this; | | } | | | | static paramsList = { | | limited_time_offer: { | | text: 'string', | | url: 'string', | | copy_code: 'string', | | expiration_time: 'number', | | }, | | bottom_sheet: { | | in_thread_buttons_limit: 'number', | | divider_indices: ['number'], | | list_title: 'string', | | button_title: 'string', | | }, | | tap_target_configuration: { | | title: 'string', | | description: 'string', | | canonical_url: 'string', | | domain: 'string', | | buttonIndex: 'number', | | }, | | }; | | | | async toCard() { | | return { | | body: { | | text: this._body, | | }, | | footer: { | | text: this._footer, | | }, | | header: { | | title: this._title, | | subtitle: this._subtitle, | | hasMediaAttachment: !!this._data, | | ...(this._data ? await prepareWAMessageMedia(this._data, { upload: this.#client.waUploadToServer }) : {}), | | }, | | nativeFlowMessage: { | | messageParamsJson: JSON.stringify(this._params), | | buttons: this._buttons, | | }, | | }; | | } | | | | async build(jid, { ...options } = {}) { | | const message = await this.toCard(); | | | | return generateWAMessageFromContent( | | jid, | | { | | ...this._extraPayload, | | interactiveMessage: { | | ...message, | | contextInfo: this._contextInfo, | | }, | | }, | | { ...options } | | ); | | } | | | | async send(jid, { ...options } = {}) { | | const msg = await this.build(jid, options); | | | | await this.#client.relayMessage(msg.key.remoteJid, msg.message, { | | messageId: msg.key.id, | | additionalNodes: [ | | { | | tag: 'biz', | | attrs: {}, | | content: [ | | { | | tag: 'interactive', | | attrs: { type: 'native_flow', v: '1' }, | | content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }], | | }, | | ], | | }, | | ], | | ...options, | | }); | | return msg; | | } | | } | | | | class ButtonV2 extends BaseBuilder { | | #client; | | | | constructor(client) { | | super(); | | if (!client) { | | throw new Error('Socket is required'); | | } | | | | this.#client = client; | | this._image; | | this._data; | | this._buttons = []; | | } | | | | addButton(displayText = '', buttonId = crypto.randomUUID()) { | | this._buttons.push({ buttonId, buttonText: { displayText }, type: 1 }); | | return this; | | } | | | | addRawButton(obj) { | | if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { | | throw new TypeError('Buttons must be a plain object'); | | } | | | | this._buttons.push(obj); | | return this; | | } | | | | setThumbnail(path) { | | if (!path) throw new Error('Url or buffer needed'); | | this._image = path; | | return this; | | } | | | | setMedia(obj) { | | if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) { | | throw new TypeError('Media must be a plain object'); | | } | | | | this._data = obj; | | return this; | | } | | | | async build(jid, { ...options } = {}) { | | let _thumbnail = this._image | | ? await sharp(Buffer.isBuffer(this._image) ? this._image : await fetchBuffer(this._image, {}, { silent: true })) | | .resize(300, 300) | | .png() | | .toBuffer() | | : null; | | const msg = generateWAMessageFromContent( | | jid, | | { | | ...this._extraPayload, | | buttonsMessage: { | | contentText: this._body, | | footerText: this._footer, | | ...(this._data | | ? this._data | | : { | | headerType: 6, | | locationMessage: { | | jpegThumbnail: _thumbnail, | | }, | | }), | | viewOnce: true, | | contextInfo: this._contextInfo, | | buttons: [...this._buttons], | | }, | | }, | | { ...options } | | ); | | return msg; | | } | | | | async send(jid, { ...options } = {}) { | | const msg = await this.build(jid, options); | | | | await this.#client.relayMessage(msg.key.remoteJid, msg.message, { | | messageId: msg.key.id, | | additionalNodes: [ | | { | | tag: 'biz', | | attrs: {}, | | content: [ | | { | | tag: 'interactive', | | attrs: { type: 'native_flow', v: '1' }, | | content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }], | | }, | | ], | | }, | | ], | | ...options, | | }); | | return msg; | | } | | } | | | | class Carousel extends BaseBuilder { | | #client; | | constructor(client) { | | super(); | | if (!client) { | | throw new Error('Socket is required'); | | } | | | | this.#client = client; | | this._cards = []; | | } | | | | addCard(card) { | | if (Array.isArray(card)) { | | this._cards.push(...card); | | } else { | | this._cards.push(card); | | } | | | | return this; | | } | | | | build(jid, { ...options }) { | | return generateWAMessageFromContent( | | jid, | | { | | ...this._extraPayload, | | interactiveMessage: { | | header: { | | hasMediaAttachment: false, | | }, | | body: { text: this._body }, | | footer: { text: this._footer }, | | contextInfo: this._contextInfo, | | carouselMessage: { | | cards: this._cards, | | }, | | }, | | }, | | { ...options } | | ); | | } | | | | async send(jid, { ...options } = {}) { | | const msg = this.build(jid, options); | | | | await this.#client.relayMessage(msg.key.remoteJid, msg.message, { | | messageId: msg.key.id, | | additionalNodes: [ | | { | | tag: 'biz', | | attrs: {}, | | content: [ | | { | | tag: 'interactive', | | attrs: { type: 'native_flow', v: '1' }, | | content: [{ tag: 'native_flow', attrs: { v: '9', name: 'mixed' } }], | | }, | | ], | | }, | | ], | | ...options, | | }); | | return msg; | | } | | } | | | | class AIRich { | | #client; | | constructor(client) { | | if (!client) { | | throw new Error('Socket is required'); | | } | | | | this.#client = client; | | this._submessages = []; | | this._sections = []; | | this._richResponseSources = []; | | } | | | | addText(text, { hyperlink = true } = {}) { | | const extractedHyperlink = hyperlink | | ? extractHyperlink(text) | | : { | | text, | | hyperlink: [], | | }; | | | | this._submessages.push({ | | messageType: 2, | | messageText: hyperlink ? extractedHyperlink.text : text, | | }); | | | | if (extractedHyperlink.hyperlink.length && hyperlink) { | | this._sections.push({ | | view_model: { | | primitive: { | | text: extractedHyperlink.text, | | inline_entities: extractedHyperlink.hyperlink.map(({ reference_id, key, text, url }) => ({ | | key, | | metadata: text?.trim() | | ? { | | display_name: text, | | is_trusted: true, | | url, | | __typename: 'GenAIInlineLinkItem', | | } | | : { | | reference_id, | | reference_url: url, | | reference_title: url, | | reference_display_name: url, | | sources: [], | | __typename: 'GenAISearchCitationItem', | | }, | | })), | | __typename: 'GenAIMarkdownTextUXPrimitive', | | }, | | __typename: 'GenAISingleLayoutViewModel', | | }, | | }); | | } else { | | this._sections.push({ | | view_model: { | | primitive: { | | text, | | __typename: 'GenAIMarkdownTextUXPrimitive', | | }, | | | | __typename: 'GenAISingleLayoutViewModel', | | }, | | }); | | } | | | | return this; | | } | | | | addCode(language, code) { | | const meta = AIRich.tokenizer(code, language); | | | | this._submessages.push({ | | messageType: 5, | | codeMetadata: { | | codeLanguage: language, | | codeBlocks: meta.codeBlock, | | }, | | }); | | | | this._sections.push({ | | view_model: { | | primitive: { | | language, | | code_blocks: meta.unified_codeBlock, | | __typename: 'GenAICodeUXPrimitive', | | }, | | __typename: 'GenAISingleLayoutViewModel', | | }, | | }); | | | | return this; | | } | | | | addTable(table) { | | const meta = AIRich.toTableMetadata(table); | | | | this._submessages.push({ | | messageType: 4, | | tableMetadata: { | | title: meta.title, | | rows: meta.rows, | | }, | | }); | | | | this._sections.push({ | | view_model: { | | primitive: { | | rows: meta.unified_rows, | | __typename: 'GenATableUXPrimitive', | | }, | | __typename: 'GenAISingleLayoutViewModel', | | }, | | }); | | | | return this; | | } | | | | addSource(sources = []) { | | const source = sources.map(([profile_url, url, text]) => ({ | | source_type: 'THIRD_PARTY', | | source_display_name: text, | | source_subtitle: 'AI', | | source_url: url, | | favicon: { | | url: profile_url, | | mime_type: 'image/jpeg', | | width: 16, | | height: 16, | | }, | | })); | | | | this._sections.push({ | | view_model: { | | primitive: { | | sources: source, | | __typename: 'GenAISearchResultPrimitive', | | }, | | __typename: 'GenAISingleLayoutViewModel', | | }, | | }); | | | | return this; | | } | | | | addReels(reelsItems = []) { | | this._submessages.push({ | | messageType: 9, | | contentItemsMetadata: { | | contentType: 1, | | itemsMetadata: reelsItems.map((item) => ({ | | reelItem: { | | title: item.title, | | profileIconUrl: item.profileIconUrl, | | thumbnailUrl: item.thumbnailUrl, | | videoUrl: item.videoUrl, | | }, | | })), | | }, | | }); | | | | reelsItems.forEach((item, idx) => { | | this._richResponseSources.push({ | | provider: 'UNKNOWN', | | thumbnailCDNURL: item.thumbnailUrl, | | sourceProviderURL: item.videoUrl, | | sourceQuery: '', | | faviconCDNURL: item.profileIconUrl, | | citationNumber: idx + 1, | | sourceTitle: item.title, | | }); | | }); | | | | this._sections.push({ | | view_model: { | | primitives: reelsItems.map((item) => ({ | | reels_url: item.videoUrl, | | thumbnail_url: item.thumbnailUrl, | | creator: item.title, | | avatar_url: item.profileIconUrl, | | reels_title: item.reels_title, | | likes_count: 0, | | shares_count: 0, | | view_count: 0, | | reel_source: 'IG', | | is_verified: item.is_verified, | | __typename: 'GenAIReelPrimitive', | | })), | | __typename: 'GenAIHScrollLayoutViewModel', | | }, | | }); | | | | return this; | | } | | | | addImage(imageUrl) { | | const imageUrls = Array.isArray(imageUrl) | | ? imageUrl.map((url) => ({ | | imagePreviewUrl: url, | | imageHighResUrl: url, | | sourceUrl: 'https://google.com', | | })) | | : [ | | { | | imagePreviewUrl: imageUrl, | | imageHighResUrl: imageUrl, | | sourceUrl: 'https://google.com', | | }, | | ]; | | | | this._submessages.push({ | | messageType: 1, | | gridImageMetadata: { | | gridImageUrl: { | | imagePreviewUrl: Array.isArray(imageUrl) ? imageUrl[0] : imageUrl, | | }, | | imageUrls, | | }, | | }); | | | | imageUrls.forEach(({ imagePreviewUrl }) => { | | this._sections.push({ | | view_model: { | | primitive: { | | media: { | | url: imagePreviewUrl, | | mime_type: 'image/jpeg', | | }, | | imagine_type: 3, | | status: { | | status: 'READY', | | }, | | __typename: 'GenAIImaginePrimitive', | | }, | | __typename: 'GenAISingleLayoutViewModel', | | }, | | }); | | }); | | | | return this; | | } | | | | build({ forwarded = true, includesUnifiedResponse = true, ...options } = {}) { | | const contextInfo = forwarded | | ? { | | forwardingScore: 1, | | isForwarded: true, | | forwardedAiBotMessageInfo: { botJid: '0@bot' }, | | forwardOrigin: 4, | | } | | : {}; | | | | return { | | messageContextInfo: { | | deviceListMetadata: {}, | | deviceListMetadataVersion: 2, | | botMetadata: { | | pluginMetadata: {}, | | richResponseSourcesMetadata: { sources: this._richResponseSources }, | | }, | | }, | | botForwardedMessage: { | | message: { | | richResponseMessage: { | | messageType: 1, | | submessages: this.submessages, | | unifiedResponse: { | | data: includesUnifiedResponse ? Buffer.from(JSON.stringify({ response_id: crypto.randomUUID(), sections: this.sections })).toString('base64') : '', | | }, | | contextInfo, | | }, | | }, | | }, | | }; | | } | | | | async send(jid, { forwarded, includesUnifiedResponse, ...options } = {}) { | | const msg = this.build({ forwarded, includesUnifiedResponse, ...options }); | | | | return await this.#client.relayMessage(jid, msg, { ...options }); | | } | | | | static tokenizer(code, lang = 'javascript') { | | const keywordsMap = { | | javascript: new Set([ | | 'break', | | 'case', | | 'catch', | | 'continue', | | 'debugger', | | 'delete', | | 'do', | | 'else', | | 'finally', | | 'for', | | 'function', | | 'if', | | 'in', | | 'instanceof', | | 'new', | | 'return', | | 'switch', | | 'this', | | 'throw', | | 'try', | | 'typeof', | | 'var', | | 'void', | | 'while', | | 'with', | | 'true', | | 'false', | | 'null', | | 'undefined', | | 'class', | | 'const', | | 'let', | | 'super', | | 'extends', | | 'export', | | 'import', | | 'yield', | | 'static', | | 'constructor', | | 'async', | | 'await', | | 'get', | | 'set', | | ]), | | }; | | | | const TYPE_MAP = { | | 0: 'DEFAULT', | | 1: 'KEYWORD', | | 2: 'METHOD', | | 3: 'STR', | | 4: 'NUMBER', | | 5: 'COMMENT', | | }; | | | | const keywords = keywordsMap[lang] || new Set(); | | const tokens = []; | | | | let i = 0; | | | | const push = (content, type) => { | | if (!content) return; | | const last = tokens[tokens.length - 1]; | | if (last && last.highlightType === type) last.codeContent += content; | | else tokens.push({ codeContent: content, highlightType: type }); | | }; | | | | while (i < code.length) { | | const c = code[i]; | | | | if (/\s/.test(c)) { | | let s = i; | | while (i < code.length && /\s/.test(code[i])) i++; | | push(code.slice(s, i), 0); | | continue; | | } | | | | if (c === '/' && code[i + 1] === '/') { | | let s = i; | | i += 2; | | while (i < code.length && code[i] !== '\n') i++; | | push(code.slice(s, i), 5); | | continue; | | } | | | | if (c === '"' || c === "'" || c === '`') { | | let s = i; | | const q = c; | | i++; | | while (i < code.length) { | | if (code[i] === '\' && i + 1 < code.length) i += 2; | | else if (code[i] === q) { | | i++; | | break; | | } else i++; | | } | | push(code.slice(s, i), 3); | | continue; | | } | | | | if (/[0-9]/.test(c)) { | | let s = i; | | while (i < code.length && /[0-9.]/.test(code[i])) i++; | | push(code.slice(s, i), 4); | | continue; | | } | | | | if (/[a-zA-Z$]/.test(c)) { | | let s = i; | | while (i < code.length && /[a-zA-Z0-9$]/.test(code[i])) i++; | | const word = code.slice(s, i); | | | | let type = 0; | | if (keywords.has(word)) type = 1; | | else { | | let j = i; | | while (j < code.length && /\s/.test(code[j])) j++; | | if (code[j] === '(') type = 2; | | } | | | | push(word, type); | | continue; | | } | | | | push(c, 0); | | i++; | | } | | | | return { | | codeBlock: tokens, | | unified_codeBlock: tokens.map((t) => ({ | | content: t.codeContent, | | type: TYPE_MAP[t.highlightType], | | })), | | }; | | } | | | | static toTableMetadata(arr) { | | if (!Array.isArray(arr) || arr.length < 2) throw new Error('Format tabel ngawur'); | | | | const [header, ...rows] = arr; | | | | const maxLen = Math.max(header.length, ...rows.map((r) => r.length)); | | | | const normalize = (r) => [...r, ...Array(maxLen - r.length).fill('')]; | | | | const unified_rows = [ | | { | | is_header: true, | | cells: normalize(header), | | }, | | ...rows.map((r) => ({ | | is_header: false, | | cells: normalize(r), | | })), | | ]; | | | | const rowsMeta = unified_rows.map((r) => ({ | | items: r.cells, | | ...(r.is_header ? { isHeading: true } : {}), | | })); | | | | return { | | title: '', | | rows: rowsMeta, | | unified_rows, | | }; | | } | | } | | | | export { VERSION, Button, ButtonV2, Carousel, AIRich }; |
── more in #ai-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/messagebuilderv4-3-j…] indexed:0 read:22min 2026-05-25 ·