npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

genmagic-tanstack-ai

v0.1.0

Published

GenMagic adapters for TanStack AI: one API key for text, image, speech and video models (Veo, Kling, Seedance, Wan, FLUX, Nano Banana, GPT Image and more) with chat, generateImage, generateSpeech and generateVideo.

Readme

genmagic-tanstack-ai

GenMagic adapters for TanStack AI. One API key and one pay-as-you-go balance for more than 450 models: text, images, speech and video, including Veo, Kling, Seedance, Wan, FLUX, Nano Banana and GPT Image. Each model's price is public before you run it.

It adds four adapters: genmagicText for chat(), genmagicImage for generateImage(), genmagicSpeech for generateSpeech() and genmagicVideo for generateVideo().

Install

npm install genmagic-tanstack-ai @tanstack/ai

Needs @tanstack/ai 1.0.1 or newer and Node 22 or newer. The package is ESM.

Get a key (a free key with starter credit takes a minute): https://genmagic.co/get-api-key?utm_source=tanstack-ai&utm_medium=package

export GENMAGIC_API_KEY=...

Or pass it yourself. The key is read when a call is made, so creating an adapter never fails without one.

import { genmagicImage, createGenMagicImage } from 'genmagic-tanstack-ai'

genmagicImage('google/gemini-nano-banana-2.1', { apiKey: process.env.MY_KEY })
createGenMagicImage('google/gemini-nano-banana-2.1', process.env.MY_KEY!)

It is paid per generation

GenMagic bills every text, image, speech and video call against a prepaid balance, at the price listed for the model (see "Find models and prices"). A video is charged when the clip completes, not when it starts. This package never calls GenMagic by itself: you pay only for the generations your code asks for.

Text

import { chat } from '@tanstack/ai'
import { genmagicText } from 'genmagic-tanstack-ai'

const stream = chat({
  adapter: genmagicText('anthropic/claude-haiku-5.5'),
  threadId: 'thread-1',
  messages: [{ role: 'user', content: 'Write a one-line tagline for a coffee subscription.' }],
})

for await (const chunk of stream) {
  if (chunk.type === 'TEXT_MESSAGE_CONTENT') process.stdout.write(chunk.delta)
}

Text goes through GenMagic's OpenAI-compatible /chat/completions, so streaming, tools, outputSchema and usage work as they do with any OpenAI-style model. Set sampling and thinking with modelOptions (temperature, max_tokens, reasoning_effort, or any parameter in the model's supported_parameters). The chat({ reasoning }) shortcut is not mapped.

Images

import { generateImage } from '@tanstack/ai'
import { genmagicImage } from 'genmagic-tanstack-ai'

const result = await generateImage({
  adapter: genmagicImage('google/gemini-nano-banana-2.1'),
  threadId: 'thread-1',
  prompt: 'A red fox in snow, 35mm photo',
  size: '1792x1024',
})

console.log(result.images[0]?.url)

GenMagic images come in 1024x1024, 1792x1024 and 1024x1792, up to four per call (numberOfImages). The answer is a hosted url; set modelOptions: { response_format: 'b64_json' } to receive base64 instead. To transform a picture, add one image to the prompt:

prompt: [
  { type: 'text', content: 'Make it a watercolor' },
  { type: 'image', source: { type: 'url', value: 'https://example.com/fox.png' } },
]

GenMagic transforms one reference image per call and takes no mask, so more images or a mask role are refused with a clear error before anything is sent. modelOptions: { type: 'logo' } steers the model toward a brand mark.

Speech

import { writeFile } from 'node:fs/promises'
import { generateSpeech } from '@tanstack/ai'
import { genmagicSpeech } from 'genmagic-tanstack-ai'

const result = await generateSpeech({
  adapter: genmagicSpeech('openai/gpt-audio-mini'),
  threadId: 'thread-1',
  text: 'Welcome to the show.',
  voice: 'alloy',
})

await writeFile(`welcome.${result.format}`, Buffer.from(result.audio, 'base64'))

result.audio is base64, and result.format and result.contentType say what GenMagic returned. GenMagic voices the text exactly as written in the format its model produces: format and speed are ignored with a warning.

Video

import { generateVideo } from '@tanstack/ai'
import { genmagicVideo } from 'genmagic-tanstack-ai'

const stream = generateVideo({
  adapter: genmagicVideo('alibaba/wan-3.0'),
  threadId: 'thread-1',
  prompt: 'Waves at sunset, slow drone shot',
  size: '16:9',
  duration: 5,
  pollingInterval: 5000,
  stream: true,
})

