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

corent-sdk

v0.6.0

Published

Official TypeScript/JavaScript SDK for Corent — one API for AI image, video, voice, and text generation with built-in routing, failover, and exact receipts.

Readme

Corent SDK

One API for AI image, video, voice, and text generation. You pick a quality tier; Corent's router picks the best live model, reroutes failures, verifies the output, and returns the exact charge on every response. Failed generations are never billed.

npm install corent-sdk
import { Corent } from "corent-sdk";

const client = new Corent("co_live_..."); // get a key at https://corent.tech

const image = await client.images.generate("a lighthouse at dusk", {
  tier: "premium",
  aspectRatio: "9:16",
});
console.log(image.url, image.width, image.height, image.costCents);

const video = await client.videos.generate("a paper boat drifting across a puddle", {
  tier: "premium",
  durationS: 5,
  resolution: "1080p",
});
console.log(video.url, video.resolution, video.costCents);

const speech = await client.speech.generate("Welcome to Corent.");
console.log(speech.url, speech.costCents);

const answer = await client.text.generate("Name three uses for a paperclip.", { tier: "premium" });
console.log(answer.text, answer.costCents);

Make a film from one sentence

Describe the film and Corent writes the script, creates the characters once, shoots every scene with them speaking their lines, checks quality, reshoots a bad scene once, and joins it all into one video with sound. The price comes first and costs nothing; the charge never goes above maxCostCents; a film that fails or is cancelled is not billed.

const plan = await client.films.plan(
  "a 50 second parody where 5 founders start a startup, know nothing, and the AI part is easy because they used Corent",
  { durationS: 50 },
);
console.log(plan.title, `$${(plan.estimatedCostCents! / 100).toFixed(2)}`);
for (const scene of plan.scenes) console.log(scene.index, scene.action, scene.dialogue);

const started = await client.films.create({
  planId: plan.planId,
  maxCostCents: Math.ceil(plan.estimatedCostCents! * 1.1),
});
const film = await client.films.wait(started.filmId); // checks every 60 seconds; about 15 to 30 minutes
console.log(film.videoUrl, film.costCents);

A 50 second 720p film with five characters costs roughly $10 to $20. wait() throws GenerationFailedError if the film failed and FilmCancelledError if it was cancelled. client.films.get(id) shows the stage (writing, casting, shooting, checking, editing), client.films.cancel(id) stops one, and client.films.list({ customerId }) lists them.

What the SDK handles for you

  • Timeout-safe renders: images submit as background jobs and are polled; a network hiccup can never lose a finished (and billed) result.
  • Safe retries: every generate call carries an auto idempotency key; retries can never double-charge.
  • Backoff: 429/5xx retried with Retry-After respected.
  • Honest receipts: width/height are the measured pixels of the delivered file; costCents is the exact charge.

Pick a model yourself (direct access)

Pass model instead of tier to pin an exact model. It is never substituted: if that model can't deliver, the call fails and you are not charged.

const image = await client.images.generate("a lighthouse at dusk", { model: "corent-flux-schnell" });
console.log(image.model); // "corent-flux-schnell", the name you asked for

await client.models(); // the menu: every model with its kind, quality and live status

Each model has one name, published as corent- + the model: corent-flux-schnell, corent-seedance-2.0, corent-claude-opus-5. That is the spelling client.models() lists and the one every receipt echoes back. Older spellings you may already have hard-coded (flux-schnell, seedream-5.0-direct) keep working, the API accepts them and answers with the published name.

When we can reach a model by more than one route, Corent serves whichever is cheapest at that moment and charges you that price, you never have to shop between near-identical entries.

Text (language models)

Every frontier lab on one key and one bill, priced per token.

const answer = await client.text.generate("Explain reserve-then-settle billing.", {
  system: "Answer in two sentences.",
  tier: "premium",
});
console.log(answer.text, answer.promptTokens, answer.completionTokens, answer.costCents);

// a real conversation, tool calls included
const reply = await client.text.chat(
  [
    { role: "system", content: "Be terse." },
    { role: "user", content: "What's the weather?" },
  ],
  { model: "corent-claude-opus-5" },
);

Streaming isn't wrapped here: point any OpenAI-compatible client at https://api.corent.tech/v1 with your Corent key and it works as-is.

Keep a character or product consistent

Pass 1–4 reference images and the prompt is applied as an edit of them, so the same face, character, or product carries into a new scene.

const shot = await client.images.generate("the same woman, now on a beach", {
  tier: "pro", // edit-capable models sit at premium and up
  referenceImageUrls: ["https://cdn.example/her.png"],
});

air and lite cannot do this and say so with a 400. client.tiers() reports capabilities.supports_reference_images per tier.

A consistent character across shots

Make the character once as an image, then hand that image to every clip as a reference (@Image 1 in the prompt) on corent-seedance-2.5. Ask for the last frame back and start the next clip from it, so one shot flows into the next without a cut. Photos of real people are rejected as references; characters generated inside Corent are accepted.

const hero = await client.images.generate("a young sailor in a yellow raincoat, portrait, plain background", { tier: "pro" });

const shot1 = await client.videos.generate("@Image 1 pushes a rowing boat off a misty shore", {
  model: "corent-seedance-2.5",
  referenceImageUrls: [hero.url],
  aspectRatio: "16:9", durationS: 8,
  returnLastFrame: true,
});
const shot2 = await client.videos.generate("the boat drifts out and she looks back at the shore", {
  imageUrl: shot1.lastFrameUrl, // the exact frame shot 1 ended on
  returnLastFrame: true,
});
console.log(shot1.url, shot2.url, shot2.durationS);

