Generative features in your module
Add a Generate action to a module face. Maru bills the listener's own credits and records your app as the source.
A module face can ask the host to generate audio for the person using it. The host makes the request with its own sign-in, and Maru meters the job on that person's account. Your registered app is recorded as the source. The face never holds a token, a URL or an account identifier. It sees a status, job ids and progress events.
This is an experimental source-workspace feature. Hosted generation also requires an available inference service and an account admitted to hosted generation.
1. Register an app for the module
Open Creator apps and register an app:
- set Module to your module's id, for example
music.example.sdk-graph-effect; - tick inference:run among the offered permissions, so the app may ask to spend credits;
- add at least one callback: the page where your app's own sign-in runs.
The host looks up the app by module id. A module needs exactly one enabled
app. With none, or with more than one, the host reports unavailable and does
not generate. Nothing falls back to Maru's own attribution.
2. Request the capability
Declare the host capability in the module's UI options:
ui: {
entry: "./ui/index.tsx",
hostCapabilities: { optional: ["app.generation/v1"] },
},
Hosts offer face.appGeneration only to faces that declare it. It is
optional: a host without it, such as an offline plug-in, omits the prop, and
your face should keep working.
3. Generate from the face
const generation = face.appGeneration
useEffect(() => generation?.subscribe((event) => setStatus(event.type)), [generation])
const jobId = await generation!.submit({ prompt: "dry punchy drum loop", seconds: 4, audioType: "loop" })
submit takes a bounded request: a prompt of up to 1000 characters, 1 to 120
seconds, 1 to 8 items (variations), an optional model id (auto, sm-sfx,
sm-music or medium) and an optional audio type. The face cannot choose
seeds, a payer or an app. cancel(jobId) stops a job you submitted.
subscribe delivers the events of your own jobs: queued, progress, item,
item-error, then one of done, cancelled or error. An item event means
the host fetched that take and saved it to the person's generated sounds
library. It carries the seed, model, duration, sample rate and channel count,
not the audio.
status tells the face what to show:
| Status | Meaning | Face action |
|---|---|---|
ready | The person can generate now. | Show Generate. |
needs-sign-in | Nobody is signed in on this host. | Call requestAccess(); the host opens its sign-in. |
needs-consent | The person has not given your app spending permission. | Call requestAccess(); the host opens your app. |
unavailable | See reason, for example app-not-registered. | Explain; do not retry in a loop. |
The SDK Graph Effect reference module shows the complete pattern in
modules/sdk-graph-effect/src/ui/index.tsx.
Consent and billing
Spending permission is the same explicit inference:run consent a standalone
app receives. The person grants it once by signing in to your app through
Maru's consent page, which names your app, its owner, the account and its
shared credit balance. Until then the host reports needs-consent, and
requestAccess() opens your app's first registered callback origin.
Disconnecting the app in Connected apps, disabling it or
changing its access policy ends that permission for new requests and for
streams already running.
Every job uses the person's existing credit wallet, quotas and admission. The module page and the Studio preview submit with the website session; your face code is the same in each host.
What Usage shows
Each job's usage row and credit receipt record your app's client id. The person's Usage page groups credit consumption by app, under your app's current name. Historical rows keep the app id when the app is renamed or deleted.
The same code in a standalone app
A creator app that runs outside Maru uses the generation SDK's hosted
connector with an app credential: an authenticated fetch and your client id.
The connector adds the app header to every request. With a creator app OAuth
session, createCreatorAppGenerationConnector builds that credential from the
session's request function:
import { createCreatorAppGenerationConnector } from "@maruaudio/gen-sdk/service/hosted"
const cloud = createCreatorAppGenerationConnector({ config, request: session.request })
// equivalent to credentials: { kind: "app", fetch, clientId }
See Build an audio generator for the connector itself.