for await (const chunk of stream) {
  if (chunk.type === 'CUSTOM' && chunk.name === 'generation:result') {
    console.log(chunk.value.url)
  }
}

A video is a job. The adapter starts it (GenMagic answers at once), then TanStack AI polls it until it is done. To start now and collect later, even from another process, keep the job id:

import { generateVideo, getVideoJobStatus } from '@tanstack/ai'

const adapter = genmagicVideo('alibaba/wan-3.0')
const { jobId } = await generateVideo({ adapter, threadId: 'thread-1', prompt: 'Waves at sunset' })

const status = await getVideoJobStatus({ adapter, jobId })
// status.status is 'pending', 'processing', 'completed' or 'failed'; status.url when completed

size is an aspect ratio (16:9, 9:16, 1:1), a resolution (720p) or width and height (1280x720, read as 16:9 at 720p). duration is whole seconds. Which durations and resolutions a model has is in its catalog entry. Put the rest in modelOptions, for example { generate_audio: true, resolution: '720p' }.

Prompt images route by metadata.role: no role or start_frame is the opening image, end_frame is the closing image, reference or character adds a reference (up to nine; GenMagic does not combine references with an opening or closing image). Which models take which is in capabilities.frame_images and capabilities.references.

Find models and prices

Browse https://genmagic.co/models, or ask the API. The catalog needs no key.

curl -s "https://genmagic.co/api/v1/models?category=video" \
  | jq -r '.data[] | "\(.id)  $\(.pricing.est_per_generation_usd)"'

curl -s "https://genmagic.co/api/v1/models?category=image" \
  | jq -r '.data[] | "\(.id)  $\(.pricing.est_per_generation_usd)"'

category is text, image, audio or video. Speech models are the audio ones whose audio_kind is speech. est_per_generation_usd is the estimated price of one default generation; a model's pricing has the exact rates (per token, per image, per second at each resolution). The full API is described at https://genmagic.co/openapi.json.

What a call cost

GenMagic returns the cost of each image, speech and video call, and the balance left. They arrive as result.usage:

result.usage?.cost // US dollars, for example 0.058
result.usage?.providerUsageDetails // { costCents: 5.8, creditsRemainingCents: 194.2 }

For a video the usage is on the completed result (getVideoJobStatus(...).usage, or value.usage in the streamed generation:result). usage is left out when GenMagic did not send a cost. Text reports token counts as usual; GET https://genmagic.co/api/v1/usage returns your balance and spend.

Errors and retries

When GenMagic refuses a call you get its own message: a wrong key, too little balance (it says how to top up), a model's content refusal, a rate limit. Media calls throw a GenMagicApiError with status, code and type; chat() ends the run with a RUN_ERROR event carrying the same message and code. Without a key, the call fails before any request is sent and the message says where to get one.

A paid call is sent once and never retried by this package: GenMagic does not deduplicate, so a retry after a lost connection could bill twice. That covers every text, image, speech and video start, including after a 429 or 5xx. If you want TanStack AI to wait out a rate limit, opt in with chat({ retry }); the wait GenMagic asks for is on the RUN_ERROR.

The one thing that is retried is the video status lookup, which is read-only and free: after a network error, a 429 or a 5xx it is tried up to three more times (waits of 0.5, 1.5 and 3 seconds, or the longer wait GenMagic asks for). Change the waits with statusRetryDelaysMs on genmagicVideo, or pass [] to turn it off.

Settings

Each factory takes (model, config); each createGenMagic* factory takes (model, apiKey, config).

  • apiKey: defaults to GENMAGIC_API_KEY.
  • baseURL: defaults to https://genmagic.co/api/v1.
  • headers: extra headers for every call.
  • fetch: your own fetch, for logging, proxies or tests.
  • statusRetryDelaysMs (video only): waits between retries of a status lookup.

Every call carries X-GenMagic-Client: tanstack-ai/<version> so GenMagic can tell traffic through this package apart from your other API use.

Bring your own key

For apps where each user pastes their own key, genmagic-tanstack-ai/byok exports genmagicByok, a defineByokProvider descriptor (id: 'genmagic', env GENMAGIC_API_KEY). Import it from that subpath, never from the main entry.

Not covered

GenMagic's music and sound models, transcription, embeddings, voice design and live video have no adapter in this version.

Links

  • Developer docs: https://genmagic.co/developers?utm_source=tanstack-ai&utm_medium=package
  • Models and prices: https://genmagic.co/models
  • API reference: https://genmagic.co/openapi.json
  • Support: [email protected]

MIT