referenceVideoUrls (up to 10, @Video 1) and referenceAudioUrls (up to 10, @Audio 1) work the same way, and task says what to do with them: auto, reference, edit, extend. Two helpers cover the last two:

const fixed = await client.videos.edit("Replace the red car in @Video 1 with a blue bicycle", shot1.url);
const longer = await client.videos.extend("she reaches the far bank and climbs out", shot2.url, { durationS: 5 });

An edit keeps the source clip's length and shape, an extension keeps its shape, and first/last frame (imageUrl / endImageUrl) cannot be mixed with references; the SDK throws InvalidRequestError before anything is sent. client.models() reports supports_reference_images, supports_video_edit, supports_video_extend and supports_last_frame per video model.

Upload your own files

Hand Corent a file and get back a URL every other call accepts: imageUrl, maskUrl, sourceImageUrl, referenceImageUrls. Takes a File/Blob (browser or Node), raw bytes (Buffer, Uint8Array), or a file path (Node). Up to 25 MB. The type comes from the File, then the filename's extension, unless you name one.

const up = await client.upload("product.png"); // or a Blob, or bytes with { filename: "product.png" }
console.log(up.url, up.contentType, up.bytes);

await client.images.generate("the same bottle, on a beach", { tier: "pro", referenceImageUrls: [up.url] });
await client.videos.generate("the bottle slowly rotates", { imageUrl: up.url });

Image tools: upscale, cut out, edit

Flat price, no tier, synchronous. The edit keeps every pixel outside the mask exactly as you sent it, which is what an ad needs when the product carries someone else's trademark.

const bigger = await client.images.upscale(up.url, { prompt: "keep the film grain" }); // prompt optional
const cutout = await client.images.removeBackground(up.url);                            // PNG, real transparency
const mask = await client.upload("mask.png");                    // white = regenerate, black = keep
const edited = await client.images.edit(up.url, mask.url, "a red can instead of the blue one");
console.log(edited.url, edited.costCents);

Tag spend by your own customer

Pass customerId (1 to 128 characters, your own id) on any generating call and client.usage({ customerId }) reports that customer's spend alone. Batches take a default plus a per-item override.

await client.images.generate("a fox", { tier: "air", customerId: "acct_8812" });
await client.text.generate("Summarise this.", { customerId: "acct_8812" });
await client.batches.images(
  [{ prompt: "a" }, { prompt: "b", customerId: "acct_other" }],
  { customerId: "acct_8812" }, // default for every item without its own
);
await client.usage({ customerId: "acct_8812" });

Batches and webhooks

// Up to 50 renders in one call. Each item bills at the normal rate.
const batch = await client.batches.images(
  [{ prompt: "a fox", tier: "air" }, { prompt: "a heron", tier: "air" }],
  { idempotencyKey: "campaign-9" }, // a retry replays instead of re-billing
);
const progress = await client.batches.progress(batch.batchId);

// Or have the server deliver each result and skip polling entirely.
await client.videos.generate("a drone shot", {
  tier: "premium",
  webhookUrl: "https://your-server.com/webhooks/corent",
  webhookSecret: "your_shared_secret", // signs every delivery
});

What else you can ask for

// Repeat an image exactly, then change one thing.
const first = await client.images.generate("a fox in a library", { tier: "pro" });
const again = await client.images.generate("a fox in a library, wearing glasses", {
  tier: "pro", seed: 12345, negativePrompt: "text, watermark",
});

// Four versions of one prompt in one call (four real renders, four charges).
const { images, totalCostCents } = await client.images.generateMany("a fox", 4, { tier: "air" });

// A transparent logo, at a size you choose.
await client.images.generate("a minimal fox mark", { transparent: true, width: 1024, height: 1024 });

// Video with sound, going from one picture to another.
await client.videos.generate("the camera pulls back", {
  tier: "premium", audio: true,
  imageUrl: "https://.../start.png", endImageUrl: "https://.../end.png",
  camera: "zoom_out",
});

// Pick a voice, and shape how it reads.
const voices = await client.voices();
await client.speech.generate("Welcome aboard.", {
  voiceId: voices[0].voice_id, stability: 0.3, speed: 1.1,
});

// Started something by mistake? Stop it. Costs nothing.
await client.jobs.cancel(job.id);

audio: true routes only to models that actually render sound, so a silent model can never quietly serve the request. Not every model takes every setting: anything the chosen one could not honour comes back in meta.unsupported_options rather than being silently ignored.

Fine-grained control

const job = await client.images.generate("...", { tier: "max_pro", wait: false });
const done = await client.jobs.wait(job.id); // resume any time

await client.tiers();    // live catalog with honest min–max price ranges
await client.models();   // direct-access menu: names, quality, live status (no price; billing is flat cost-plus)
await client.balance();  // { balanceCents, heldCents, availableCents }
await client.usage();    // what this account has spent; { customerId } narrows it

Every generate call sends an Idempotency-Key, so the SDK's own retries can never double-charge. Pass your own idempotencyKey to make that survive a process restart too.

Tiers: air | lite | premium | pro | max_pro, see corent.tech/pricing. Models: corent.tech/models. Docs: corent.tech/docs. MCP server for agents: corent-mcp.