@nodaro/sdk 2.54.0 → 2.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-P6AM42UB.cjs → chunk-2KX5ZE6M.cjs} +2 -2
- package/dist/chunk-2KX5ZE6M.cjs.map +1 -0
- package/dist/{chunk-JOVJAKBT.cjs → chunk-2LOTDOUV.cjs} +6 -6
- package/dist/chunk-2LOTDOUV.cjs.map +1 -0
- package/dist/{chunk-AN36M6HO.js → chunk-37LL6BPM.js} +5 -5
- package/dist/chunk-37LL6BPM.js.map +1 -0
- package/dist/{chunk-22P4X3N5.cjs → chunk-3CVWTUK5.cjs} +26 -8
- package/dist/chunk-3CVWTUK5.cjs.map +1 -0
- package/dist/{chunk-7CUWAVWB.js → chunk-4FSWJTRS.js} +3 -3
- package/dist/{chunk-7CUWAVWB.js.map → chunk-4FSWJTRS.js.map} +1 -1
- package/dist/{chunk-DV6GTEX5.js → chunk-4SZUSZXK.js} +2 -2
- package/dist/{chunk-DV6GTEX5.js.map → chunk-4SZUSZXK.js.map} +1 -1
- package/dist/{chunk-L6T44A3G.js → chunk-4VP2GFIZ.js} +20 -5
- package/dist/chunk-4VP2GFIZ.js.map +1 -0
- package/dist/{chunk-NKH2UFSD.cjs → chunk-4WOT5OAY.cjs} +5 -5
- package/dist/{chunk-NKH2UFSD.cjs.map → chunk-4WOT5OAY.cjs.map} +1 -1
- package/dist/{chunk-W5RMFTPA.cjs → chunk-57GANTLV.cjs} +2 -2
- package/dist/chunk-57GANTLV.cjs.map +1 -0
- package/dist/{chunk-HK5FSTKG.cjs → chunk-A3XA6UNM.cjs} +2 -2
- package/dist/chunk-A3XA6UNM.cjs.map +1 -0
- package/dist/{chunk-AUKHMT53.js → chunk-BGOZRZHY.js} +3 -3
- package/dist/{chunk-AUKHMT53.js.map → chunk-BGOZRZHY.js.map} +1 -1
- package/dist/{chunk-PBFODIFT.js → chunk-CBDUHYTR.js} +2 -2
- package/dist/chunk-CBDUHYTR.js.map +1 -0
- package/dist/{chunk-OSMKIRKI.cjs → chunk-DFT4LD2H.cjs} +4 -4
- package/dist/{chunk-OSMKIRKI.cjs.map → chunk-DFT4LD2H.cjs.map} +1 -1
- package/dist/{chunk-RBX3QTKB.js → chunk-E6X6BGRO.js} +3 -3
- package/dist/{chunk-RBX3QTKB.js.map → chunk-E6X6BGRO.js.map} +1 -1
- package/dist/{chunk-47ULSVO2.js → chunk-FTCAT2LK.js} +3 -3
- package/dist/chunk-FTCAT2LK.js.map +1 -0
- package/dist/{chunk-QGVOAPUI.js → chunk-GIQDM2MH.js} +2 -2
- package/dist/chunk-GIQDM2MH.js.map +1 -0
- package/dist/{chunk-65VIIZEF.cjs → chunk-GJH73EGF.cjs} +2 -2
- package/dist/{chunk-65VIIZEF.cjs.map → chunk-GJH73EGF.cjs.map} +1 -1
- package/dist/{chunk-HAVIVOLO.js → chunk-HFYNZ4SO.js} +2 -2
- package/dist/chunk-HFYNZ4SO.js.map +1 -0
- package/dist/{chunk-THLTFB6I.js → chunk-HJLSOT5C.js} +2 -2
- package/dist/chunk-HJLSOT5C.js.map +1 -0
- package/dist/{chunk-D2ILCSOQ.js → chunk-HK6XP5EN.js} +3 -3
- package/dist/{chunk-D2ILCSOQ.js.map → chunk-HK6XP5EN.js.map} +1 -1
- package/dist/{chunk-HWSYNUSC.js → chunk-HUYI5G3D.js} +2 -2
- package/dist/chunk-HUYI5G3D.js.map +1 -0
- package/dist/{chunk-JVDUGVLX.cjs → chunk-MIXRL6I2.cjs} +2 -2
- package/dist/chunk-MIXRL6I2.cjs.map +1 -0
- package/dist/{chunk-SF2CMKWA.cjs → chunk-OMJ45CW4.cjs} +9 -9
- package/dist/{chunk-SF2CMKWA.cjs.map → chunk-OMJ45CW4.cjs.map} +1 -1
- package/dist/{chunk-DAONQZPI.cjs → chunk-PDX742CC.cjs} +2 -2
- package/dist/chunk-PDX742CC.cjs.map +1 -0
- package/dist/{chunk-EZXFDCII.js → chunk-PQ6G5EM7.js} +15 -15
- package/dist/{chunk-EZXFDCII.js.map → chunk-PQ6G5EM7.js.map} +1 -1
- package/dist/{chunk-FRQJNGJS.cjs → chunk-Q4MFQC2J.cjs} +5 -5
- package/dist/{chunk-FRQJNGJS.cjs.map → chunk-Q4MFQC2J.cjs.map} +1 -1
- package/dist/{chunk-VHTDOACT.cjs → chunk-Q7W4QNE5.cjs} +22 -22
- package/dist/chunk-Q7W4QNE5.cjs.map +1 -0
- package/dist/{chunk-XZRBRXGJ.cjs → chunk-RIMDKJSQ.cjs} +28 -28
- package/dist/{chunk-XZRBRXGJ.cjs.map → chunk-RIMDKJSQ.cjs.map} +1 -1
- package/dist/{chunk-BQAW4RX2.js → chunk-VEQLP5TA.js} +25 -7
- package/dist/chunk-VEQLP5TA.js.map +1 -0
- package/dist/{chunk-I3MEBVLP.js → chunk-XZPSJG2X.js} +2 -2
- package/dist/chunk-XZPSJG2X.js.map +1 -0
- package/dist/{chunk-O74MSMFH.cjs → chunk-XZQ6Z4T6.cjs} +2 -2
- package/dist/chunk-XZQ6Z4T6.cjs.map +1 -0
- package/dist/{chunk-FM2KM5TY.cjs → chunk-Z4B4SZ33.cjs} +21 -4
- package/dist/chunk-Z4B4SZ33.cjs.map +1 -0
- package/dist/{developer-apps-zSQXWmEG.d.ts → developer-apps-CMUzKpE9.d.cts} +2 -0
- package/dist/{developer-apps-zSQXWmEG.d.cts → developer-apps-CMUzKpE9.d.ts} +2 -0
- package/dist/entries/apps.d.cts +1 -1
- package/dist/entries/apps.d.ts +1 -1
- package/dist/entries/audio.d.cts +1 -1
- package/dist/entries/audio.d.ts +1 -1
- package/dist/entries/billing.d.cts +1 -1
- package/dist/entries/billing.d.ts +1 -1
- package/dist/entries/cast-swap.cjs +2 -2
- package/dist/entries/cast-swap.d.cts +13 -1
- package/dist/entries/cast-swap.d.ts +13 -1
- package/dist/entries/cast-swap.js +1 -1
- package/dist/entries/catalogs.d.cts +1 -1
- package/dist/entries/catalogs.d.ts +1 -1
- package/dist/entries/characters.cjs +10 -10
- package/dist/entries/characters.d.cts +11 -3
- package/dist/entries/characters.d.ts +11 -3
- package/dist/entries/characters.js +1 -1
- package/dist/entries/client.cjs +21 -21
- package/dist/entries/client.d.cts +5 -5
- package/dist/entries/client.d.ts +5 -5
- package/dist/entries/client.js +16 -16
- package/dist/entries/collections.d.cts +1 -1
- package/dist/entries/collections.d.ts +1 -1
- package/dist/entries/community.d.cts +1 -1
- package/dist/entries/community.d.ts +1 -1
- package/dist/entries/competitors.d.cts +1 -1
- package/dist/entries/competitors.d.ts +1 -1
- package/dist/entries/copilot.cjs +4 -4
- package/dist/entries/copilot.d.cts +1 -1
- package/dist/entries/copilot.d.ts +1 -1
- package/dist/entries/copilot.js +3 -3
- package/dist/entries/core.cjs +6 -6
- package/dist/entries/core.d.cts +1 -1
- package/dist/entries/core.d.ts +1 -1
- package/dist/entries/core.js +2 -2
- package/dist/entries/creatures.cjs +6 -6
- package/dist/entries/creatures.d.cts +11 -3
- package/dist/entries/creatures.d.ts +11 -3
- package/dist/entries/creatures.js +1 -1
- package/dist/entries/credits.d.cts +1 -1
- package/dist/entries/credits.d.ts +1 -1
- package/dist/entries/developer-apps.d.cts +1 -1
- package/dist/entries/developer-apps.d.ts +1 -1
- package/dist/entries/edit.cjs +7 -7
- package/dist/entries/edit.d.cts +1 -1
- package/dist/entries/edit.d.ts +1 -1
- package/dist/entries/edit.js +2 -2
- package/dist/entries/errors.cjs +32 -24
- package/dist/entries/errors.d.cts +28 -4
- package/dist/entries/errors.d.ts +28 -4
- package/dist/entries/errors.js +1 -1
- package/dist/entries/executions.d.cts +1 -1
- package/dist/entries/executions.d.ts +1 -1
- package/dist/entries/gallery.d.cts +1 -1
- package/dist/entries/gallery.d.ts +1 -1
- package/dist/entries/jobs.cjs +2 -2
- package/dist/entries/jobs.d.cts +7 -4
- package/dist/entries/jobs.d.ts +7 -4
- package/dist/entries/jobs.js +1 -1
- package/dist/entries/keepers.d.cts +1 -1
- package/dist/entries/keepers.d.ts +1 -1
- package/dist/entries/library.d.cts +1 -1
- package/dist/entries/library.d.ts +1 -1
- package/dist/entries/llm.d.cts +1 -1
- package/dist/entries/llm.d.ts +1 -1
- package/dist/entries/locations.cjs +5 -5
- package/dist/entries/locations.d.cts +11 -3
- package/dist/entries/locations.d.ts +11 -3
- package/dist/entries/locations.js +1 -1
- package/dist/entries/media.cjs +4 -4
- package/dist/entries/media.d.cts +34 -5
- package/dist/entries/media.d.ts +34 -5
- package/dist/entries/media.js +3 -3
- package/dist/entries/models.d.cts +1 -1
- package/dist/entries/models.d.ts +1 -1
- package/dist/entries/moodboards.d.cts +1 -1
- package/dist/entries/moodboards.d.ts +1 -1
- package/dist/entries/node-presets.d.cts +1 -1
- package/dist/entries/node-presets.d.ts +1 -1
- package/dist/entries/nodes.cjs +3 -3
- package/dist/entries/nodes.d.cts +3 -3
- package/dist/entries/nodes.d.ts +3 -3
- package/dist/entries/nodes.js +2 -2
- package/dist/entries/oauth.d.cts +1 -1
- package/dist/entries/oauth.d.ts +1 -1
- package/dist/entries/objects.cjs +6 -6
- package/dist/entries/objects.d.cts +11 -3
- package/dist/entries/objects.d.ts +11 -3
- package/dist/entries/objects.js +1 -1
- package/dist/entries/organizations.d.cts +1 -1
- package/dist/entries/organizations.d.ts +1 -1
- package/dist/entries/palettes.d.cts +1 -1
- package/dist/entries/palettes.d.ts +1 -1
- package/dist/entries/picker-catalogs.d.cts +1 -1
- package/dist/entries/picker-catalogs.d.ts +1 -1
- package/dist/entries/pipelines.d.cts +1 -1
- package/dist/entries/pipelines.d.ts +1 -1
- package/dist/entries/projects.d.cts +1 -1
- package/dist/entries/projects.d.ts +1 -1
- package/dist/entries/prompt-helper.d.cts +1 -1
- package/dist/entries/prompt-helper.d.ts +1 -1
- package/dist/entries/recast.d.cts +1 -1
- package/dist/entries/recast.d.ts +1 -1
- package/dist/entries/reduce.d.cts +1 -1
- package/dist/entries/reduce.d.ts +1 -1
- package/dist/entries/saved-posts.d.cts +1 -1
- package/dist/entries/saved-posts.d.ts +1 -1
- package/dist/entries/scene3d.d.cts +4 -4
- package/dist/entries/scene3d.d.ts +4 -4
- package/dist/entries/sessions.d.cts +1 -1
- package/dist/entries/sessions.d.ts +1 -1
- package/dist/entries/shots.d.cts +1 -1
- package/dist/entries/shots.d.ts +1 -1
- package/dist/entries/studio.cjs +5 -5
- package/dist/entries/studio.d.cts +3 -3
- package/dist/entries/studio.d.ts +3 -3
- package/dist/entries/studio.js +2 -2
- package/dist/entries/templates.d.cts +1 -1
- package/dist/entries/templates.d.ts +1 -1
- package/dist/entries/trash.d.cts +1 -1
- package/dist/entries/trash.d.ts +1 -1
- package/dist/entries/trends.cjs +2 -2
- package/dist/entries/trends.d.cts +37 -17
- package/dist/entries/trends.d.ts +37 -17
- package/dist/entries/trends.js +1 -1
- package/dist/entries/tutorials.d.cts +1 -1
- package/dist/entries/tutorials.d.ts +1 -1
- package/dist/entries/uploads.d.cts +1 -1
- package/dist/entries/uploads.d.ts +1 -1
- package/dist/entries/user-settings.d.cts +1 -1
- package/dist/entries/user-settings.d.ts +1 -1
- package/dist/entries/video-pro.d.cts +1 -1
- package/dist/entries/video-pro.d.ts +1 -1
- package/dist/entries/voices.d.cts +1 -1
- package/dist/entries/voices.d.ts +1 -1
- package/dist/entries/webhooks.d.cts +3 -3
- package/dist/entries/webhooks.d.ts +3 -3
- package/dist/entries/workflows.d.cts +1 -1
- package/dist/entries/workflows.d.ts +1 -1
- package/dist/entries/workspaces.d.cts +1 -1
- package/dist/entries/workspaces.d.ts +1 -1
- package/dist/index.cjs +90 -82
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +16 -16
- package/dist/{nodes-DuXF6XVv.d.ts → nodes-1u7MPrD5.d.ts} +11 -1
- package/dist/{nodes-bY51Z1Os.d.cts → nodes-BZavad1T.d.cts} +11 -1
- package/dist/{studio-productions-r2-VZsKj.d.cts → studio-productions-CMiS827q.d.cts} +1 -1
- package/dist/{studio-productions-DtTE8mdl.d.ts → studio-productions-DkI51Z9M.d.ts} +1 -1
- package/dist/{webhooks-BJawEIz8.d.ts → webhooks-C2DZTK4n.d.ts} +1 -1
- package/dist/{webhooks-Dn_DtNTD.d.cts → webhooks-tg3VN39V.d.cts} +1 -1
- package/package.json +3 -3
- package/dist/chunk-22P4X3N5.cjs.map +0 -1
- package/dist/chunk-47ULSVO2.js.map +0 -1
- package/dist/chunk-AN36M6HO.js.map +0 -1
- package/dist/chunk-BQAW4RX2.js.map +0 -1
- package/dist/chunk-DAONQZPI.cjs.map +0 -1
- package/dist/chunk-FM2KM5TY.cjs.map +0 -1
- package/dist/chunk-HAVIVOLO.js.map +0 -1
- package/dist/chunk-HK5FSTKG.cjs.map +0 -1
- package/dist/chunk-HWSYNUSC.js.map +0 -1
- package/dist/chunk-I3MEBVLP.js.map +0 -1
- package/dist/chunk-JOVJAKBT.cjs.map +0 -1
- package/dist/chunk-JVDUGVLX.cjs.map +0 -1
- package/dist/chunk-L6T44A3G.js.map +0 -1
- package/dist/chunk-O74MSMFH.cjs.map +0 -1
- package/dist/chunk-P6AM42UB.cjs.map +0 -1
- package/dist/chunk-PBFODIFT.js.map +0 -1
- package/dist/chunk-QGVOAPUI.js.map +0 -1
- package/dist/chunk-THLTFB6I.js.map +0 -1
- package/dist/chunk-VHTDOACT.cjs.map +0 -1
- package/dist/chunk-W5RMFTPA.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/objects.ts"],"names":[],"mappings":"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","file":"chunk-GIQDM2MH.js","sourcesContent":["import type { ObjectAspectRatio, ObjectAssetType, ObjectAttachColumn } from \"@nodaro/shared/entities\"\nexport type { ObjectAssetType, ObjectAttachColumn, ObjectAspectRatio } from \"@nodaro/shared/entities\"\nexport { OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, OBJECT_ASPECT_OPTIONS, OBJECT_ASPECT_DEFAULTS } from \"@nodaro/shared/entities\"\nimport type { NodaroClientCore } from \"../core.js\"\nimport type { SetKeeperCatalogInput, SetKeeperCatalogResult } from \"./keepers.js\"\nimport type { GenerationSessionParams } from \"./nodes.js\"\n\n/**\n * Re-export the shared `ObjectAssetType` / `ObjectAttachColumn` unions and\n * their runtime tuples so SDK consumers don't have to add `@nodaro/shared` as\n * a second dependency just to typecheck the `assetType` / `attachToColumn`\n * fields. Single source of truth lives in `@nodaro/shared/entity-prompts`.\n *\n * `ObjectAspectRatio` is re-exported alongside them — `generateMotion`'s\n * `aspectRatio` field is the 5-value object enum (1:1 / 3:4 / 16:9 / 9:16 /\n * 4:3) from `@nodaro/shared/object-aspect-defaults`. Distinct from\n * `CharacterAspectRatio` because objects support an extra 4:3 framing for\n * product-showcase shots.\n */\n\n/**\n * Reference-photo kind discriminator — the mood-board roles a user can attach\n * to an object. Mirrors the `reference_photos.kind` field accepted by\n * `backend/src/routes/objects.ts` (the route accepts open strings; this SDK\n * type narrows to the 6 canonical roles surfaced by the Studio). `other` is\n * the free-form bucket.\n */\nexport type ObjectReferencePhotoKind =\n | \"front\"\n | \"side\"\n | \"detail\"\n | \"context\"\n | \"moodBoard\"\n | \"other\"\n\nexport interface ObjectReferencePhoto {\n url: string\n kind: ObjectReferencePhotoKind\n}\n\n/**\n * An object record returned by Nodaro's REST API. Mirrors the camelCase\n * shape produced by `backend/src/routes/objects.ts::toCamel()`.\n *\n * Asset buckets (`angles`, `materials`, `variations`, `motionClips`) are\n * independent JSONB arrays keyed by a human-readable variant name (e.g.\n * `\"front\"`, `\"wood\"`, `\"weathered\"`). Each entry's `url` points at an\n * R2-hosted asset.\n *\n * Identity-foundation fields:\n * - `referencePhotos` — caller-supplied mood-board refs (cap 20). Objects\n * do NOT carry a `piiConsentAt` field (location Phase 2 #7 only).\n * - `canonicalDescription` — ~80–120-word LLM-authored visual caption,\n * populated by `approveMainImage()` / `recaption()`. The wire still sends\n * `\"\"` on caption sub-failure (the breaking wire change is deferred to a\n * major bump), but `get()` normalizes `\"\"` → `null` so consumers see the\n * same `string | null` semantics as characters.\n * - `styleLock` — whether asset gens should anchor to the canonical style\n * captured at approval time. Defaults to `true` on new rows.\n *\n * `Object` shadows the JS global, which TypeScript handles cleanly via\n * local-scope resolution. Consumers who need both can alias as\n * `import type { Object as NodaroObject } from \"@nodaro/sdk\"`.\n */\nexport interface Object {\n id: string\n userId: string\n nodeId: string\n projectId: string | null\n name: string\n description: string | null\n category: string | null\n style: string | null\n sourceImageUrl: string | null\n /** MODEL_CATALOG image-model id the main image was generated with (or `null`).\n * Set on create + editable via the update route. */\n imageProvider: string | null\n angles: Array<{ name: string; url: string }>\n materials: Array<{ name: string; url: string }>\n variations: Array<{ name: string; url: string }>\n motionClips: Array<{ name: string; url: string }>\n /** Named Product Boards — dense reference sheets, one per variant/colorway\n * (the `generate-image/product-board` factory preset rendered from the\n * object's images). A first-class bucket: community publish snapshots it\n * and clone hands the consumer their own copy to extend. Defaults to `[]`.\n * `type` marks an image-collage `\"identity\"` sheet vs a plain `\"looks\"`\n * board; `sourceImages` are the R2 URLs it was collaged from. Both optional\n * + backward-compatible (legacy boards have neither). */\n boards?: Array<{ name: string; url: string; type?: \"looks\" | \"identity\"; sourceImages?: string[] }> | null\n referencePhotos: ObjectReferencePhoto[]\n /** `null` when no caption is set (or the LLM caption sub-failed) — the wire\n * sends `\"\"`, normalized to `null` in `get()` to match character semantics. */\n canonicalDescription: string | null\n styleLock: boolean\n /** The user's chosen DEFAULT asset take per variant (Studio version history).\n * OPAQUE map: key `\"<bucket>:<variant>\"` (e.g. `\"angles:front\"`) → the chosen\n * asset URL (one already present in that bucket). Stored verbatim — keys are\n * NOT normalized; soft-capped server-side at 200 keys / 2048-char values\n * (overflow dropped silently). Defaults to `{}`. */\n selectedAssetByVariant?: Record<string, string> | null\n /** Nodaro Keepers: whether this row is on the shared shelf (`client.keepers`).\n * Admin-set through `setCatalog`; `false` on everyone else's rows and on\n * every copy. Optional on the read surface for older servers. */\n catalog?: boolean\n /** The shelf order (lowest first); `0` when never set. */\n catalogSort?: number\n /** The shelf heading, or `null`. */\n catalogCategory?: string | null\n deletedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\n/**\n * GET /v1/objects/:id may append a `pendingJobs` bucket the studio uses to\n * rehydrate spinners after a reload. Optional on the SDK surface — it doesn't\n * appear on `list()` rows.\n */\nexport interface ObjectDetail extends Object {\n pendingJobs?: Array<{\n jobId: string\n assetType: string\n name: string\n status: string\n }>\n}\n\n/**\n * Body for `client.objects.create()`. Mirrors the INSERT branch of\n * `upsertObjectBody` in `backend/src/routes/objects.ts`. `name` + `nodeId`\n * are required on create.\n */\nexport interface CreateObjectInput {\n nodeId: string\n name: string\n description?: string\n category?: ObjectCategory\n style?: string\n workflowId?: string\n projectId?: string\n sourceImageUrl?: string\n /** Persistent image-model id (a MODEL_CATALOG image model). Validated\n * server-side — unknown / non-image / \"\" is stored as `null`. */\n imageProvider?: string | null\n referencePhotos?: ObjectReferencePhoto[]\n canonicalDescription?: string\n styleLock?: boolean\n /** The user's chosen DEFAULT asset take per variant. OPAQUE\n * `\"<bucket>:<variant>\"` → chosen-URL map; a write REPLACES the whole map.\n * Keys stored verbatim; soft-capped server-side at 200 keys / 2048-char values. */\n selectedAssetByVariant?: Record<string, string>\n}\n\n/**\n * The 10-value Object category enum. Mirrors the literal accepted by\n * `POST /v1/generate-object` and surfaced in the Object Studio category\n * picker. Distinct from location's geography-based set.\n */\nexport type ObjectCategory =\n | \"furniture\"\n | \"vehicle\"\n | \"weapon\"\n | \"food\"\n | \"clothing\"\n | \"electronics\"\n | \"nature\"\n | \"tool\"\n | \"animal\"\n | \"other\"\n\n/**\n * Body for `client.objects.update()`. Mirrors the UPDATE branch of\n * `upsertObjectBody` in `backend/src/routes/objects.ts`.\n *\n * Worker-owned asset buckets (`angles` / `materials` / `variations` /\n * `motionClips`) are deliberately omitted — the route drops them on UPDATE\n * so a Studio auto-save with a stale snapshot cannot clobber the worker's\n * atomic `append_object_asset()` writes.\n *\n * `expectedUpdatedAt` is the optimistic-concurrency token: when present, the\n * UPDATE only succeeds if the row's `updated_at` still matches; on mismatch\n * the route returns 409 so the studio can re-fetch + merge.\n */\nexport interface UpdateObjectInput {\n name?: string\n description?: string\n category?: ObjectCategory\n style?: string\n sourceImageUrl?: string\n /** Persistent image-model id (a MODEL_CATALOG image model). Validated\n * server-side — unknown / non-image / \"\" is stored as `null`. */\n imageProvider?: string | null\n referencePhotos?: ObjectReferencePhoto[]\n canonicalDescription?: string\n styleLock?: boolean\n /** The user's chosen DEFAULT asset take per variant. OPAQUE\n * `\"<bucket>:<variant>\"` → chosen-URL map; a write REPLACES the whole map\n * (omit to leave untouched). Keys stored verbatim; soft-capped server-side\n * at 200 keys / 2048-char values. */\n selectedAssetByVariant?: Record<string, string>\n /** Named Product Boards (see `Object.boards`) — whole-array replace,\n * USER-owned (unlike the worker-owned buckets it flows through UPDATE).\n * Server caps: 24 boards, 200-char names, 30 sourceImages per board. */\n boards?: Array<{ name: string; url: string; type?: \"looks\" | \"identity\"; sourceImages?: string[] }>\n expectedUpdatedAt?: string\n}\n\nexport interface UpdateObjectResult {\n id: string\n updatedAt: string\n}\n\n/**\n * Combined create + update body (parameter for both branches). Exported for\n * callers that want to drive a single `upsert` flow without picking between\n * `Create*` and `Update*`. Mirrors the `upsertObjectBody` Zod schema in\n * `backend/src/routes/objects.ts`. `nodeId` + `name` are required on INSERT;\n * `id` flips the route into UPDATE mode.\n */\nexport interface UpsertObjectInput extends CreateObjectInput {\n id?: string\n expectedUpdatedAt?: string\n}\n\nexport type UpsertObjectResult = { id: string } | UpdateObjectResult\n\nexport interface ListObjectsParams {\n /** When true, return archived objects instead of active ones. */\n archived?: boolean\n /** Optional project filter — server-scoped to the caller's user. */\n projectId?: string\n /**\n * Search words: only the objects whose name or description contains every\n * word (split on spaces, the first 5), in any order, ignoring case. Each\n * word is matched as written (`%`, `_` and `*` are not wildcards;\n * punctuation is kept); blank means no search; up to 200 characters.\n * Combines with the other filters and with `cursor` paging.\n */\n q?: string\n /**\n * Max rows to return (cap 500). OPT-IN: omitted, the server returns the\n * full legacy listing with no `nextCursor`; supplied, the response is one\n * page plus `nextCursor` — keep passing it back until it is `null`.\n */\n limit?: number\n /** Opaque cursor from a prior page's `nextCursor` (fetches the next page). */\n cursor?: string\n}\n\n/**\n * Input for `client.objects.generate()` — fires the\n * `POST /v1/generate-object` route. Produces 1–10 candidate\n * main images; each lands as one `jobs` row in `pending` state and is then\n * enqueued for the worker.\n *\n * When `attachToObjectId` is set AND `count === 1`, the worker writes the\n * resulting URL directly to `objects.source_image_url` on completion —\n * caller doesn't need a separate `approveMainImage` call. Multi-candidate\n * batches MUST go through explicit approval so the user picks the winner.\n *\n * `seedPromptHint` (Pass 7 F-77) flows the parameter-picker's prompt fragment\n * through to the worker so a catalog selection (e.g. \"antique brass lantern\")\n * gets appended to the generated prompt context.\n */\nexport interface GenerateObjectInput extends GenerationSessionParams {\n name: string\n description?: string\n userPrompt?: string\n category?: ObjectCategory\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n sourceImageUrl?: string\n provider?: string\n /** Number of candidate images to generate (1–10; server-validated). */\n count?: number\n /** Auto-attach the result to this object row (single-candidate only). */\n attachToObjectId?: string\n /** Parameter-picker prompt-fragment pass-through. */\n seedPromptHint?: string\n /** Optional name to set on the attached row alongside the main image. */\n attachName?: string\n /** Optimistic-concurrency token for the single-candidate auto-attach path. */\n expectedUpdatedAt?: string\n}\n\n/**\n * `generate()` response — `jobIds` is ALWAYS present (the harmonized contract,\n * matching characters). `jobId` is a deprecated back-compat alias populated only\n * on `count === 1`; prefer `jobIds`. (Will be removed on the next major.)\n */\nexport interface GenerateObjectResult {\n jobIds: string[]\n /** @deprecated count===1 back-compat alias — use `jobIds`. */\n jobId?: string\n}\n\n/**\n * Input for `client.objects.generateAsset()` — fires the\n * `POST /v1/generate-object-asset` route. Produces a single\n * angles / materials / variations / custom variant.\n *\n * When all three studio-path fields are set (`attachToObjectId` +\n * `attachToColumn` + `attachName`), the worker appends\n * `{ name: attachName, url: <result> }` to the named JSONB array column on\n * the user's object row on completion. `attachToColumn` is REQUIRED for\n * `assetType === \"custom\"` — the worker can't infer the bucket from the\n * asset type.\n */\nexport interface GenerateObjectAssetInput extends GenerationSessionParams {\n assetType: ObjectAssetType\n variant: string\n name: string\n description?: string\n userPrompt?: string\n category?: string\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n sourceImageUrl?: string\n provider?: string\n attachToObjectId?: string\n attachToColumn?: ObjectAttachColumn\n attachName?: string\n /** Parameter-picker prompt-fragment pass-through (Pass 7 F-77). */\n seedPromptHint?: string\n}\n\nexport interface GenerateObjectAssetResult {\n jobId: string\n}\n\n/**\n * Input for `client.objects.generateMotion()` — fires the\n * `POST /v1/generate-object-motion` route. Produces a single motion clip\n * (rotation, orbit, hover, drift, etc.) animated FROM a static product-shot\n * image.\n *\n * Mirrors `client.locations.generateMotion()` minus the location-specific\n * atmospheric fields. The route hardcodes the attach column to `motion_clips`\n * — callers supply `attachToObjectId` + `attachName` only.\n *\n * `sourceImageUrl` is REQUIRED — image-to-video needs a source frame and the\n * route has no fallback (no `source_image_url` column to pull from on the\n * objects row at this point in the flow; the studio path supplies the\n * canonical product-shot URL explicitly).\n *\n * Object-specific defaults vs location:\n * - `provider` defaults to `\"kling-turbo\"` (not location's `\"kling\"`)\n * - `aspectRatio` defaults to `\"1:1\"` server-side via\n * `resolveObjectAspectRatio({ assetType: \"motion\" })` — objects are\n * product-showcase framing, not cinematic establishing shots.\n *\n * When the studio path is set (`attachToObjectId` + `attachName`), the\n * worker appends `{ name: attachName, url: <result> }` to the object row's\n * `motion_clips` JSONB column on completion.\n */\nexport interface GenerateObjectMotionInput extends GenerationSessionParams {\n motionPrompt: string\n sourceImageUrl: string\n provider?: string\n name: string\n /** Source clip URL — when set, worker routes to video-to-video refine. */\n refineFromVideoUrl?: string\n category?: string\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n canonicalDescription?: string\n /** Parameter-picker prompt-fragment pass-through (Pass 7 F-77). */\n seedPromptHint?: string\n attachToObjectId?: string\n attachName?: string\n /**\n * Optional aspect ratio override. Defaults to 1:1 server-side. One of the\n * 5-value `ObjectAspectRatio` union (1:1 / 3:4 / 16:9 / 9:16 / 4:3) —\n * objects have their own enum (with 4:3 added) vs the character set.\n */\n aspectRatio?: ObjectAspectRatio\n /**\n * Optional clip duration in seconds. Validated server-side against the chosen\n * provider's allowed durations (e.g. kling 5/10, wan-i2v 5/10/15); omitted →\n * the model's own default (no behavior change). Mirrors generate-video's\n * per-model i2v duration lever.\n */\n duration?: number\n}\n\nexport interface GenerateObjectMotionResult {\n jobId: string\n}\n\nexport interface ApproveObjectMainImageResult {\n sourceImageUrl: string\n /**\n * LLM-authored caption. `null` when the LLM caption sub-failed — the wire\n * sends `\"\"`, normalized to `null` here so consumers see the same\n * `string | null` semantics as characters. The main image is still set; call\n * `recaption()` to retry.\n */\n canonicalDescription: string | null\n}\n\nexport interface RecaptionObjectResult {\n canonicalDescription: string\n}\n\nexport class ObjectsResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * List the caller's objects. By default returns active objects only;\n * pass `archived: true` to fetch soft-deleted rows for an \"archive\" view.\n * Optional `projectId` scopes the result to a single project; `q` keeps the\n * objects whose name or description contains it.\n */\n list(params: ListObjectsParams = {}): Promise<{ objects: Object[]; nextCursor?: string | null }> {\n const query: Record<string, string | undefined> = {}\n if (params.archived) query.archived = \"true\"\n if (params.projectId) query.projectId = params.projectId\n if (params.q) query.q = params.q\n if (params.limit !== undefined) query.limit = String(params.limit)\n if (params.cursor) query.cursor = params.cursor\n return this.client.request(\"GET\", \"/v1/objects\", { query })\n }\n\n /**\n * Convenience wrapper for `list({ archived: true })`. Returns soft-deleted\n * rows so callers can drive a UI \"Archived\" tab without re-encoding the\n * query param.\n *\n * `archived` is omitted from the param type — it's always set to `true` here.\n */\n listArchived(params: Omit<ListObjectsParams, \"archived\"> = {}): Promise<{ objects: Object[]; nextCursor?: string | null }> {\n return this.list({ ...params, archived: true })\n }\n\n /**\n * Fetch a single object including in-flight asset job state. Soft-deleted\n * (archived) rows are NOT returned by id — the route enforces\n * `deleted_at IS NULL` so archived objects 404 (uniform Pass 10 F-90b\n * \"not_found\" — does not leak the deleted vs non-existent distinction).\n */\n async get(id: string): Promise<ObjectDetail> {\n const res = await this.client.request<ObjectDetail>(\n \"GET\",\n `/v1/objects/${encodeURIComponent(id)}`,\n )\n // Normalize the wire `\"\"` caption (DB null / LLM sub-failure) → null so\n // consumers see the same `string | null` semantics as characters. New\n // object — never mutate the response.\n return { ...res, canonicalDescription: res.canonicalDescription || null }\n }\n\n /**\n * Create a new object. `name` + `nodeId` are required — the route 400s\n * otherwise. Returns the new row's id.\n *\n * Note: the underlying route is the same `POST /v1/objects` upsert that\n * powers `update()`. This convenience wrapper enforces the INSERT-required\n * fields at the type level and never sends an `id`.\n */\n create(data: CreateObjectInput): Promise<{ id: string }> {\n return this.client.request(\"POST\", \"/v1/objects\", { body: data })\n }\n\n /**\n * Update an object. Only the fields you pass are written — undefined keys\n * are NOT touched on the row. Worker-owned asset buckets are intentionally\n * not exposed on this surface (see `UpdateObjectInput` for the rationale).\n *\n * Optimistic-concurrency: pass `expectedUpdatedAt` to require the row's\n * `updated_at` still matches; on mismatch the route returns 409\n * `concurrent_modification` carrying the fresh `updatedAt`. The SDK\n * surfaces that as a generic `NodaroError` with the same code (per Phase\n * E1 calibration finding — error centralization in `throwApiError`).\n */\n update(id: string, data: UpdateObjectInput): Promise<UpdateObjectResult> {\n return this.client.request(\"POST\", \"/v1/objects\", {\n body: { id, ...data },\n })\n }\n\n /**\n * Soft-delete (archive) an object. The row is hidden from `list()` by\n * default but recoverable via `restore(id)` or visible under\n * `listArchived()`. Idempotent — repeating a delete on an already-archived\n * row is a no-op.\n */\n delete(id: string): Promise<{ success: true; archived: true }> {\n return this.client.request(\"DELETE\", `/v1/objects/${encodeURIComponent(id)}`)\n }\n\n /**\n * Hard-delete (permanent) an object — the row + every R2 asset it\n * references. Archived rows ONLY: active objects return 400 `not_archived`.\n * Call `delete()` first to archive, then `permanentDelete()` to destroy.\n *\n * Mirrors the `app_runs` permanent-delete pattern (archive-first) so a\n * stray SDK / curl caller cannot bypass the studio's archive-first UI\n * flow.\n */\n permanentDelete(id: string): Promise<{ success: true; permanent: true }> {\n return this.client.request(\"DELETE\", `/v1/objects/${encodeURIComponent(id)}`, {\n query: { permanent: \"true\" },\n })\n }\n\n /**\n * Un-archive an object. If the original name now collides (case-\n * insensitive) with an active row, the server auto-suffixes \"(restored)\"\n * and returns the effective name.\n */\n restore(id: string): Promise<{ id: string; name: string }> {\n return this.client.request(\"POST\", `/v1/objects/${encodeURIComponent(id)}/restore`)\n }\n\n /**\n * Admin only: put one of your own objects on the shared Nodaro Keepers\n * shelf (`client.keepers.catalog()`), or take it off. A first-party session\n * or your personal token; `forbidden` for anyone who is not a platform\n * admin, `not_found` for a row that is not yours.\n */\n setCatalog(id: string, input: SetKeeperCatalogInput): Promise<SetKeeperCatalogResult> {\n return this.client.request(\"PUT\", `/v1/objects/${encodeURIComponent(id)}/catalog`, { body: input })\n }\n\n /**\n * Fire `POST /v1/generate-object` to produce one or more candidate main\n * images. With `count > 1`, all jobs are reserved up-front before any\n * is enqueued — mid-batch failures roll back atomically.\n *\n * When `attachToObjectId` is set AND `count === 1`, the worker writes\n * the result directly to the row's `source_image_url`; otherwise you must\n * call `approveMainImage()` after picking a candidate.\n */\n async generate(data: GenerateObjectInput): Promise<GenerateObjectResult> {\n const res = await this.client.request<{ jobId?: string; jobIds?: string[] }>(\n \"POST\", \"/v1/generate-object\", { body: data },\n )\n // Tolerate the legacy `{ jobId }`-only shape (older server): synthesize jobIds.\n const jobIds = res.jobIds ?? (res.jobId ? [res.jobId] : [])\n return res.jobId ? { jobIds, jobId: res.jobId } : { jobIds }\n }\n\n /**\n * Fire `POST /v1/generate-object-asset` to produce a single variant.\n * When the studio path is set (`attachToObjectId` + `attachToColumn` +\n * `attachName`), the worker appends `{ name: attachName, url: <result> }`\n * to the named JSONB array column on completion.\n *\n * Note: `attachToColumn` is REQUIRED for `assetType === \"custom\"` — the\n * worker can't infer the bucket from the asset type. For canonical asset\n * types (`angles` / `materials` / `variations` / `motion`), the column is\n * derived automatically by the route.\n */\n generateAsset(\n data: GenerateObjectAssetInput,\n ): Promise<GenerateObjectAssetResult> {\n return this.client.request(\"POST\", \"/v1/generate-object-asset\", { body: data })\n }\n\n /**\n * Fire `POST /v1/generate-object-motion` to animate the object's main\n * image into a motion clip. Image-to-video, single clip per call; the\n * attach column is hardcoded to `motion_clips` server-side (objects have a\n * single motion bucket so the caller doesn't supply `attachToColumn`).\n * When the studio path is set (`attachToObjectId` + `attachName`), the\n * worker appends `{ name: attachName, url: <result> }` to the row's\n * `motion_clips` column on completion.\n *\n * Defaults: `provider` → `\"kling-turbo\"`, `aspectRatio` → `\"1:1\"` (set\n * server-side via `resolveObjectAspectRatio({ assetType: \"motion\" })`).\n */\n generateMotion(\n data: GenerateObjectMotionInput,\n ): Promise<GenerateObjectMotionResult> {\n return this.client.request(\"POST\", \"/v1/generate-object-motion\", { body: data })\n }\n\n /**\n * Approve a completed `generate-object` job as the object's main image.\n * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)\n * inline. Returns the new main-image URL plus the caption.\n *\n * Caption-failure semantics: the route still sends `\"\"` on LLM sub-failure,\n * but the SDK normalizes `\"\"` → `null` here so `canonicalDescription` carries\n * the same `string | null` semantics as characters. The main image is still\n * set; call `recaption()` to retry.\n *\n * Optimistic-concurrency: pass `expectedUpdatedAt` to gate the update on\n * the row's current `updated_at`; on mismatch the route returns 409\n * `concurrent_modification` carrying the fresh token.\n */\n async approveMainImage(\n id: string,\n candidateJobId: string,\n expectedUpdatedAt?: string,\n ): Promise<ApproveObjectMainImageResult> {\n const res = await this.client.request<{ sourceImageUrl: string; canonicalDescription: string | null }>(\n \"POST\",\n `/v1/objects/${encodeURIComponent(id)}/approve-main-image`,\n { body: { candidateJobId, expectedUpdatedAt } },\n )\n // Normalize the wire `\"\"` (LLM sub-failure) → null; build a new object\n // rather than mutating the response.\n return { sourceImageUrl: res.sourceImageUrl, canonicalDescription: res.canonicalDescription || null }\n }\n\n /**\n * Re-fire the LLM caption against the object's current main image. 502s\n * on LLM failure (unlike `approveMainImage` which preserves the side-effect\n * and returns \"\"); returns 400 `main_image_required` if no main image is\n * set yet.\n *\n * The route is a pure idempotent retry — it does NOT accept an\n * `expectedUpdatedAt` token (per Phase E1 calibration finding: backend\n * route is idempotent retry, not gated on optimistic-concurrency).\n */\n recaption(id: string): Promise<RecaptionObjectResult> {\n return this.client.request(\n \"POST\",\n `/v1/objects/${encodeURIComponent(id)}/llm-caption`,\n )\n }\n}\n"]}
|
|
@@ -59,5 +59,5 @@ var CastSwapResource = class {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
exports.CastSwapResource = CastSwapResource;
|
|
62
|
-
//# sourceMappingURL=chunk-
|
|
63
|
-
//# sourceMappingURL=chunk-
|
|
62
|
+
//# sourceMappingURL=chunk-GJH73EGF.cjs.map
|
|
63
|
+
//# sourceMappingURL=chunk-GJH73EGF.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resources/cast-swap.ts"],"names":["nodaroMotionEngineFrom"],"mappings":";;;;;AAoeO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,GAAA,CAAI,QAAwB,OAAA,EAA6E;AACvG,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,eAAA,EAAiB;AAAA,MAClD,IAAA,EAAM,MAAA;AAAA,MACN,GAAI,OAAA,EAAS,cAAA,GAAiB,EAAE,OAAA,EAAS,EAAE,iBAAA,EAAmB,OAAA,CAAQ,cAAA,EAAe,EAAE,GAAI;AAAC,KAC7F,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAS,MAAA,EAAmD;AAChE,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAA0B,QAAQ,wBAAA,EAA0B,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAE5G,IAAA,MAAM,MAAA,GAASA,6BAAA,CAAuB,KAAA,EAAO,MAAM,CAAA;AACnD,IAAA,OAAO,MAAA,IAAU,WAAW,KAAA,CAAM,MAAA,GAAS,EAAE,GAAG,KAAA,EAAO,QAAO,GAAI,KAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,oBAAoB,KAAA,EAAqD;AACvE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,sBAAA,CAAA,EAA0B,EAAE,IAAA,EAAM,IAAI,CAAA;AAAA,EACrH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAA,CAAY,KAAA,EAAe,MAAA,GAAoC,EAAC,EAAuC;AACrG,IAAA,MAAM,IAAA,GAAO,OAAO,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU,GAAI,EAAC;AACjF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,aAAA,CAAA,EAAiB,EAAE,IAAA,EAAM,CAAA;AAAA,EACxG;AACF","file":"chunk-65VIIZEF.cjs","sourcesContent":["import { nodaroMotionEngineFrom } from \"@nodaro/shared/models\"\nimport type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Nodaro Motion (the `castSwap` resource; routes `/v1/cast-swap`) — replace\n * the people, pets, products and/or the location in a short video with your\n * own references, keeping its motion, framing, timing and sound (the clip's\n * audio is kept, and the result is the clip's length).\n *\n * Before the video, each person, pet and product role's photos are turned\n * into one clean reference picture by an image model. This costs extra\n * credits (`breakdown.references` in the estimate), charged when it runs, even\n * if the video then fails; it adds about a minute, falls back to your own\n * photos if it fails, and is turned off with `prepareReferences: false`.\n * Locations are not prepared.\n *\n * Engines: a run is made on Nodaro Motion Prism (`engine` left out, or\n * `\"motion-prism\"`) or Nodaro Motion Pulse (`\"motion-pulse\"`). Pulse renders 720p\n * (its default) or 1080p and has no draft; it makes a new take guided by the\n * clip and pictures, so its Full Quality is a new take at 1080p rather than\n * the same take re-rendered (`CastSwapFullQualityEstimate.kind`).\n *\n * How the clip is prepared for the video model (for one, whether faces are\n * hidden first, and whether a refused clip is retried) is set by Nodaro for\n * each engine; a run cannot change it. `faceMasking` is no longer read\n * (deprecated: accepted and ignored).\n *\n * Cloud edition only: `/v1/cast-swap` is served by the cloud plugin and 404s\n * on self-hosted installs. `run()` answers 202 with a job id; follow it with\n * `client.jobs.get(jobId)` / `client.jobs.getStatus(jobId)` like any other job.\n *\n * Repeats: pass `{ idempotencyKey }` to `run()` and it is sent as the\n * `Idempotency-Key` header. A repeat with the same key within the credit\n * guard's dedup window (about 10 s) answers 200 `{ jobId, deduped: true }` with\n * an `X-Dedup-Hit` header; a later one answers 202 with the first run's\n * `jobId`. Nothing new is started or charged.\n *\n * Refusals (thrown as a `NodaroError` subclass; body `{ error: { code, message } }`), before\n * anything is charged: 400 `validation_error` (the body: no role with images,\n * no reference and no `prePrompt` or `postPrompt`, more roles of a kind\n * than allowed, more than 30 images in all, `draft: true` above 480p, a\n * `prePrompt` or `postPrompt` over 4,000 characters); on Nodaro Motion Pulse,\n * `draft_unsupported` (`draft: true`), `resolution_unsupported` (480p),\n * `output_format_unsupported` (a MOV edit output) and `too_many_images` (more\n * than 10 images in the run, across every role and fixed reference);\n * `raw_reference_token` (also in a reference's `line`),\n * `invalid_role_mention` (also any `{role:N}` in a reference's `line`),\n * `unsafe_url`, `video_unreadable`, `clip_out_of_range` (4–30 s),\n * `preview_out_of_range`, `no_roles_in_preview` (a preview with every role\n * `inPreview: false`, always refused even with a prompt, or with no role kept\n * in it that has images and no `prePrompt` or `postPrompt`), `prompt_too_long`\n * (the prompt would build too long: a `{role:N}` reads as the role's name when\n * it sends no images; Nodaro Motion Pulse's cap is 8,000 characters); 401; 402 `insufficient_credits` (`run()` only); 404\n * (a `sessionId` you may not use, `run()` only); 422 `job_blocked` (`run()`\n * only); 503 `host_too_old` (both); 503 `estimate_unavailable` (`estimate()`\n * only).\n */\n\n/**\n * The engine a Nodaro Motion run is made on, by its public id. Left out =\n * `\"motion-prism\"`.\n *\n * - `\"motion-prism\"` (Nodaro Motion Prism): 480p (the default, a draft unless\n * `draft: false`), 720p or 1080p; Full Quality re-renders a draft's own take\n * at 1080p.\n * - `\"motion-pulse\"` (Nodaro Motion Pulse): 720p (the default) or 1080p, never a\n * draft (`draft: true` answers 400 `draft_unsupported`); Full Quality makes a\n * new take at 1080p from a completed 720p run's inputs. A preview is still\n * 4 s from `previewStart`.\n */\nexport type CastSwapEngine = \"motion-prism\" | \"motion-pulse\"\n\n/**\n * The engine ids an older client sent: the earlier public ids (`\"motion-pro\"`\n * = `\"motion-prism\"`, `\"motion-lite\"` = `\"motion-pulse\"`) and the internal\n * ones (`\"seedance-2-5\"`, `\"kling-4\"`). Still accepted in a request; never\n * returned.\n * @deprecated use {@link CastSwapEngine}.\n */\nexport type CastSwapEngineLegacyId = \"motion-pro\" | \"motion-lite\" | \"seedance-2-5\" | \"kling-4\"\n\n/**\n * How a run follows its clip. Left out = `\"precise\"`.\n *\n * - `\"precise\"`: follows the clip exactly.\n * - `\"motion\"`: follows the clip's movement and takes the looks from your\n * photos, more freely than `\"precise\"`. Its price may differ from\n * `\"precise\"`'s: the estimate shows the exact price.\n */\nexport type CastSwapStyle = \"precise\" | \"motion\"\n\n/**\n * Where a Nodaro Motion Pulse run cuts the clip to whole seconds (Pulse renders\n * whole seconds; asked for more than the clip, it would stretch the motion):\n * - `\"cut-end\"` (the default): drop the fraction of a second at its end;\n * - `\"cut-start\"`: drop it at its start.\n */\nexport type CastSwapMotionLength = \"cut-end\" | \"cut-start\"\n\n/** @deprecated use {@link CastSwapMotionLength}. */\nexport type CastSwapKlingLength = CastSwapMotionLength\n\n/** Whether a swapped subject takes this trait from the references (`\"new\"`) or keeps the video's (`\"original\"`). */\nexport type CastSwapTraitSource = \"new\" | \"original\"\n\n/**\n * Preview-only settings, on every role kind; a full run (`preview` not `true`)\n * ignores both.\n */\nexport interface CastSwapRolePreviewSettings {\n /** The name used instead of `name` in a preview. Same rules as `name` (1–200 characters). */\n previewName?: string\n /**\n * `false` leaves this role out of the preview: its reference images are not\n * sent, not prepared and not charged, and a `{role:N}` naming it reads as its\n * `previewName`, else its `name`. Default `true`. A preview with every role\n * left out (always refused, even with a prompt), or with no role kept in it\n * that has images and no pre / post prompt, answers 400 `no_roles_in_preview`.\n */\n inPreview?: boolean\n}\n\n/** A person in the video to recast. */\nexport interface CastSwapPersonRole extends CastSwapRolePreviewSettings {\n kind: \"person\"\n /** How the person is told apart in the video, e.g. `\"the woman that attacks\"`. */\n name: string\n /** 0–3 images of ONE person. Empty or `null` keeps the original person. */\n images: string[] | null\n /** Body from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Outfit from the references or the video. Default `\"new\"`. */\n outfit?: CastSwapTraitSource\n /** Hairstyle and haircut from the references or the video. Default `\"new\"`. */\n hair?: CastSwapTraitSource\n}\n\n/** The place the video happens in. */\nexport interface CastSwapLocationRole extends CastSwapRolePreviewSettings {\n kind: \"location\"\n /** How the place is named. Default `\"the setting\"`. */\n name?: string\n /** 0–3 images of ONE place. Empty or `null` keeps the original place. */\n images: string[] | null\n}\n\n/** An animal in the video to recast. */\nexport interface CastSwapPetRole extends CastSwapRolePreviewSettings {\n kind: \"pet\"\n /** How the animal is told apart in the video, e.g. `\"the dog\"`. */\n name: string\n /** 0–3 images of ONE animal. Empty or `null` keeps the original animal. */\n images: string[] | null\n /** Body (shape, size and build) from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Coat (fur, colors and markings) from the references or the video. Default `\"new\"`. */\n coat?: CastSwapTraitSource\n}\n\n/** An object in the video to recast. */\nexport interface CastSwapProductRole extends CastSwapRolePreviewSettings {\n kind: \"product\"\n /** How the object is told apart in the video, e.g. `\"the can\"`. */\n name: string\n /** 0–3 images of ONE product. Empty or `null` keeps the original object. */\n images: string[] | null\n /** Shape and proportions from the references or the video. Default `\"new\"`. */\n shape?: CastSwapTraitSource\n /** Finish (colors, materials, label and markings) from the references or the video. Default `\"new\"`. */\n finish?: CastSwapTraitSource\n}\n\nexport type CastSwapRole = CastSwapPersonRole | CastSwapLocationRole | CastSwapPetRole | CastSwapProductRole\n\n/**\n * A fixed reference: 1–3 images of ONE thing that no role replaces, and the\n * line that says what it is (`\"the glass she drinks from\"`). Sent as given,\n * never prepared; its images count toward the 30.\n */\nexport interface CastSwapReference {\n /** 1–3 http(s) image URLs of one thing. */\n images: string[]\n /**\n * What it is, 1–500 characters. `{image}` in the line stands for this\n * reference's first image (`\"Use {image} for the sky\"`); a line without it\n * gets it appended. A `{role:N}` or a raw `{image:` / `{video:` / `{audio:`\n * token answers 400.\n */\n line: string\n}\n\n/**\n * @deprecated Nodaro sets this per engine; a run's `faceMasking` is ignored.\n */\nexport interface CastSwapFaceMaskingZone {\n leftPct?: number\n rightPct?: number\n topPct?: number\n bottomPct?: number\n}\n\n/**\n * @deprecated Nodaro sets how the clip is prepared for the video model, per\n * engine; a run cannot change it. A `faceMasking` sent is accepted and\n * ignored (no error), so older code keeps working unchanged.\n */\nexport interface CastSwapFaceMasking {\n mode: \"off\" | \"always\" | \"auto\"\n fill?: \"blur\" | \"depth\"\n minFaceHeightPct?: number\n maxFaceHeightPct?: number\n zone?: CastSwapFaceMaskingZone | null\n blurStrengthPct?: number\n threshold?: number\n}\n\n/** The body of `POST /v1/cast-swap` and `POST /v1/cast-swap/estimate`. */\nexport interface CastSwapParams {\n /** The source clip, 4–30 seconds. */\n videoUrl: string\n /**\n * Who and what to swap: at most 6 person roles, 1 location role, 3 pet roles\n * and 3 product roles, with at most 30 images in all. A role with no images\n * is skipped (that subject or place stays as in the video). At least one role\n * with images, or a `prePrompt` or `postPrompt`, is required.\n */\n roles: CastSwapRole[]\n /**\n * Fixed references (at most 5): things the video should show that no role\n * replaces, each with the line that names it. Their images count toward the\n * 30. A reference alone is enough for a run (no role needs images).\n */\n references?: CastSwapReference[]\n /**\n * Your own words placed at the start of the prompt, before the role\n * instructions; at most 4,000 characters. Mention a role as `{role:N}`, as in\n * `postPrompt`; the same 400 refusals apply (an N outside 1..`roles.length`,\n * a raw `{image:` / `{video:` / `{audio:` token).\n */\n prePrompt?: string\n /**\n * Extra instructions in your own words, at most 4,000 characters. Mention a\n * role as `{role:N}`, where N is its 1-based position in `roles`\n * (`{role:1}` is `roles[0]`; empty roles count).\n *\n * The route answers 400, before charging, for an N outside 1..`roles.length`,\n * for a raw `{image:` / `{video:` / `{audio:` token in the pre or post prompt\n * or a role's `name`, for a clip outside 4–30 s, and for a preview past the clip's\n * end (`previewStart + 4` > its length).\n */\n postPrompt?: string\n /** `true` runs on 4 seconds of the clip, starting at `previewStart`: a cheap check of the roles and choices. */\n preview?: boolean\n /** Where the preview starts, in seconds. Default 0. */\n previewStart?: number\n /**\n * The engine (see {@link CastSwapEngine}). Default `\"motion-prism\"`. The job\n * records it in `input_data.engine`, and a completed job's output in its\n * `engine`. The ids an older client sent ({@link CastSwapEngineLegacyId})\n * are still accepted.\n */\n engine?: CastSwapEngine | CastSwapEngineLegacyId\n /**\n * How the run follows the clip (see {@link CastSwapStyle}). Default\n * `\"precise\"`; the job records it in `input_data.style`.\n */\n style?: CastSwapStyle\n /**\n * Nodaro Motion Pulse only (Prism ignores it): which end of the clip is cut to\n * whole seconds (see {@link CastSwapMotionLength}). Default `\"cut-end\"`.\n */\n motionLength?: CastSwapMotionLength\n /** @deprecated use {@link motionLength} (still accepted). */\n klingLength?: CastSwapKlingLength\n /**\n * The output resolution. Nodaro Motion Prism: `\"480p\"` (default), `\"720p\"` or\n * `\"1080p\"`. Nodaro Motion Pulse: `\"720p\"` (default) or `\"1080p\"`; `\"480p\"`\n * answers 400.\n */\n resolution?: \"480p\" | \"720p\" | \"1080p\"\n /**\n * Render as a draft (Nodaro Motion Prism only). Defaults to `true` at 480p and\n * `false` above it; `true` with `\"720p\"` or `\"1080p\"` answers 400 (draft is\n * 480p only). Nodaro Motion Pulse has no draft: `true` answers 400\n * `draft_unsupported`.\n */\n draft?: boolean\n /**\n * Turn each person, pet and product role's photos into one clean reference\n * picture before the video (extra credits, shown in `breakdown.references`;\n * about a minute longer; falls back to your own photos if it fails).\n * Default `true`.\n */\n prepareReferences?: boolean\n /**\n * Ignored: Nodaro sets how the clip is prepared, per engine. Accepted (no\n * error) so older code keeps working.\n * @deprecated leave it out.\n */\n faceMasking?: CastSwapFaceMasking\n /**\n * `\"draft\"` means 480p draft.\n * @deprecated use `resolution` + `draft`.\n */\n quality?: \"draft\"\n /** A generation session to file the result in. */\n sessionId?: string\n /** The client app that sent the run (stored on the job as `input_data.origin`). */\n origin?: string\n}\n\n/** What a run would cost, in credits. */\nexport interface CastSwapEstimate {\n /**\n * The engine the run would use, by its public id (absent from an older\n * server = `\"motion-prism\"`). An id an older server answers is read as the\n * public id it names.\n */\n engine?: CastSwapEngine\n /**\n * What is held when the run starts. The run is charged what it actually\n * costs, which is expected to be `expectedCredits`.\n */\n totalCredits: number\n /**\n * The charge the run is expected to come to. Never above `totalCredits`\n * (on Nodaro Motion Pulse it equals it: Pulse renders exactly the length\n * asked for, so the hold is what it settles at). Absent from an older\n * server: read `totalCredits` then.\n */\n expectedCredits?: number\n /**\n * The parts of the quote, by name, for display only:\n * - `base`: the run itself (its base fee). A server before Cast Swap 0.396.0\n * names it `castSwap` instead: read `base`, else `castSwap`;\n * - `references`: preparing the reference pictures (0 when\n * `prepareReferences` is off or there is nothing to prepare);\n * - `motion`: what the video holds (on Nodaro Motion Pulse, what it costs);\n * - `motionExpected`: what the video is expected to be charged, never above\n * `motion` (Nodaro Motion Prism);\n * - `privacy`: preparing the clip, when the engine's setting does. In both\n * totals when it always runs; outside both when it is the retry\n * (`privacyCredits`).\n *\n * `motion` and `motionExpected` are alternatives, so the parts sum to more\n * than either total: read `totalCredits` and `expectedCredits`, never the\n * sum. Other parts may appear.\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n references: number\n motion?: number\n motionExpected?: number\n privacy?: number\n } & Record<string, number>\n /**\n * The extra credits charged only if the video model refuses the clip and\n * the run is retried (Nodaro's setting for the engine decides whether it\n * does). Not in `totalCredits` or `expectedCredits`; `run()` needs credits\n * for both the hold and this (else 402).\n */\n privacyCredits?: number\n /** @deprecated read {@link privacyCredits} (an older server answered this name). */\n maskingCredits?: number\n /**\n * `true` when the video is made at Auto length (every Nodaro Motion Prism\n * run): the final charge is expected to come out lower than `totalCredits`,\n * at about `expectedCredits`. `false` on Nodaro Motion Pulse.\n */\n settlesLower: boolean\n}\n\n/** Per-call options for {@link CastSwapResource.run}. */\nexport interface CastSwapRunOptions {\n /**\n * Sent as the `Idempotency-Key` header, unchanged (the SDK checks nothing;\n * an empty string sends no header, like no key).\n * The server takes 8–200 characters and answers 400 for any other length.\n * Reuse the same value when retrying the same run: within about 10 s the\n * repeat answers 200 `{ jobId, deduped: true }`, later 202 with the first\n * run's `jobId`. Nothing new is started or charged.\n */\n idempotencyKey?: string\n}\n\n/**\n * What a Full Quality version would be: `\"same-take\"` re-renders a Nodaro\n * Motion Prism draft's own take at 1080p; `\"new-take\"` makes a new Nodaro Motion Pulse take at\n * 1080p from a 720p run's inputs (it will not match the 720p run frame for\n * frame). The 720p run or draft stays either way.\n */\nexport type CastSwapFullQualityKind = \"same-take\" | \"new-take\"\n\n/**\n * What a Full Quality version of a run would cost\n * (`POST /v1/cast-swap/:jobId/full-quality/estimate`): a Nodaro Motion Prism\n * draft, or a completed Nodaro Motion Pulse run at 720p.\n */\nexport interface CastSwapFullQualityEstimate {\n /**\n * Which Full Quality this is ({@link CastSwapFullQualityKind}), so it can\n * be worded right. Absent from an older server: `\"same-take\"`.\n */\n kind?: CastSwapFullQualityKind\n /** The quote in credits: `breakdown.base` plus the 1080p render (same take) or the new take. */\n totalCredits: number\n /**\n * The parts of the quote, by name, for display only: `base` (the Full\n * Quality job's own steps; a server before Cast Swap 0.396.0 names it\n * `castSwap` instead: read `base`, else `castSwap`), and `motionHd` (a same\n * take: the 1080p render, 0 when an earlier try of this draft already\n * finished that render, which is then reused) or `motion` (a new take).\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n motionHd?: number\n motion?: number\n } & Record<string, number>\n /** ISO time until which the run can be finished at Full Quality (7 days after it completed). */\n availableUntil: string\n}\n\n/** Options for {@link CastSwapResource.fullQuality}. */\nexport interface CastSwapFullQualityParams {\n /** A generation session to file the Full Quality result in. */\n sessionId?: string\n}\n\n/** The Full Quality job (`POST /v1/cast-swap/:jobId/full-quality`). */\nexport interface CastSwapFullQualityResult {\n jobId: string\n /** `true` when this run's Full Quality was already running or done: that job is answered, nothing new is started or charged. */\n existing?: boolean\n}\n\n/**\n * The `code` of a Full Quality refusal (`NodaroError.code`), all before\n * anything is charged:\n * - `unauthorized` (401): no authenticated user;\n * - `not_found` (404): not your job, or not a Nodaro Motion run; also a\n * `sessionId` you may not use;\n * - `not_completed` (409): the run has not finished;\n * - `not_a_draft` (409): the run is neither a Nodaro Motion Prism draft nor a\n * Nodaro Motion Pulse run at 720p (a Pulse run at 1080p is already Full Quality);\n * - `draft_expired` (410): more than 7 days after the draft completed, or\n * the draft can no longer be finished at Full Quality;\n * - `full_quality_pending` (409, `details.retryable: true`): not final — an\n * earlier try's 1080p render of this draft is being reviewed, or has not\n * started yet; try again later (once the review ends). The only refusal\n * that ends on its own;\n * - `full_quality_unavailable` (409): final — nothing kept to re-render, no\n * readable completion time, or the 1080p finalize refuses this draft; on\n * the start only, also \"failed too many times\" (every try failed) or no\n * try can be started for this run;\n * - `insufficient_credits` (402), or in a workspace `budget_exceeded`,\n * `member_cap_exceeded` or `user_allowance_exceeded`;\n * - `job_blocked` (422): the request was blocked by the job policy;\n * - `job_read_failed` (503, retryable), `estimate_unavailable` (503, try\n * again shortly), `host_too_old` (503).\n *\n * Open-ended: a code not listed here may still arrive.\n */\nexport type CastSwapFullQualityRefusalCode =\n | \"unauthorized\"\n | \"not_found\"\n | \"not_completed\"\n | \"not_a_draft\"\n | \"draft_expired\"\n | \"full_quality_pending\"\n | \"full_quality_unavailable\"\n | \"insufficient_credits\"\n | \"budget_exceeded\"\n | \"member_cap_exceeded\"\n | \"user_allowance_exceeded\"\n | \"job_blocked\"\n | \"job_read_failed\"\n | \"estimate_unavailable\"\n | \"host_too_old\"\n | (string & {})\n\nexport class CastSwapResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Start a Nodaro Motion run (`POST /v1/cast-swap`, 202 `{ jobId }`). Returns the\n * job to follow. With `options.idempotencyKey` (sent as the\n * `Idempotency-Key` header; 8–200 characters, else 400) a repeat with the\n * same key within about 10 s answers 200 `{ jobId, deduped: true }`, a later\n * one 202 with the first run's `jobId`; nothing new starts.\n */\n run(params: CastSwapParams, options?: CastSwapRunOptions): Promise<{ jobId: string; deduped?: boolean }> {\n return this.client.request(\"POST\", \"/v1/cast-swap\", {\n body: params,\n ...(options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}),\n })\n }\n\n /** Quote a run before starting it (`POST /v1/cast-swap/estimate`); spends nothing. */\n async estimate(params: CastSwapParams): Promise<CastSwapEstimate> {\n const quote = await this.client.request<CastSwapEstimate>(\"POST\", \"/v1/cast-swap/estimate\", { body: params })\n // An older server names the engine by an earlier id: answered as the public id it names.\n const engine = nodaroMotionEngineFrom(quote?.engine)\n return engine && engine !== quote.engine ? { ...quote, engine } : quote\n }\n\n /**\n * Quote finishing a run at Full Quality (`POST\n * /v1/cast-swap/:jobId/full-quality/estimate`); spends nothing. `jobId` is a\n * finished Nodaro Motion Prism DRAFT run, or a finished Nodaro Motion Pulse\n * run at 720p (a Nodaro Motion or trend run); the quote's `kind` says whether it is the same take\n * re-rendered or a new take. The quote\n * does not look for a Full Quality already running: when one is,\n * {@link fullQuality} answers it (`existing: true`) and charges nothing.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQualityEstimate(jobId: string): Promise<CastSwapFullQualityEstimate> {\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality/estimate`, { body: {} })\n }\n\n /**\n * Finish a run at Full Quality (`POST /v1/cast-swap/:jobId/full-quality`):\n * at 1080p, with the clip's audio, as a new job linked to the run — a\n * Nodaro Motion Prism draft's own take re-rendered, or a new Nodaro Motion Pulse take from a\n * 720p run's inputs (the quote's `kind`). SPENDS CREDITS: quote it first with\n * {@link fullQualityEstimate}. Answers 202 `{ jobId }`, or 200\n * `{ jobId, existing: true }` when this run's Full Quality is already\n * running or done (one per run; a failed one may be asked again). Follow\n * the job with `client.jobs.get(jobId)`. No `Idempotency-Key` is taken: the\n * server keys the job by the draft. The new job keeps the draft's origin.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQuality(jobId: string, params: CastSwapFullQualityParams = {}): Promise<CastSwapFullQualityResult> {\n const body = params.sessionId !== undefined ? { sessionId: params.sessionId } : {}\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality`, { body })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/resources/cast-swap.ts"],"names":["nodaroMotionEngineFrom"],"mappings":";;;;;AA8eO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,GAAA,CAAI,QAAwB,OAAA,EAA6E;AACvG,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,eAAA,EAAiB;AAAA,MAClD,IAAA,EAAM,MAAA;AAAA,MACN,GAAI,OAAA,EAAS,cAAA,GAAiB,EAAE,OAAA,EAAS,EAAE,iBAAA,EAAmB,OAAA,CAAQ,cAAA,EAAe,EAAE,GAAI;AAAC,KAC7F,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAS,MAAA,EAAmD;AAChE,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAA0B,QAAQ,wBAAA,EAA0B,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAE5G,IAAA,MAAM,MAAA,GAASA,6BAAA,CAAuB,KAAA,EAAO,MAAM,CAAA;AACnD,IAAA,OAAO,MAAA,IAAU,WAAW,KAAA,CAAM,MAAA,GAAS,EAAE,GAAG,KAAA,EAAO,QAAO,GAAI,KAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,oBAAoB,KAAA,EAAqD;AACvE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,sBAAA,CAAA,EAA0B,EAAE,IAAA,EAAM,IAAI,CAAA;AAAA,EACrH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAA,CAAY,KAAA,EAAe,MAAA,GAAoC,EAAC,EAAuC;AACrG,IAAA,MAAM,IAAA,GAAO,OAAO,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU,GAAI,EAAC;AACjF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,aAAA,CAAA,EAAiB,EAAE,IAAA,EAAM,CAAA;AAAA,EACxG;AACF","file":"chunk-GJH73EGF.cjs","sourcesContent":["import { nodaroMotionEngineFrom } from \"@nodaro/shared/models\"\nimport type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Nodaro Motion (the `castSwap` resource; routes `/v1/cast-swap`) — replace\n * the people, pets, products and/or the location in a short video with your\n * own references, keeping its motion, framing, timing and sound (the clip's\n * audio is kept, and the result is the clip's length).\n *\n * Before the video, each person, pet and product role's photos are turned\n * into one clean reference picture by an image model. This costs extra\n * credits (`breakdown.references` in the estimate), charged when it runs, even\n * if the video then fails; it adds about a minute, falls back to your own\n * photos if it fails, and is turned off with `prepareReferences: false`.\n * Locations are not prepared.\n *\n * Engines: a run is made on Nodaro Motion Prism (`engine` left out, or\n * `\"motion-prism\"`) or Nodaro Motion Pulse (`\"motion-pulse\"`). Pulse renders 720p\n * (its default) or 1080p and has no draft; it makes a new take guided by the\n * clip and pictures, so its Full Quality is a new take at 1080p rather than\n * the same take re-rendered (`CastSwapFullQualityEstimate.kind`).\n *\n * How the clip is prepared for the video model (for one, whether faces are\n * hidden first, and whether a refused clip is retried) is set by Nodaro for\n * each engine; a run cannot change it. `faceMasking` is no longer read\n * (deprecated: accepted and ignored).\n *\n * Cloud edition only: `/v1/cast-swap` is served by the cloud plugin and 404s\n * on self-hosted installs. `run()` answers 202 with a job id; follow it with\n * `client.jobs.get(jobId)` / `client.jobs.getStatus(jobId)` like any other job.\n *\n * Repeats: pass `{ idempotencyKey }` to `run()` and it is sent as the\n * `Idempotency-Key` header. A repeat with the same key within the credit\n * guard's dedup window (about 10 s) answers 200 `{ jobId, deduped: true }` with\n * an `X-Dedup-Hit` header; a later one answers 202 with the first run's\n * `jobId`. Nothing new is started or charged.\n *\n * Refusals (thrown as a `NodaroError` subclass; body `{ error: { code, message } }`), before\n * anything is charged: 400 `validation_error` (the body: no role with images,\n * no reference and no `prePrompt` or `postPrompt`, more roles of a kind\n * than allowed, more than 30 images in all, `draft: true` above 480p, a\n * `prePrompt` or `postPrompt` over 4,000 characters); on Nodaro Motion Pulse,\n * `draft_unsupported` (`draft: true`), `resolution_unsupported` (480p),\n * `output_format_unsupported` (a MOV edit output) and `too_many_images` (more\n * than 10 images in the run, across every role and fixed reference);\n * `raw_reference_token` (also in a reference's `line`),\n * `invalid_role_mention` (also any `{role:N}` in a reference's `line`),\n * `unsafe_url`, `video_unreadable`, `clip_out_of_range` (4–30 s),\n * `preview_out_of_range`, `no_roles_in_preview` (a preview with every role\n * `inPreview: false`, always refused even with a prompt, or with no role kept\n * in it that has images and no `prePrompt` or `postPrompt`), `prompt_too_long`\n * (the prompt would build too long: a `{role:N}` reads as the role's name when\n * it sends no images; Nodaro Motion Pulse's cap is 8,000 characters); 401; 402 `insufficient_credits` (`run()` only); 404\n * (a `sessionId` you may not use, `run()` only); 422 `job_blocked` (`run()`\n * only); 503 `host_too_old` (both); 503 `estimate_unavailable` (`estimate()`\n * only).\n */\n\n/**\n * The engine a Nodaro Motion run is made on, by its public id. Left out =\n * `\"motion-prism\"`.\n *\n * - `\"motion-prism\"` (Nodaro Motion Prism): 480p (the default, a draft unless\n * `draft: false`), 720p or 1080p; Full Quality re-renders a draft's own take\n * at 1080p.\n * - `\"motion-pulse\"` (Nodaro Motion Pulse): 720p (the default) or 1080p, never a\n * draft (`draft: true` answers 400 `draft_unsupported`); Full Quality makes a\n * new take at 1080p from a completed 720p run's inputs. A preview is still\n * 4 s from `previewStart`.\n */\nexport type CastSwapEngine = \"motion-prism\" | \"motion-pulse\"\n\n/**\n * The engine ids an older client sent: the earlier public ids (`\"motion-pro\"`\n * = `\"motion-prism\"`, `\"motion-lite\"` = `\"motion-pulse\"`) and the internal\n * ones (`\"seedance-2-5\"`, `\"kling-4\"`). Still accepted in a request; never\n * returned.\n * @deprecated use {@link CastSwapEngine}.\n */\nexport type CastSwapEngineLegacyId = \"motion-pro\" | \"motion-lite\" | \"seedance-2-5\" | \"kling-4\"\n\n/**\n * How a run follows its clip. Left out = `\"precise\"`.\n *\n * - `\"precise\"`: follows the clip exactly.\n * - `\"motion\"`: follows the clip's movement and takes the looks from your\n * photos, more freely than `\"precise\"`. Its price may differ from\n * `\"precise\"`'s: the estimate shows the exact price.\n */\nexport type CastSwapStyle = \"precise\" | \"motion\"\n\n/**\n * Where a Nodaro Motion Pulse run cuts the clip to whole seconds (Pulse renders\n * whole seconds; asked for more than the clip, it would stretch the motion):\n * - `\"cut-end\"` (the default): drop the fraction of a second at its end;\n * - `\"cut-start\"`: drop it at its start.\n */\nexport type CastSwapMotionLength = \"cut-end\" | \"cut-start\"\n\n/** @deprecated use {@link CastSwapMotionLength}. */\nexport type CastSwapKlingLength = CastSwapMotionLength\n\n/** Whether a swapped subject takes this trait from the references (`\"new\"`) or keeps the video's (`\"original\"`). */\nexport type CastSwapTraitSource = \"new\" | \"original\"\n\n/**\n * Preview-only settings, on every role kind; a full run (`preview` not `true`)\n * ignores both.\n */\nexport interface CastSwapRolePreviewSettings {\n /** The name used instead of `name` in a preview. Same rules as `name` (1–200 characters). */\n previewName?: string\n /**\n * `false` leaves this role out of the preview: its reference images are not\n * sent, not prepared and not charged, and a `{role:N}` naming it reads as its\n * `previewName`, else its `name`. Default `true`. A preview with every role\n * left out (always refused, even with a prompt), or with no role kept in it\n * that has images and no pre / post prompt, answers 400 `no_roles_in_preview`.\n */\n inPreview?: boolean\n}\n\n/** A person in the video to recast. */\nexport interface CastSwapPersonRole extends CastSwapRolePreviewSettings {\n kind: \"person\"\n /** How the person is told apart in the video, e.g. `\"the woman that attacks\"`. */\n name: string\n /** 0–3 images of ONE person. Empty or `null` keeps the original person. */\n images: string[] | null\n /** Body from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Outfit from the references or the video. Default `\"new\"`. */\n outfit?: CastSwapTraitSource\n /** Hairstyle and haircut from the references or the video. Default `\"new\"`. */\n hair?: CastSwapTraitSource\n}\n\n/** The place the video happens in. */\nexport interface CastSwapLocationRole extends CastSwapRolePreviewSettings {\n kind: \"location\"\n /** How the place is named. Default `\"the setting\"`. */\n name?: string\n /** 0–3 images of ONE place. Empty or `null` keeps the original place. */\n images: string[] | null\n}\n\n/** An animal in the video to recast. */\nexport interface CastSwapPetRole extends CastSwapRolePreviewSettings {\n kind: \"pet\"\n /** How the animal is told apart in the video, e.g. `\"the dog\"`. */\n name: string\n /** 0–3 images of ONE animal. Empty or `null` keeps the original animal. */\n images: string[] | null\n /** Body (shape, size and build) from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Coat (fur, colors and markings) from the references or the video. Default `\"new\"`. */\n coat?: CastSwapTraitSource\n}\n\n/** An object in the video to recast. */\nexport interface CastSwapProductRole extends CastSwapRolePreviewSettings {\n kind: \"product\"\n /** How the object is told apart in the video, e.g. `\"the can\"`. */\n name: string\n /** 0–3 images of ONE product. Empty or `null` keeps the original object. */\n images: string[] | null\n /** Shape and proportions from the references or the video. Default `\"new\"`. */\n shape?: CastSwapTraitSource\n /** Finish (colors, materials, label and markings) from the references or the video. Default `\"new\"`. */\n finish?: CastSwapTraitSource\n}\n\nexport type CastSwapRole = CastSwapPersonRole | CastSwapLocationRole | CastSwapPetRole | CastSwapProductRole\n\n/**\n * A fixed reference: 1–3 images of ONE thing that no role replaces, and the\n * line that says what it is (`\"the glass she drinks from\"`). Sent as given,\n * never prepared; its images count toward the 30.\n */\nexport interface CastSwapReference {\n /** 1–3 http(s) image URLs of one thing. */\n images: string[]\n /**\n * What it is, 1–500 characters. `{image}` in the line stands for this\n * reference's first image (`\"Use {image} for the sky\"`); a line without it\n * gets it appended. A `{role:N}` or a raw `{image:` / `{video:` / `{audio:`\n * token answers 400.\n */\n line: string\n}\n\n/**\n * @deprecated Nodaro sets this per engine; a run's `faceMasking` is ignored.\n */\nexport interface CastSwapFaceMaskingZone {\n leftPct?: number\n rightPct?: number\n topPct?: number\n bottomPct?: number\n}\n\n/**\n * @deprecated Nodaro sets how the clip is prepared for the video model, per\n * engine; a run cannot change it. A `faceMasking` sent is accepted and\n * ignored (no error), so older code keeps working unchanged.\n */\nexport interface CastSwapFaceMasking {\n mode: \"off\" | \"always\" | \"auto\"\n fill?: \"blur\" | \"depth\"\n minFaceHeightPct?: number\n maxFaceHeightPct?: number\n zone?: CastSwapFaceMaskingZone | null\n blurStrengthPct?: number\n threshold?: number\n}\n\n/** The body of `POST /v1/cast-swap` and `POST /v1/cast-swap/estimate`. */\nexport interface CastSwapParams {\n /** The source clip, 4–30 seconds. */\n videoUrl: string\n /**\n * Who and what to swap: at most 6 person roles, 1 location role, 3 pet roles\n * and 3 product roles, with at most 30 images in all. A role with no images\n * is skipped (that subject or place stays as in the video). At least one role\n * with images, or a `prePrompt` or `postPrompt`, is required.\n */\n roles: CastSwapRole[]\n /**\n * Fixed references (at most 5): things the video should show that no role\n * replaces, each with the line that names it. Their images count toward the\n * 30. A reference alone is enough for a run (no role needs images).\n */\n references?: CastSwapReference[]\n /**\n * Your own words placed at the start of the prompt, before the role\n * instructions; at most 4,000 characters. Mention a role as `{role:N}`, as in\n * `postPrompt`; the same 400 refusals apply (an N outside 1..`roles.length`,\n * a raw `{image:` / `{video:` / `{audio:` token).\n */\n prePrompt?: string\n /**\n * Extra instructions in your own words, at most 4,000 characters. Mention a\n * role as `{role:N}`, where N is its 1-based position in `roles`\n * (`{role:1}` is `roles[0]`; empty roles count).\n *\n * The route answers 400, before charging, for an N outside 1..`roles.length`,\n * for a raw `{image:` / `{video:` / `{audio:` token in the pre or post prompt\n * or a role's `name`, for a clip outside 4–30 s, and for a preview past the clip's\n * end (`previewStart + 4` > its length).\n */\n postPrompt?: string\n /** `true` runs on 4 seconds of the clip, starting at `previewStart`: a cheap check of the roles and choices. */\n preview?: boolean\n /** Where the preview starts, in seconds. Default 0. */\n previewStart?: number\n /**\n * The engine (see {@link CastSwapEngine}). Default `\"motion-prism\"`. The job\n * records it in `input_data.engine`, and a completed job's output in its\n * `engine`. The ids an older client sent ({@link CastSwapEngineLegacyId})\n * are still accepted.\n */\n engine?: CastSwapEngine | CastSwapEngineLegacyId\n /**\n * How the run follows the clip (see {@link CastSwapStyle}). Default\n * `\"precise\"`; the job records it in `input_data.style`.\n */\n style?: CastSwapStyle\n /**\n * Flex only (`style: \"motion\"`, a direct run): an art style that restyles\n * the whole video, as a `direction.style` id of the platform's `style`\n * picker catalog (the same ids an image's `direction.style` takes); the\n * platform words it. Refused with 400 `unknown_art_style` (not in the\n * catalog), `art_style_not_supported` (a saved moodboard, `moodboard:…`)\n * or `art_style_needs_flex` (Precise, a trend run). It never changes the\n * price. The job records it in `input_data.direction`.\n */\n direction?: { style: string }\n /**\n * Nodaro Motion Pulse only (Prism ignores it): which end of the clip is cut to\n * whole seconds (see {@link CastSwapMotionLength}). Default `\"cut-end\"`.\n */\n motionLength?: CastSwapMotionLength\n /** @deprecated use {@link motionLength} (still accepted). */\n klingLength?: CastSwapKlingLength\n /**\n * The output resolution. Nodaro Motion Prism: `\"480p\"` (default), `\"720p\"` or\n * `\"1080p\"`. Nodaro Motion Pulse: `\"720p\"` (default) or `\"1080p\"`; `\"480p\"`\n * answers 400.\n */\n resolution?: \"480p\" | \"720p\" | \"1080p\"\n /**\n * Render as a draft (Nodaro Motion Prism only). Defaults to `true` at 480p and\n * `false` above it; `true` with `\"720p\"` or `\"1080p\"` answers 400 (draft is\n * 480p only). Nodaro Motion Pulse has no draft: `true` answers 400\n * `draft_unsupported`.\n */\n draft?: boolean\n /**\n * Turn each person, pet and product role's photos into one clean reference\n * picture before the video (extra credits, shown in `breakdown.references`;\n * about a minute longer; falls back to your own photos if it fails).\n * Default `true`.\n */\n prepareReferences?: boolean\n /**\n * Ignored: Nodaro sets how the clip is prepared, per engine. Accepted (no\n * error) so older code keeps working.\n * @deprecated leave it out.\n */\n faceMasking?: CastSwapFaceMasking\n /**\n * `\"draft\"` means 480p draft.\n * @deprecated use `resolution` + `draft`.\n */\n quality?: \"draft\"\n /** A generation session to file the result in. */\n sessionId?: string\n /** The client app that sent the run (stored on the job as `input_data.origin`). */\n origin?: string\n}\n\n/** What a run would cost, in credits. */\nexport interface CastSwapEstimate {\n /**\n * The engine the run would use, by its public id (absent from an older\n * server = `\"motion-prism\"`). An id an older server answers is read as the\n * public id it names.\n */\n engine?: CastSwapEngine\n /**\n * What is held when the run starts. The run is charged what it actually\n * costs, which is expected to be `expectedCredits`.\n */\n totalCredits: number\n /**\n * The charge the run is expected to come to. Never above `totalCredits`\n * (on Nodaro Motion Pulse it equals it: Pulse renders exactly the length\n * asked for, so the hold is what it settles at). Absent from an older\n * server: read `totalCredits` then.\n */\n expectedCredits?: number\n /**\n * The parts of the quote, by name, for display only:\n * - `base`: the run itself (its base fee). A server before Cast Swap 0.396.0\n * names it `castSwap` instead: read `base`, else `castSwap`;\n * - `references`: preparing the reference pictures (0 when\n * `prepareReferences` is off or there is nothing to prepare);\n * - `motion`: what the video holds (on Nodaro Motion Pulse, what it costs);\n * - `motionExpected`: what the video is expected to be charged, never above\n * `motion` (Nodaro Motion Prism);\n * - `privacy`: preparing the clip, when the engine's setting does. In both\n * totals when it always runs; outside both when it is the retry\n * (`privacyCredits`).\n *\n * `motion` and `motionExpected` are alternatives, so the parts sum to more\n * than either total: read `totalCredits` and `expectedCredits`, never the\n * sum. Other parts may appear.\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n references: number\n motion?: number\n motionExpected?: number\n privacy?: number\n } & Record<string, number>\n /**\n * The extra credits charged only if the video model refuses the clip and\n * the run is retried (Nodaro's setting for the engine decides whether it\n * does). Not in `totalCredits` or `expectedCredits`; `run()` needs credits\n * for both the hold and this (else 402).\n */\n privacyCredits?: number\n /** @deprecated read {@link privacyCredits} (an older server answered this name). */\n maskingCredits?: number\n /**\n * `true` when the video is made at Auto length (every Nodaro Motion Prism\n * run): the final charge is expected to come out lower than `totalCredits`,\n * at about `expectedCredits`. `false` on Nodaro Motion Pulse.\n */\n settlesLower: boolean\n}\n\n/** Per-call options for {@link CastSwapResource.run}. */\nexport interface CastSwapRunOptions {\n /**\n * Sent as the `Idempotency-Key` header, unchanged (the SDK checks nothing;\n * an empty string sends no header, like no key).\n * The server takes 8–200 characters and answers 400 for any other length.\n * Reuse the same value when retrying the same run: within about 10 s the\n * repeat answers 200 `{ jobId, deduped: true }`, later 202 with the first\n * run's `jobId`. Nothing new is started or charged.\n */\n idempotencyKey?: string\n}\n\n/**\n * What a Full Quality version would be: `\"same-take\"` re-renders a Nodaro\n * Motion Prism draft's own take at 1080p; `\"new-take\"` makes a new Nodaro Motion Pulse take at\n * 1080p from a 720p run's inputs (it will not match the 720p run frame for\n * frame). The 720p run or draft stays either way.\n */\nexport type CastSwapFullQualityKind = \"same-take\" | \"new-take\"\n\n/**\n * What a Full Quality version of a run would cost\n * (`POST /v1/cast-swap/:jobId/full-quality/estimate`): a Nodaro Motion Prism\n * draft, or a completed Nodaro Motion Pulse run at 720p.\n */\nexport interface CastSwapFullQualityEstimate {\n /**\n * Which Full Quality this is ({@link CastSwapFullQualityKind}), so it can\n * be worded right. Absent from an older server: `\"same-take\"`.\n */\n kind?: CastSwapFullQualityKind\n /** The quote in credits: `breakdown.base` plus the 1080p render (same take) or the new take. */\n totalCredits: number\n /**\n * The parts of the quote, by name, for display only: `base` (the Full\n * Quality job's own steps; a server before Cast Swap 0.396.0 names it\n * `castSwap` instead: read `base`, else `castSwap`), and `motionHd` (a same\n * take: the 1080p render, 0 when an earlier try of this draft already\n * finished that render, which is then reused) or `motion` (a new take).\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n motionHd?: number\n motion?: number\n } & Record<string, number>\n /** ISO time until which the run can be finished at Full Quality (7 days after it completed). */\n availableUntil: string\n}\n\n/** Options for {@link CastSwapResource.fullQuality}. */\nexport interface CastSwapFullQualityParams {\n /** A generation session to file the Full Quality result in. */\n sessionId?: string\n}\n\n/** The Full Quality job (`POST /v1/cast-swap/:jobId/full-quality`). */\nexport interface CastSwapFullQualityResult {\n jobId: string\n /** `true` when this run's Full Quality was already running or done: that job is answered, nothing new is started or charged. */\n existing?: boolean\n}\n\n/**\n * The `code` of a Full Quality refusal (`NodaroError.code`), all before\n * anything is charged:\n * - `unauthorized` (401): no authenticated user;\n * - `not_found` (404): not your job, or not a Nodaro Motion run; also a\n * `sessionId` you may not use;\n * - `not_completed` (409): the run has not finished;\n * - `not_a_draft` (409): the run is neither a Nodaro Motion Prism draft nor a\n * Nodaro Motion Pulse run at 720p (a Pulse run at 1080p is already Full Quality);\n * - `draft_expired` (410): more than 7 days after the draft completed, or\n * the draft can no longer be finished at Full Quality;\n * - `full_quality_pending` (409, `details.retryable: true`): not final — an\n * earlier try's 1080p render of this draft is being reviewed, or has not\n * started yet; try again later (once the review ends). The only refusal\n * that ends on its own;\n * - `full_quality_unavailable` (409): final — nothing kept to re-render, no\n * readable completion time, or the 1080p finalize refuses this draft; on\n * the start only, also \"failed too many times\" (every try failed) or no\n * try can be started for this run;\n * - `insufficient_credits` (402), or in a workspace `budget_exceeded`,\n * `member_cap_exceeded` or `user_allowance_exceeded`;\n * - `job_blocked` (422): the request was blocked by the job policy;\n * - `job_read_failed` (503, retryable), `estimate_unavailable` (503, try\n * again shortly), `host_too_old` (503).\n *\n * Open-ended: a code not listed here may still arrive.\n */\nexport type CastSwapFullQualityRefusalCode =\n | \"unauthorized\"\n | \"not_found\"\n | \"not_completed\"\n | \"not_a_draft\"\n | \"draft_expired\"\n | \"full_quality_pending\"\n | \"full_quality_unavailable\"\n | \"insufficient_credits\"\n | \"budget_exceeded\"\n | \"member_cap_exceeded\"\n | \"user_allowance_exceeded\"\n | \"job_blocked\"\n | \"job_read_failed\"\n | \"estimate_unavailable\"\n | \"host_too_old\"\n | (string & {})\n\nexport class CastSwapResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Start a Nodaro Motion run (`POST /v1/cast-swap`, 202 `{ jobId }`). Returns the\n * job to follow. With `options.idempotencyKey` (sent as the\n * `Idempotency-Key` header; 8–200 characters, else 400) a repeat with the\n * same key within about 10 s answers 200 `{ jobId, deduped: true }`, a later\n * one 202 with the first run's `jobId`; nothing new starts.\n */\n run(params: CastSwapParams, options?: CastSwapRunOptions): Promise<{ jobId: string; deduped?: boolean }> {\n return this.client.request(\"POST\", \"/v1/cast-swap\", {\n body: params,\n ...(options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}),\n })\n }\n\n /** Quote a run before starting it (`POST /v1/cast-swap/estimate`); spends nothing. */\n async estimate(params: CastSwapParams): Promise<CastSwapEstimate> {\n const quote = await this.client.request<CastSwapEstimate>(\"POST\", \"/v1/cast-swap/estimate\", { body: params })\n // An older server names the engine by an earlier id: answered as the public id it names.\n const engine = nodaroMotionEngineFrom(quote?.engine)\n return engine && engine !== quote.engine ? { ...quote, engine } : quote\n }\n\n /**\n * Quote finishing a run at Full Quality (`POST\n * /v1/cast-swap/:jobId/full-quality/estimate`); spends nothing. `jobId` is a\n * finished Nodaro Motion Prism DRAFT run, or a finished Nodaro Motion Pulse\n * run at 720p (a Nodaro Motion or trend run); the quote's `kind` says whether it is the same take\n * re-rendered or a new take. The quote\n * does not look for a Full Quality already running: when one is,\n * {@link fullQuality} answers it (`existing: true`) and charges nothing.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQualityEstimate(jobId: string): Promise<CastSwapFullQualityEstimate> {\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality/estimate`, { body: {} })\n }\n\n /**\n * Finish a run at Full Quality (`POST /v1/cast-swap/:jobId/full-quality`):\n * at 1080p, with the clip's audio, as a new job linked to the run — a\n * Nodaro Motion Prism draft's own take re-rendered, or a new Nodaro Motion Pulse take from a\n * 720p run's inputs (the quote's `kind`). SPENDS CREDITS: quote it first with\n * {@link fullQualityEstimate}. Answers 202 `{ jobId }`, or 200\n * `{ jobId, existing: true }` when this run's Full Quality is already\n * running or done (one per run; a failed one may be asked again). Follow\n * the job with `client.jobs.get(jobId)`. No `Idempotency-Key` is taken: the\n * server keys the job by the draft. The new job keeps the draft's origin.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQuality(jobId: string, params: CastSwapFullQualityParams = {}): Promise<CastSwapFullQualityResult> {\n const body = params.sessionId !== undefined ? { sessionId: params.sessionId } : {}\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality`, { body })\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/trends.ts"],"names":[],"mappings":"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","file":"chunk-HFYNZ4SO.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport type { CastSwapEngine } from \"./cast-swap.js\"\n\n/**\n * Trends — ready-made Nodaro Motion recipes. A trend is a short clip with slots\n * (the people, pets, products and place you can replace); fill its slots with\n * your own pictures and run it to get the clip back with them in it.\n *\n * Cloud edition only: `/v1/trends` 404s on self-hosted installs. Only\n * published trends exist here: a draft, unpublished or unknown slug is a 404\n * on every route. `\"runs\"` and `\"tags\"` are never slugs (`/v1/trends/runs` is\n * the run list, `/v1/trends/tags` the tag list): the slug methods throw a\n * `TypeError` for them before any request. `run()` answers 202 with a job id; follow it with\n * `client.jobs.get(jobId)` / `client.jobs.getStatus(jobId)` like any other\n * job, or read it back as a trend run with `getRun(jobId)` / `runs()`.\n *\n * Repeats: pass `{ idempotencyKey }` to `run()` and it is sent as the\n * `Idempotency-Key` header. A repeat with the same key answers with the first\n * run's `jobId`; nothing new is started or charged.\n *\n * Refusals (thrown as a `NodaroError` subclass; body `{ error: { code, message } }`):\n * - 400 `validation_error` (the body, a query, or a bad `cursor`);\n * `estimate()` / `run()` only, before anything is charged:\n * `missing_slot` (a required slot without pictures), `unknown_slot`,\n * `invalid_choice` (a chip the slot's kind does not take),\n * `chip_not_offered` (a chip of the kind that the slot's\n * {@link TrendDetailSlot.chips} does not list: the trend fixes it),\n * `example_out_of_range` (`example` names no example of the trend, or is\n * sent at all on a trend with none), `preview_unavailable` (the trend offers no\n * preview), `invalid_slot_mention` (a `{slot:<key>}` in `details` naming no\n * slot), `prompt_too_long` (shorten `details`), `draft_unsupported`\n * (`draft: true` on a trend whose `engine` has no draft: Nodaro Motion Pulse),\n * `resolution_unsupported` (a `resolution` not in the trend's\n * `resolutions`), `too_many_images` (a Nodaro Motion Pulse trend's run would send more\n * than 10 pictures: send fewer per slot). The slot errors carry the\n * slot's key as `slot` (in `NodaroError.details`), and `chip_not_offered`\n * the chip as `chip` too.\n * - 401 `unauthorized`.\n * - 404 `not_found`: the trend is not published (every method), or `run()`'s\n * `sessionId` is not a session you may use.\n * - 409 `trend_unavailable` (`estimate()` / `run()`): the trend's setup is out\n * of date — it cannot run until it is updated, so a retry gets the same answer.\n * - 502 `engine_error` (`estimate()` / `run()`).\n * - 503 `engine_unsupported` (this platform version cannot run trends yet),\n * `trend_unavailable` (`estimate()` / `run()`), `not_available` (this\n * server has no trend catalog yet).\n * - `estimate()` / `run()` answer the video engine's refusals with the trend\n * routes' OWN codes and fixed messages — never the engine's text or\n * `issues`: 400 `trend_run_rejected` (the inputs could not run), or\n * `clip_out_of_range` / `preview_out_of_range` / `video_unreadable` (this\n * trend's clip), `unsafe_url` (a picture is not a public http(s) address),\n * `raw_reference_token` (`details` holds `{image:` / `{video:` /\n * `{audio:`); 402 `insufficient_credits` (or a workspace cap) as given;\n * 413 `storage_limit_exceeded`; 422 `job_blocked` (the job policy\n * blocked it); 429 `rate_limited`; 503 `engine_unsupported`,\n * `estimate_unavailable`; 502 `engine_error` for anything else. `run()`\n * also answers 400 `validation_error` for an `idempotencyKey` outside\n * 8–200 characters.\n */\n\n/** `/v1/trends/runs` is the run list and `/v1/trends/tags` the tag list, so neither can be a trend's slug. */\nconst RESERVED_SLUGS: Readonly<Record<string, string>> = {\n runs: \"the run list; use runs()\",\n tags: \"the tag list; use tags()\",\n}\n\nfunction trendPath(slug: string, rest = \"\"): string {\n if (Object.hasOwn(RESERVED_SLUGS, slug)) {\n throw new TypeError(`\"${slug}\" is not a trend slug (it is reserved for ${RESERVED_SLUGS[slug]})`)\n }\n return `/v1/trends/${encodeURIComponent(slug)}${rest}`\n}\n\n/** What a slot holds. */\nexport type TrendSlotKind = \"person\" | \"location\" | \"product\" | \"pet\"\n\n/** A chip: make this trait anew from your pictures (`\"new\"`), or keep the clip's (`\"original\"`). */\nexport type TrendChoice = \"new\" | \"original\"\n\n/**\n * The chips a slot can take, by its kind: a person `body` / `outfit` / `hair`,\n * a pet `body` / `coat`, a product `shape` / `finish`, a location none.\n */\nexport interface TrendChips {\n body?: TrendChoice\n outfit?: TrendChoice\n hair?: TrendChoice\n coat?: TrendChoice\n shape?: TrendChoice\n finish?: TrendChoice\n}\n\n/** A chip's name: `body`, `outfit`, `hair`, `coat`, `shape` or `finish`. */\nexport type TrendChipKey = keyof TrendChips\n\nexport type TrendResolution = \"480p\" | \"720p\" | \"1080p\"\n\n/**\n * The engine a trend runs on, by its public id ({@link CastSwapEngine}):\n * `\"motion-prism\"` (Nodaro Motion Prism) or `\"motion-pulse\"` (Nodaro Motion Pulse).\n * The trend chooses it, never the person running it.\n */\nexport type TrendEngine = CastSwapEngine\n\n/** A trend in the catalog (`list()`). Text is in the resolved locale. */\nexport interface TrendCard {\n id: string\n slug: string\n name: string\n description?: string\n tags: string[]\n /** e.g. `\"trending\"`, `\"new\"`. */\n badges: string[]\n /**\n * The trend's first example, else (a trend with no example) its original's\n * display copy, as {@link TrendDetail.original}.\n */\n cover: { videoUrl: string; posterUrl?: string; width: number; height: number }\n /**\n * The original's display copy, the same address as {@link TrendDetail.original}\n * (without its length and preview start). Absent on a version without a\n * display copy (and from an older server). On a trend that hides its\n * original, its first example instead (then the same as {@link cover}).\n */\n original?: { videoUrl: string; posterUrl?: string; width: number; height: number }\n /**\n * Every example's video, in the page's order, so a list can show each clip\n * without reading the trend's page. Empty on a trend with only its original;\n * absent from an older server. The pictures each slot used are on the page\n * ({@link TrendDetail.examples}). On a trend that hides its original, from\n * its second example (the first is {@link original}).\n */\n examples?: Array<{ videoUrl: string; posterUrl?: string; width: number; height: number }>\n /** How many slots of each kind the trend has. */\n needs: Record<TrendSlotKind, number>\n /** The length of a full run, in seconds. */\n durationSec: number\n isFavorite: boolean\n}\n\n/** One slot of a trend: what it asks you for. */\nexport interface TrendDetailSlot {\n /** The key to fill in {@link TrendRunRequest.slots}, and to mention in `details` as `{slot:<key>}`. */\n key: string\n label: string\n kind: TrendSlotKind\n /**\n * A required slot needs pictures; an optional one left empty takes the\n * chosen example's, or, on a trend with no example (or when that example has\n * none for it), stays as in the original;\n * except in Full depth trends, where it uses the trend's default image for that role if one is set, otherwise the original's look.\n */\n required: boolean\n hint?: string\n /**\n * A picture showing who or what this slot is in the original (e.g. a frame\n * of that actor), when the trend has one. Show it on an empty slot; a run\n * never sends it.\n */\n hintImageUrl?: string\n /**\n * The chips you may set on this slot, in its kind's order; `[]` = none (show\n * no chips row). A chip of the kind that is not listed is fixed by the\n * trend: sending it is refused with `400 chip_not_offered`.\n */\n chips: TrendChipKey[]\n /** The starting value of the chips in {@link chips} (only those). */\n defaults?: TrendChips\n}\n\n/** A finished run shown on a trend's page, with the pictures it used per slot. */\nexport interface TrendExample {\n videoUrl: string\n posterUrl?: string\n width: number\n height: number\n /**\n * Slot key → the pictures this example used for it. An optional slot the\n * example kept as in the original has no key; a run that leaves that slot\n * empty with this example keeps it as in the original too.\n */\n slots: Record<string, string[]>\n}\n\n/**\n * The clip a trend recasts, as you may show it: a browser-safe copy (H.264\n * MP4) of the clip every run starts from. On a trend that hides its original,\n * its first example instead (the original clip is then never sent). Its fields\n * parallel {@link TrendExample}'s.\n */\nexport interface TrendOriginal {\n videoUrl: string\n posterUrl?: string\n width: number\n height: number\n /** The copy's length (on a trend that hides its original, the first example's), in seconds. */\n durationSec: number\n /**\n * Where the 4-second preview starts in the clip, in seconds (`0` included),\n * when the trend offers one ({@link TrendDetail.previewSec} is `4`); absent\n * otherwise.\n */\n previewStartSec?: number\n}\n\n/** A trend's page (`get()`). */\nexport interface TrendDetail extends TrendCard {\n /** The published version this page shows. */\n version: number\n /** `4` when the trend offers a 4-second preview run, else `null`. */\n previewSec: 4 | null\n /**\n * The original clip every run starts from, to show beside the examples.\n * Absent only on a version without a display copy (and from an older server).\n * On a trend that hides its original, its first example (see {@link TrendOriginal}).\n */\n original?: TrendOriginal\n /** The engine every run of this trend uses. Absent (an older server) = `\"motion-prism\"`. */\n engine?: TrendEngine\n /** Its name to show: \"Nodaro Motion Prism\" or \"Nodaro Motion Pulse\". Absent from an older server. */\n engineName?: string\n /**\n * The resolutions a run may ask for, the default first. Nodaro Motion Prism:\n * `[\"480p\", \"720p\", \"1080p\"]`, where 480p is a draft (show it as one);\n * Nodaro Motion Pulse: `[\"720p\", \"1080p\"]`, no draft. Offer exactly these.\n */\n resolutions: TrendResolution[]\n slots: TrendDetailSlot[]\n /**\n * Finished runs to show beside the original; may be empty (a trend with only\n * its original). On a trend that hides its original, from its second example\n * (the first is {@link original}).\n */\n examples: TrendExample[]\n}\n\n/** What you put in one slot of a run: 1–3 pictures, and the chips the slot offers ({@link TrendDetailSlot.chips}). */\nexport interface TrendRunSlot extends TrendChips {\n images?: string[]\n}\n\n/** The body of `estimate()` and `run()`. */\nexport interface TrendRunRequest {\n /**\n * Slot key → what you put in it. Every required slot needs pictures; an\n * optional slot left out takes the chosen example's, or, on a trend with no\n * example (or when that example has none for it), stays as in the original; except in Full depth trends, where it uses the trend's default image for that role if one is set, otherwise the original's look.\n * 1–3 pictures per slot.\n */\n slots: Record<string, TrendRunSlot>\n /**\n * 1-based example whose pictures fill the optional slots you leave empty\n * (never in a Full depth trend, which records `example: 0`), numbering the\n * examples as {@link TrendDetail.examples} lists them. Default 1. Leave it out on a trend with no examples: sending one there\n * answers 400 `example_out_of_range` (and `0` is a `validation_error`). On a\n * trend that hides its original ({@link TrendDetail.original} is its first\n * example), `1` is still the first entry of `examples`, and leaving it out\n * fills the slots from the example shown as the original.\n */\n example?: number\n /** Your own words, at most 1,000 characters. Mention a slot as `{slot:<key>}`. */\n details?: string\n /** `true` runs a 4-second preview (only when the trend's `previewSec` is `4`). */\n preview?: boolean\n /**\n * One of the trend's {@link TrendDetail.resolutions}; default its first\n * (`\"480p\"` on Nodaro Motion Prism, `\"720p\"` on Nodaro Motion Pulse). Another answers 400\n * `resolution_unsupported`.\n */\n resolution?: TrendResolution\n /**\n * A draft run, only at 480p on a Nodaro Motion Prism trend. Default `true` at\n * 480p. `true` on a Nodaro Motion Pulse trend answers 400 `draft_unsupported`.\n */\n draft?: boolean\n /**\n * A generation session of yours. Accepted (and checked: one you may not use\n * is a 404), but not yet applied: trend runs are not filed into sessions yet.\n */\n sessionId?: string\n /** Accepted, but not used by the run today. */\n projectId?: string\n /**\n * A full run's own preview: the `jobId` of a completed preview run of this\n * trend that you started. When that preview needed the trend's retry (the\n * clip refused at first), the full run is made that way from the start (the\n * quote includes it). Any other job is ignored, without an error. Must be a uuid\n * (else 400 `validation_error`).\n */\n previewJobId?: string\n /**\n * `run()`: your client app's slug (e.g. `\"tools\"`: lowercase letters,\n * digits and `-`, 1–40 characters, starting with a letter or digit), as on\n * any job: the run's job carries it as `input_data.origin`, so\n * `client.jobs.list({ origin })` finds it. Not a slug is a 400\n * `validation_error`; without it the run has no origin. `estimate()`\n * ignores it.\n */\n origin?: string\n}\n\n/** What a run would cost, in credits (`estimate()`). */\nexport interface TrendEstimate {\n /** The charge the run is expected to come to. */\n expectedCredits: number\n /** What is reserved when the run starts; the run is charged what it actually costs. */\n holdCredits: number\n /**\n * The parts of the quote, by name, for display only: some are alternatives\n * or sit outside the totals (`privacy`, the retry's, beside\n * `privacyCredits`), so read `expectedCredits` and `holdCredits`, never\n * their sum.\n */\n breakdown: Record<string, number>\n /**\n * Only on a trend that retries a clip the video model refuses: the extra\n * credits charged if that retry runs. Not included in `expectedCredits` or\n * `holdCredits`. 0 (or absent) when there is nothing extra to charge.\n */\n privacyCredits?: number\n /** @deprecated read {@link privacyCredits} (an older server answered this name). */\n maskingCredits?: number\n}\n\n/** Per-call options for {@link TrendsResource.run}. */\nexport interface TrendRunOptions {\n /**\n * Sent as the `Idempotency-Key` header, unchanged (an empty string sends no\n * header). The server takes 8–200 characters and answers 400 for any other\n * length. Reuse it when retrying the same run.\n */\n idempotencyKey?: string\n}\n\n/** One slot of a past run, as it was run. Labels are English. */\nexport interface TrendRunDisplaySlot extends TrendChips {\n key: string\n label: string\n kind: TrendSlotKind\n images: string[]\n /**\n * `true` when the slot was left empty and the example's pictures filled it.\n * `false` with no `images`: left empty on a trend with no example, or the\n * chosen example has no pictures for it, so it stayed as in the original.\n */\n fromExample: boolean\n /**\n * `true` when the slot was left empty and the trend's own default pictures\n * filled it (`fromExample` is then `false`). Absent otherwise.\n */\n fromDefault?: true\n}\n\n/**\n * One of your trend runs (`runs()`, `getRun()`). Stays readable after the\n * trend moves on or is unpublished.\n *\n * A Full Quality version of a draft is a run of its own, with its own status,\n * result and charge: `fullQualityOf` names the draft it was made from, and it\n * stays listed after that draft is deleted.\n */\nexport interface TrendRun {\n jobId: string\n status: string\n progress: number | null\n /**\n * Why a failed or cancelled run did not finish; `null` otherwise. `code` is\n * `safety-block` or `policy-block` when the job was blocked, `credits` when\n * it ran out of credits partway (it was refunded: ask the person to top up,\n * then run it again), else `cancelled` or `failed`. `message` is the same\n * fixed sentence for every code — branch on `code`, not on the text.\n */\n error: { code?: string; message: string } | null\n createdAt: string\n completedAt: string | null\n /** The trend and version it ran (name in English). */\n trend: { id: string; slug: string; version: number; name: string }\n /**\n * The 1-based example used for empty optional slots, numbered as the trend's\n * page listed its examples for the version the run ran on ({@link trend}'s\n * `version`); `0` = none was used (the trend had no example, or is a Full\n * depth trend): never show it as \"Example 0\". Absent when the run used the\n * example a trend that hides its original shows as its original.\n */\n example?: number\n slots: TrendRunDisplaySlot[]\n details?: string\n preview: boolean\n resolution: string\n draft: boolean\n /** The engine the run was made on. Absent (an older server) = `\"motion-prism\"`. */\n engine?: TrendEngine\n /** Its name to show: \"Nodaro Motion Prism\" or \"Nodaro Motion Pulse\". Absent from an older server. */\n engineName?: string\n /** The result, once completed. */\n videoUrl: string | null\n posterUrl: string | null\n /**\n * What the run was charged once settled, every step it ran included (its\n * reference preparation, mask and video); `null` until the run's own hold\n * settles. A step adds its charge once it settles.\n */\n creditsCharged: number | null\n /** The run's hold: its own plus its steps'. Absent from an older server. */\n creditsHeld?: number | null\n /** What went back from `creditsHeld` once every hold in the run settled; `null` until then. Absent from an older server. */\n creditsReleased?: number | null\n /** A Full Quality version: the job id of the run (a draft, or a Nodaro Motion Pulse 720p run) it was made from. `null` for any other run. */\n fullQualityOf: string | null\n /**\n * A draft's (or Nodaro Motion Pulse 720p run's) newest Full Quality try, if one was started: a pointer only,\n * to know an upgrade exists and how it is going. Its video and charge are on\n * that run, listed on its own (its `fullQualityOf` is this run's `jobId`) —\n * read it there (`getRun(fullQuality.jobId)`). Older tries of the draft (a\n * failed or cancelled one tried again) are not listed by `runs()`;\n * `getRun()` still reads one by its id.\n */\n fullQuality: { jobId: string; status: string } | null\n /**\n * Until when a completed run can be redone in Full Quality — a Nodaro Motion\n * Prism draft (the same take at 1080p) or a Nodaro Motion Pulse run at 720p (a new take at\n * 1080p); `null` otherwise.\n */\n fullQualityUntil: string | null\n}\n\nexport interface ListTrendsParams {\n /** Search text. */\n q?: string\n tag?: string\n /** `true` lists only your favorites. */\n favorites?: boolean\n /** A platform language for names and descriptions; default your profile's, then English. */\n locale?: string\n /** The previous page's `next`. */\n cursor?: string\n /** Page size, 1–60 (server default 30). */\n limit?: number\n}\n\nexport interface ListTrendRunsParams {\n /** Only runs of this trend (its slug). */\n trend?: string\n /** The previous page's `next`. */\n cursor?: string\n /** Page size, 1–60 (server default 30). */\n limit?: number\n}\n\n/** A tag in use on the published catalog (`tags()`). */\nexport interface TrendTag {\n /** The tag itself: pass it as `list({ tag })`. */\n tag: string\n /** The tag's label in the resolved locale; the tag itself when it has none. */\n label: string\n /** How many published trends carry it. */\n count: number\n}\n\nexport interface TrendPage<T> {\n data: T[]\n /** Pass back as `cursor` for the next page; `null` on the last one. */\n next: string | null\n}\n\nexport class TrendsResource {\n constructor(private client: NodaroClientCore) {}\n\n /** The published catalog in its curated order (`GET /v1/trends`), a page at a time. */\n list(params: ListTrendsParams = {}): Promise<TrendPage<TrendCard>> {\n const query: Record<string, string> = {}\n if (params.q) query.q = params.q\n if (params.tag) query.tag = params.tag\n if (params.favorites) query.favorites = \"1\"\n if (params.locale) query.locale = params.locale\n if (params.cursor) query.cursor = params.cursor\n if (params.limit !== undefined) query.limit = String(params.limit)\n return this.client.request(\"GET\", \"/v1/trends\", { query })\n }\n\n /** A published trend's page (`GET /v1/trends/:slug`). */\n async get(slug: string, params: { locale?: string } = {}): Promise<TrendDetail> {\n const query: Record<string, string> = {}\n if (params.locale) query.locale = params.locale\n const res = await this.client.request<{ data: TrendDetail }>(\"GET\", trendPath(slug), { query })\n return res.data\n }\n\n /** Quote a run before starting it (`POST /v1/trends/:slug/estimate`); spends nothing. */\n async estimate(slug: string, request: TrendRunRequest): Promise<TrendEstimate> {\n const res = await this.client.request<{ data: TrendEstimate }>(\n \"POST\",\n trendPath(slug, \"/estimate\"),\n { body: request },\n )\n return res.data\n }\n\n /**\n * Start a run (`POST /v1/trends/:slug/runs`, 202). Returns the job to follow.\n * With `options.idempotencyKey` (sent as the `Idempotency-Key` header) a\n * repeat with the same key answers with the first run's `jobId`.\n */\n async run(slug: string, request: TrendRunRequest, options?: TrendRunOptions): Promise<{ jobId: string }> {\n const res = await this.client.request<{ data: { jobId: string } }>(\n \"POST\",\n trendPath(slug, \"/runs\"),\n {\n body: request,\n ...(options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}),\n },\n )\n return res.data\n }\n\n /**\n * Your trend runs, newest first (`GET /v1/trends/runs`). A Full Quality\n * version of a draft is listed as its own run (`fullQualityOf`).\n */\n runs(params: ListTrendRunsParams = {}): Promise<TrendPage<TrendRun>> {\n const query: Record<string, string> = {}\n if (params.trend) query.trend = params.trend\n if (params.cursor) query.cursor = params.cursor\n if (params.limit !== undefined) query.limit = String(params.limit)\n return this.client.request(\"GET\", \"/v1/trends/runs\", { query })\n }\n\n /**\n * One of your trend runs by its job id (`GET /v1/trends/runs/:jobId`), in\n * the same shape as `runs()`. A job that is not your own trend run is a\n * `NotFoundError`.\n */\n async getRun(jobId: string): Promise<TrendRun> {\n const res = await this.client.request<{ data: TrendRun }>(\"GET\", `/v1/trends/runs/${encodeURIComponent(jobId)}`)\n return res.data\n }\n\n /**\n * The tags in use on the published catalog, each with its label in the\n * resolved locale (`GET /v1/trends/tags`), most used first.\n */\n async tags(params: { locale?: string } = {}): Promise<TrendTag[]> {\n const query: Record<string, string> = {}\n if (params.locale) query.locale = params.locale\n const res = await this.client.request<{ data: TrendTag[] }>(\"GET\", \"/v1/trends/tags\", { query })\n return res.data\n }\n\n /** Add a trend to your favorites (`PUT /v1/trends/:slug/favorite`). */\n async favorite(slug: string): Promise<void> {\n await this.client.request<void>(\"PUT\", trendPath(slug, \"/favorite\"))\n }\n\n /** Remove a trend from your favorites (`DELETE /v1/trends/:slug/favorite`). */\n async unfavorite(slug: string): Promise<void> {\n await this.client.request<void>(\"DELETE\", trendPath(slug, \"/favorite\"))\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/jobs.ts"],"names":[],"mappings":"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","file":"chunk-HJLSOT5C.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\n\n/**\n * A job's lifecycle status. Hand-copied mirror of `JOB_STATUSES` in the\n * platform's `backend/src/lib/job-status.ts` — nothing links the two at build\n * time, so a new member has to be added here in the same change.\n *\n * `pending_review` is IN-FLIGHT, NOT TERMINAL: a job policy registered by the\n * deployment held the output for a human reviewer. Treat it like `processing`\n * in a `switch` — keep waiting, do not re-run — and it resolves to `completed`\n * (approved), `failed` (rejected, carrying an `error_hint` with\n * `kind: \"policy-block\"`) or `cancelled` (a held job is cancellable like any\n * in-flight job). `credit_status` reads `\"reserved\"` for the whole hold. Only\n * appears on deployments that register a job policy; `runAndWait` throws\n * {@link JobHeldError} on the first held tick rather than waiting it out.\n */\nexport type JobStatus =\n | \"pending\"\n | \"queued\"\n | \"processing\"\n | \"pending_review\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n\n/**\n * A PROVIDER's verdict: the model's own safety filter refused the output.\n * `class` distinguishes a deterministic block (copyright/likeness — retrying\n * the same request never helps) from `safety`, whose filter is known to be\n * non-deterministic for some models: `retried` says whether the worker\n * already spent its one extra attempt, and `suggestedProvider` — present\n * only when the catalog declares a fallback for the model that failed — is a\n * real model id the SAME prompt/references can be retried on.\n */\nexport type SafetyBlockHint = {\n kind: \"safety-block\"\n class: \"copyright\" | \"likeness\" | \"safety\"\n retried: boolean\n suggestedProvider?: string\n /**\n * Present when the provider named the input it refused — not the prompt or\n * the output. `\"input_video\"`: the input video itself; sending a different\n * clip is the fix. `\"input_image\"`: one of the input images, refused as\n * possibly copyrighted (with `class: \"copyright\"`); sending a different\n * picture is the fix. Treat an unknown value as absent.\n */\n subject?: \"input_video\" | \"input_image\"\n}\n\n/**\n * A NODARO-side verdict, not a provider's: a job policy registered by the\n * deployment rejected the request (`hookPoint: \"request\"` — nothing ran, and\n * the call itself failed with {@link JobBlockedError}) or the finished output\n * (`hookPoint: \"result\"` — the result was blocked and never published).\n *\n * `reason` is USER-SAFE BY CONTRACT — the platform guarantees the policy's\n * machine text (scores, labels) never reaches it — so show it to the person\n * who made the request as-is. `policyId` identifies the deployment's policy,\n * not a Nodaro product feature. Only occurs on deployments that register a\n * job policy.\n */\nexport type PolicyBlockHint = {\n kind: \"policy-block\"\n policyId: string\n reason: string\n hookPoint: \"request\" | \"result\"\n}\n\n/**\n * The job ran out of credits partway: a step that reserves its own credits\n * (for example, the video a Cast Swap or trend run dispatches) was refused —\n * the balance could not cover it, or a plan or workspace cap was reached. The\n * job failed and its credits were refunded; ask the person to top up (or raise\n * the cap), then run it again.\n *\n * `code` is the refusal's own code, a lowercase snake_case token — for\n * example `insufficient_credits`, `free_video_limit`, `instance_cap_reached`,\n * `budget_exceeded`, `member_cap_exceeded` or `user_allowance_exceeded`. Treat\n * an unknown code like `insufficient_credits`.\n */\nexport type CreditsHint = {\n kind: \"credits\"\n code: string\n}\n\n/**\n * The provider refused the job's input video without naming a content-policy\n * class (its message is about the file, not a policy). Treat it like any\n * other failure — no fallback model is offered — except that the input to\n * change is known: send a different clip.\n */\nexport type InputRefusedHint = {\n kind: \"input-refused\"\n subject: \"input_video\"\n}\n\n/**\n * A job's `jobs.error_hint` (migration 376) — a user-safe, machine-readable\n * failure verdict, so a caller can act on it without parsing `error_message`\n * prose. One column, several verdict sources; `kind` is the discriminant.\n *\n * HAND-COPIED MIRROR of `ErrorHint` in the platform's\n * `backend/src/lib/safety-block.ts` (which names this file in its own\n * comment). Nothing links the two at build time: a new arm there has to be\n * pasted here verbatim in the same change, with a changeset.\n * `packages/client/dist/index.d.ts` is REBUILT, never hand-edited.\n */\nexport type JobErrorHint = SafetyBlockHint | PolicyBlockHint | CreditsHint | InputRefusedHint\n\n/**\n * The billing lifecycle of a job's credit reservation — `usage_logs.status`\n * for the job's `usage_log_id`. `null` when the job has no usage log (e.g. a\n * free run) or hasn't reserved credits yet.\n */\nexport type CreditStatus = \"reserved\" | \"committed\" | \"refunded\"\n\n/** A job owner's rating of their job — set with {@link JobsResource.rate}. */\nexport type JobRating = \"good\" | \"bad\"\n\n/**\n * The `rating` filter of {@link JobsResource.list}: one rating, any rating\n * (`\"rated\"`) or none (`\"unrated\"`).\n */\nexport type JobRatingFilter = JobRating | \"rated\" | \"unrated\"\n\n/**\n * Job record returned to non-admin SDK consumers. Field names are snake_case\n * to match the wire format (per the OpenAPI fix in Phase 1).\n *\n * Sensitive fields stripped server-side for non-admin callers:\n * `provider`, `provider_cost`, `display_cost`, `credits_actual`. USD\n * pricing is admin-only across api/sdk/mcp — non-admin consumers see\n * only the `credits` abstraction. Server-only nested job data (including\n * Recast's private remux base) is stripped for every caller, including admins.\n */\nexport interface Job {\n id: string\n status: JobStatus\n progress: number\n user_id: string\n input_data: unknown\n output_data: unknown\n error_message: string | null\n /** Present on a failed job the worker classified as a provider\n * content-policy block (`kind: \"safety-block\"`) or that a deployment's job\n * policy rejected (`kind: \"policy-block\"`); absent/null otherwise.\n * User-safe by construction — narrow on `kind` before reading the rest. */\n error_hint?: JobErrorHint | null\n /** PR9: the job's credit reservation lifecycle, derived server-side from\n * `usage_logs.status`. `null` when there is no usage log to report. Never\n * changes the meaning of `credits` (the reserved amount) below. */\n credit_status?: CreditStatus | null\n /** The credits the job itself HELD when it was accepted. Never changes — a\n * job can settle below it; read {@link Job.credits_charged} for what it cost. */\n credits: number | null\n /**\n * What the job actually cost once its hold settled, INCLUDING the steps it\n * ran: a job that runs other jobs for you (a Nodaro Motion run's reference\n * preparation, mask and video) is charged for each, and they are not listed\n * on their own. A step adds its charge once it settles. Can be lower than\n * {@link Job.credits_held} (the unused part goes back to the balance). `0`\n * when the run's own hold was refunded, plus any settled steps (a refunded\n * Nodaro Motion run whose reference and mask steps committed reads\n * `credit_status: \"refunded\"` with `credits_charged: 165`). `null` while the\n * job's own hold is still open (even when some steps have settled), when\n * nothing in the run was reserved, or when its steps could not be read for a\n * moment (unknown — never a lower figure). Sum this — not `credits` — to\n * total spend. Returned by `get()` and `list()`.\n */\n credits_charged?: number | null\n /** The run's hold: the job's own `credits` plus its steps' holds (equals `credits` for a job with no steps). */\n credits_held?: number | null\n /** What went back from `credits_held` once every hold in the run settled; `null` until then. */\n credits_released?: number | null\n job_type: string | null\n created_at: string\n started_at: string | null\n completed_at: string | null\n /**\n * Provenance: which kind of caller created the job — one of\n * `\"internal\" | \"mcp\" | \"app\" | \"cli\" | \"sdk\" | \"extension\" | \"web\" | \"api\"`.\n * `source_detail` narrows it (origin host, `extension/<name>` label,\n * `sdk/<version>`, MCP client name, developer-app id). Descriptive only;\n * lets a library view label or filter media by origin.\n */\n source?: string | null\n source_detail?: string | null\n /** The generation session this job was born in (the `sessionId` sent with\n * the generation request), or null. See `client.sessions`. */\n session_id?: string | null\n /**\n * With `list({ withSessions: true })`: every session that holds the job now,\n * each linkable — empty when it is in no session (General). Absent otherwise.\n */\n sessions?: JobSessionRef[]\n /**\n * When the job was deleted, on a job read from the Trash\n * (`client.trash.list()`). A deleted job is left out of every other read, so\n * this is otherwise absent or `null`.\n */\n deleted_at?: string | null\n /**\n * Whether the job's owner favorited it (`client.gallery.toggleFavorite`).\n * Returned by `get()` and `list()`. Absent from an older server, and when\n * the server could not read it for a moment — treat absent as unknown,\n * never as `false`.\n */\n favorited?: boolean\n /**\n * The owner's rating of the job ({@link JobsResource.rate}), or `null` when\n * unrated. Returned by `get()` and `list()`; absent like `favorited`.\n */\n rating?: JobRating | null\n}\n\nexport interface CancelJobResult {\n success: true\n cancelled: number\n /**\n * `true` when the job could not be stopped because its provider call is\n * already running — a metered LLM job's call, an external provider task. It\n * finishes and is charged only what it used.\n */\n inFlight?: boolean\n}\n\n/**\n * The kind of caller that created a job (`Job.source`). Hand-copied mirror of\n * `JOB_SOURCES` in the platform's `backend/src/lib/job-source.ts`.\n */\nexport type JobSource = \"internal\" | \"mcp\" | \"app\" | \"cli\" | \"sdk\" | \"extension\" | \"web\" | \"api\"\n\nexport interface DeleteJobResult {\n success: true\n}\n\n/** A session that holds a job now (`Job.sessions`). */\nexport interface JobSessionRef {\n id: string\n title: string | null\n /** The session's project, or `null` when it has none. */\n projectId: string | null\n}\n\nexport interface ListJobsParams {\n /** One status or several (a job matching any of them). An unknown status is a 400. */\n status?: JobStatus | readonly JobStatus[]\n /** Exact match on `input_data.type` — the route that created the job\n * (`\"llm-structured\"`, `\"video-analysis\"`, …). One value or several (up to 20). */\n type?: string | readonly string[]\n /** Exact match on `input_data.origin` — the client app that sent it. */\n origin?: string\n /** The surface that created the job (`Job.source`): `\"mcp\"` lists what your\n * MCP clients (Claude, ChatGPT, …) made. One value or several. */\n source?: JobSource | readonly JobSource[]\n /** `true`: only jobs you favorited; `false`: only jobs you did not. */\n favorited?: boolean\n /** Your rating: `\"good\"`, `\"bad\"`, any (`\"rated\"`) or none (`\"unrated\"`). */\n rating?: JobRatingFilter\n /** The jobs of one generate-image batch (`count` / `models`) — its `batchId`. */\n batchId?: string\n /**\n * The jobs a session of this project holds now — or, `\"none\"`, a session\n * with no project. Each job once, however many sessions hold it. Not with\n * `inSession: false`.\n */\n projectId?: string | \"none\"\n /**\n * `false`: the jobs no session holds now (General), whatever session they\n * were born in. `true`: the jobs at least one session holds.\n */\n inSession?: boolean\n /** `true`: each job carries `sessions`, the sessions that hold it now. */\n withSessions?: boolean\n /** Page size, 1–100 (server default 50). */\n limit?: number\n /** The previous page's `next`. */\n cursor?: string\n}\n\n/** What {@link JobsResource.rate} answers: the job's rating now. */\nexport interface RateJobResult {\n data: { jobId: string; rating: JobRating | null }\n}\n\n/**\n * {@link JobsResource.fromUpload}'s body: an image edited in the browser,\n * already stored with `client.uploads.upload`, and what it was made from.\n */\nexport interface JobFromUploadParams {\n /** The edited image's `assetId`, as `client.uploads.upload` returned it. */\n assetId: string\n /** The job whose image was edited. */\n sourceJobId?: string\n /** Which of `sourceJobId`'s images was edited, when it made several. Default: its `imageUrl`. */\n sourceImageUrl?: string\n /** The upload that was edited, when the source is not a job. Not with `sourceJobId`. */\n sourceAssetId?: string\n /** The editor's design state, stored with `client.uploads.uploadJson`, so the edit can be reopened. */\n editStateUrl?: string\n /** The generation session to file the job in. */\n sessionId?: string\n}\n\n/** A list filter value as the query string carries it: several are comma-separated. */\nfunction listParam(value: string | readonly string[] | undefined): string | undefined {\n if (value === undefined) return undefined\n return typeof value === \"string\" ? value : value.join(\",\")\n}\n\nexport interface ListJobsPage {\n /**\n * A page may hold fewer than `limit` rows — even none — and still carry a\n * `next`. Page on `next`, never on `data.length`.\n */\n data: Job[]\n /** Pass back as `cursor` for the next page; `null` on the last one. */\n next: string | null\n}\n\n/**\n * Lean job status returned by `GET /v1/jobs/:id/status`. Skips the\n * `input_data` JSONB and cost columns. Its `output_data` still goes\n * through the server-only nested-field redaction. Intended for poll loops that\n * only need progress/output/error, and when the job finished.\n */\nexport interface JobStatusResult {\n id: string\n status: JobStatus\n progress?: number\n output_data?: unknown\n error_message?: string | null\n /** PR9: see {@link Job.error_hint}. */\n error_hint?: JobErrorHint | null\n /** PR9: see {@link Job.credit_status}. */\n credit_status?: CreditStatus | null\n /** When the job finished, on the server's clock; null until it has. */\n completed_at?: string | null\n}\n\nexport class JobsResource {\n constructor(private client: NodaroClientCore) {}\n\n /** Get a single job by ID. */\n get(id: string): Promise<{ data: Job }> {\n return this.client.request(\"GET\", `/v1/jobs/${encodeURIComponent(id)}`)\n }\n\n /**\n * Your jobs, newest first (`GET /v1/jobs`), cursor-paginated. `type` and\n * `origin` filter on the job's own `input_data`, which every job carries —\n * a client app lists its runs with `{ type: \"llm-structured\", origin: \"studio\" }`.\n * `status` and `type` take one value or a list; `favorited` and `rating`\n * filter on your own marks, `source` on the surface that created the job.\n * `projectId` / `inSession` filter on where the job is now (a project's\n * sessions, or General), and `withSessions` says which sessions each job is\n * in — for \"everything in this project\". Every filter combines with AND,\n * and each job carries `favorited` and `rating`. A deleted job is never\n * listed: read the Trash with `client.trash.list()`.\n */\n list(params: ListJobsParams = {}): Promise<ListJobsPage> {\n const { status, type, source, inSession, withSessions, ...rest } = params\n return this.client.request<ListJobsPage>(\"GET\", \"/v1/jobs\", {\n query: {\n ...rest,\n status: listParam(status),\n type: listParam(type),\n source: listParam(source),\n inSession: inSession === undefined ? undefined : String(inSession),\n withSessions: withSessions ? \"true\" : undefined,\n },\n })\n }\n\n /**\n * Record an image edited in the browser as a job (`POST /v1/jobs/from-upload`):\n * a completed, private, free `image-edit` job whose `output_data.imageUrl` is\n * the upload, linked to its source in `input_data` (`sourceJobId` /\n * `sourceAssetId`, `sourceImageUrl`). It then lists, rates, favorites and\n * files into a session like any image job. One upload is one job: the same\n * `assetId` again returns the same job. OAuth apps need the `assets:write`\n * scope. A deployment's job policy can refuse the image ({@link JobBlockedError}).\n */\n fromUpload(params: JobFromUploadParams): Promise<{ data: Job }> {\n return this.client.request<{ data: Job }>(\"POST\", \"/v1/jobs/from-upload\", { body: params })\n }\n\n /**\n * Rate one of your jobs `\"good\"` or `\"bad\"`, or clear the rating with\n * `null` (`PUT /v1/jobs/:id/rating`). Only the job's owner rates it — anyone\n * else's job is a `NotFoundError`. The rating reads back as `Job.rating`\n * and filters {@link list}. OAuth apps need the `assets:write` scope.\n */\n rate(id: string, rating: JobRating | null): Promise<RateJobResult> {\n return this.client.request<RateJobResult>(\"PUT\", `/v1/jobs/${encodeURIComponent(id)}/rating`, {\n body: { rating },\n })\n }\n\n /**\n * Get the lean status of a single job (poll-loop friendly).\n * Hits `GET /v1/jobs/:id/status` — returns only id/status/progress/\n * output_data/error_message, with far less wire/CPU cost than `get()`.\n * Same auth + ownership semantics as {@link get}.\n */\n getStatus(id: string): Promise<{ data: JobStatusResult }> {\n return this.client.request(\n \"GET\",\n `/v1/jobs/${encodeURIComponent(id)}/status`,\n )\n }\n\n /**\n * Cancel a job. Server route is `POST /v1/jobs/:jobId/cancel`.\n * Refunds any reserved credit holds. A running LLM job priced per model\n * (metered) whose call has already started answers\n * `{ success: true, cancelled: 0, inFlight: true }`: it finishes and is\n * charged only what it used. A job stopped before its call starts is\n * refunded, except for what an earlier attempt of the same job already used\n * (a retry after a billed attempt): that is charged.\n */\n cancel(id: string): Promise<CancelJobResult> {\n return this.client.request(\n \"POST\",\n `/v1/jobs/${encodeURIComponent(id)}/cancel`,\n )\n }\n\n /**\n * Delete a job: it goes to the Trash (`client.trash.list()`). It is left out\n * of every read from then on, stays restorable for 30 days ({@link restore},\n * back into the sessions it was in), and is then deleted for good, as a\n * delete always was (a copy saved to the Library stays). `{ forever: true }` deletes a job already in the Trash for good now;\n * on a live job it fails with a 409 `NodaroError` whose `code` is\n * `\"not_in_trash\"`. Only the job's owner (or an admin) may delete it; a job\n * that is still running keeps running — cancel it first when its worker\n * should stop ({@link cancel}). Nothing is refunded. OAuth apps need the\n * `assets:write` scope.\n */\n delete(id: string, options: { forever?: boolean } = {}): Promise<DeleteJobResult> {\n return this.client.request(\n \"DELETE\",\n `/v1/jobs/${encodeURIComponent(id)}`,\n options.forever ? { query: { forever: \"true\" } } : {},\n )\n }\n\n /**\n * Bring a deleted job back from the Trash: it reappears in every read and in\n * every session it was in. A job that is not in the Trash succeeds too.\n * OAuth apps need the `assets:write` scope.\n */\n restore(id: string): Promise<{ success: true }> {\n return this.client.request(\"POST\", `/v1/jobs/${encodeURIComponent(id)}/restore`)\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readSseStream } from './chunk-
|
|
1
|
+
import { readSseStream } from './chunk-4FSWJTRS.js';
|
|
2
2
|
|
|
3
3
|
// src/resources/copilot.ts
|
|
4
4
|
var COPILOT_FRAME_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -98,5 +98,5 @@ var CopilotResource = class {
|
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
export { CopilotResource };
|
|
101
|
-
//# sourceMappingURL=chunk-
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
101
|
+
//# sourceMappingURL=chunk-HK6XP5EN.js.map
|
|
102
|
+
//# sourceMappingURL=chunk-HK6XP5EN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resources/copilot.ts"],"names":[],"mappings":"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","file":"chunk-D2ILCSOQ.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { readSseStream } from \"../sse.js\"\n\n/**\n * The assistant's conversation surface (`/v1/copilot/*`) — threads, and one\n * turn as a live stream.\n *\n * A thread is the conversation; a TURN is one message and everything the\n * assistant does in answer to it. `stream` is the only method that spends: it\n * POSTs the message and yields the turn's frames as they arrive, so a caller\n * renders prose, tool activity and proposals live instead of waiting for a\n * finished answer.\n *\n * Two shapes here are deliberately TOLERANT of a deployment that predates a\n * field, because the SDK ships ahead of every instance it talks to:\n * - `surface` is optional on both {@link CopilotThread} and the `metadata`\n * frame — absent is a value (\"this deployment does not say\"), never a\n * default this package invents.\n * - An event kind this package does not model is IGNORED, not thrown: a\n * newer server may emit frames a caller was built before.\n */\n\n/** How this thread runs what it proposes: ask first, or run within a budget. */\nexport type CopilotRunMode = \"ask\" | \"auto\"\n\n/** The thread's model rung. Absent from a server that predates it. */\nexport type CopilotModelTier = \"economy\" | \"standard\" | \"premium\"\n\n/**\n * Which product the conversation belongs to.\n *\n * NO deployment sends this today — nothing in the platform emits it yet — and\n * it is typed here so that the day one does, a caller reads what the server\n * said. That is why it is OPTIONAL everywhere it appears: absent is a value\n * (\"this deployment does not say\"), never a default this package invents.\n */\nexport type CopilotSurface = \"studio\" | \"workflow\"\n\nexport interface CopilotThread {\n id: string\n workflowId: string\n runMode: CopilotRunMode\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n /** Whether this thread may build nodes that publish to connected accounts. */\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n autoRunLimitCredits: number\n userTurnCount: number\n lastMessageAt: string | null\n createdAt: string\n /** Only on {@link CopilotResource.get} — derived from a live turn. */\n status?: \"running\" | \"idle\"\n activeTurnId?: string | null\n}\n\n/** The workflow a thread was opened on, as `create` answers it. */\nexport interface CopilotThreadWorkflow {\n id: string\n projectId: string\n name: string\n version: number\n}\n\nexport type CopilotMessagePart =\n | { kind: \"text\"; text: string }\n | { kind: \"tool_call\"; id: string; name: string; label: string; status: \"finished\" | \"failed\" }\n\nexport interface CopilotMessage {\n id: string\n seq: number\n turnId: string\n role: \"user\" | \"assistant\"\n createdAt: string\n parts: CopilotMessagePart[]\n}\n\n/** Open a thread on an existing workflow, or on one this call creates. */\nexport interface CreateCopilotThreadInput {\n /** The workflow to work on. Give this OR `prompt`. */\n workflowId?: string\n /** Start from nothing: the server creates a workflow seeded by this prompt. */\n prompt?: string\n /** Name for a workflow created by `prompt` (defaults to the prompt's head). */\n name?: string\n}\n\nexport interface CopilotStreamOptions {\n /** The user's turn. */\n message: string\n /** The workflow version this message was composed against — a newer one 409s. */\n baseVersion?: number\n /** The composer's echo of the thread's rung; the thread row stays authoritative. */\n tier?: CopilotModelTier\n /**\n * Ends the stream. The client's request timeout is NOT applied to a turn.\n *\n * Aborting REJECTS the iteration — with the platform's raw `AbortError`, not\n * a `NodaroError` — whether it fires before the first frame or between two of\n * them. Wrap the loop in `try`/`catch` if a cancelled turn is an ordinary\n * ending in your UI. (`media.downloadVideoProgress` behaves the same way.)\n */\n signal?: AbortSignal\n}\n\nexport interface CopilotToolCallFrameData {\n id: string\n name: string\n label: string\n status: \"started\" | \"finished\" | \"failed\"\n summary?: string\n}\n\nexport interface CopilotWorkflowUpdateFrameData {\n workflowId: string\n version: number\n updatedAt?: string\n note?: string | null\n addedNodeIds: string[]\n updatedNodeIds: string[]\n removedNodeIds: string[]\n addedNodeTypes: string[]\n nodeCount: number\n edgeCount: number\n adjustments: string[]\n}\n\n/** A file the turn wired onto a node — named on the run card, never counted. */\nexport interface CopilotWiredAsset {\n id: string\n kind: string\n filename: string\n nodeId: string\n}\n\nexport interface CopilotRunProposalNode {\n id: string\n type: string\n graphVersion: number\n label: string\n}\n\nexport interface CopilotRunProposalFrameData {\n workflowId: string\n addedNodeTypes: string[]\n wiredAssets?: CopilotWiredAsset[]\n note: string | null\n /** Present when ONE node was proposed rather than the whole graph. */\n node?: CopilotRunProposalNode | null\n}\n\n/** A workflow the turn created — a different one from the open canvas. */\nexport interface CopilotWorkflowCreatedFrameData {\n workflowId: string\n name: string\n projectId: string\n}\n\n/** One thing the assistant saved to memory this turn. */\nexport interface CopilotMemorySavedFrameData {\n id: string\n content: string\n}\n\nexport interface CopilotMetadataFrameData {\n threadId: string\n turnId: string\n jobId: string\n model: string\n baseVersion: number | null\n runMode: CopilotRunMode\n autoRunLimitCredits: number\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n}\n\n/**\n * One frame of a turn.\n *\n * The union covers the frame KINDS; a frame's `data` is passed through\n * untouched, so a field this package does not model still reaches the caller\n * rather than being stripped on the way.\n */\nexport type CopilotStreamFrame =\n | { type: \"metadata\"; data: CopilotMetadataFrameData }\n | { type: \"token\"; data: { text: string } }\n | { type: \"tool_call\"; data: CopilotToolCallFrameData }\n | { type: \"workflow_updated\"; data: CopilotWorkflowUpdateFrameData }\n | { type: \"workflow_created\"; data: CopilotWorkflowCreatedFrameData }\n | { type: \"run_proposed\"; data: CopilotRunProposalFrameData }\n | { type: \"memory_saved\"; data: CopilotMemorySavedFrameData }\n | { type: \"usage\"; data: { inputTokens: number; outputTokens: number; cacheReadTokens: number; creditsCharged: number | null } }\n | { type: \"done\"; data: { turnId: string; messageId: string | null; status: \"completed\" | \"capped\" | \"cancelled\"; finalVersion: number | null } }\n | { type: \"error\"; data: { code: string; message: string } }\n\n/** The kinds above, as the wire spells them — the whole of what `stream` yields. */\nconst COPILOT_FRAME_TYPES: ReadonlySet<string> = new Set([\n \"metadata\",\n \"token\",\n \"tool_call\",\n \"workflow_updated\",\n \"workflow_created\",\n \"run_proposed\",\n \"memory_saved\",\n \"usage\",\n \"done\",\n \"error\",\n])\n\nfunction isCopilotFrame(value: unknown): value is CopilotStreamFrame {\n if (typeof value !== \"object\" || value === null) return false\n const type = (value as { type?: unknown }).type\n return typeof type === \"string\" && COPILOT_FRAME_TYPES.has(type)\n}\n\nexport class CopilotResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Open a conversation (`POST /v1/copilot/threads`) — on `workflowId`, or on\n * a workflow the server creates from `prompt`. Re-opening a workflow that\n * already has an active thread answers THAT thread rather than a second one.\n */\n create(input: CreateCopilotThreadInput): Promise<{ data: { thread: CopilotThread; workflow: CopilotThreadWorkflow } }> {\n return this.client.request(\"POST\", \"/v1/copilot/threads\", { body: input })\n }\n\n /**\n * The active thread for a workflow (`GET /v1/copilot/threads?workflowId=…`),\n * or `null` when the user has none open on it.\n */\n list(params: { workflowId: string }): Promise<{ data: { thread: CopilotThread | null } }> {\n return this.client.request(\"GET\", \"/v1/copilot/threads\", { query: { workflowId: params.workflowId } })\n }\n\n /**\n * One thread with its messages (`GET /v1/copilot/threads/:id`). `after` reads\n * only what followed that sequence number (the panel's catch-up); `limit`\n * caps the page at the server's own ceiling.\n */\n get(\n id: string,\n opts: { after?: number; limit?: number } = {},\n ): Promise<{ data: { thread: CopilotThread; messages: CopilotMessage[] } }> {\n return this.client.request(\"GET\", `/v1/copilot/threads/${encodeURIComponent(id)}`, {\n query: { ...(opts.after !== undefined ? { after: opts.after } : {}), ...(opts.limit !== undefined ? { limit: opts.limit } : {}) },\n })\n }\n\n /**\n * Close a conversation (`DELETE /v1/copilot/threads/:id`). Archival, not\n * deletion — the messages stay readable. Refused while a turn is running.\n */\n archive(id: string): Promise<{ data: { archived: true } }> {\n return this.client.request(\"DELETE\", `/v1/copilot/threads/${encodeURIComponent(id)}`)\n }\n\n /**\n * Stop the running turn (`POST /v1/copilot/threads/:id/cancel`). Answers the\n * turn it asked to stop; the turn's own stream ends with a `done` frame.\n */\n cancel(id: string): Promise<{ data: { cancelling: true; turnId: string } }> {\n return this.client.request(\"POST\", `/v1/copilot/threads/${encodeURIComponent(id)}/cancel`)\n }\n\n /**\n * Send one message and iterate the turn's frames\n * (`POST /v1/copilot/threads/:id/messages`, server-sent events).\n *\n * Deliberately NOT routed through `client.request`: that path arms an abort\n * timer around the whole exchange, and a turn legitimately runs for minutes —\n * inheriting `timeoutMs` would cut the assistant off mid-answer. The caller\n * owns the lifetime instead: pass `signal` to end the stream, or stop\n * iterating (the reader cancels the body, which ends the request).\n *\n * A frame kind this package does not model is skipped rather than thrown, so\n * a newer server cannot break an older caller.\n */\n async *stream(threadId: string, opts: CopilotStreamOptions): AsyncGenerator<CopilotStreamFrame, void, undefined> {\n const url = `${this.client.baseUrl}/v1/copilot/threads/${encodeURIComponent(threadId)}/messages`\n const token = await this.client.auth.getToken()\n const res = await this.client.fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n body: JSON.stringify({\n message: opts.message,\n ...(opts.baseVersion !== undefined ? { baseVersion: opts.baseVersion } : {}),\n ...(opts.tier ? { tier: opts.tier } : {}),\n }),\n signal: opts.signal,\n })\n for await (const value of readSseStream<unknown>(res, { label: \"copilot stream\" })) {\n if (isCopilotFrame(value)) yield value\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/resources/copilot.ts"],"names":[],"mappings":"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","file":"chunk-HK6XP5EN.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { readSseStream } from \"../sse.js\"\n\n/**\n * The assistant's conversation surface (`/v1/copilot/*`) — threads, and one\n * turn as a live stream.\n *\n * A thread is the conversation; a TURN is one message and everything the\n * assistant does in answer to it. `stream` is the only method that spends: it\n * POSTs the message and yields the turn's frames as they arrive, so a caller\n * renders prose, tool activity and proposals live instead of waiting for a\n * finished answer.\n *\n * Two shapes here are deliberately TOLERANT of a deployment that predates a\n * field, because the SDK ships ahead of every instance it talks to:\n * - `surface` is optional on both {@link CopilotThread} and the `metadata`\n * frame — absent is a value (\"this deployment does not say\"), never a\n * default this package invents.\n * - An event kind this package does not model is IGNORED, not thrown: a\n * newer server may emit frames a caller was built before.\n */\n\n/** How this thread runs what it proposes: ask first, or run within a budget. */\nexport type CopilotRunMode = \"ask\" | \"auto\"\n\n/** The thread's model rung. Absent from a server that predates it. */\nexport type CopilotModelTier = \"economy\" | \"standard\" | \"premium\"\n\n/**\n * Which product the conversation belongs to.\n *\n * NO deployment sends this today — nothing in the platform emits it yet — and\n * it is typed here so that the day one does, a caller reads what the server\n * said. That is why it is OPTIONAL everywhere it appears: absent is a value\n * (\"this deployment does not say\"), never a default this package invents.\n */\nexport type CopilotSurface = \"studio\" | \"workflow\"\n\nexport interface CopilotThread {\n id: string\n workflowId: string\n runMode: CopilotRunMode\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n /** Whether this thread may build nodes that publish to connected accounts. */\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n autoRunLimitCredits: number\n userTurnCount: number\n lastMessageAt: string | null\n createdAt: string\n /** Only on {@link CopilotResource.get} — derived from a live turn. */\n status?: \"running\" | \"idle\"\n activeTurnId?: string | null\n}\n\n/** The workflow a thread was opened on, as `create` answers it. */\nexport interface CopilotThreadWorkflow {\n id: string\n projectId: string\n name: string\n version: number\n}\n\nexport type CopilotMessagePart =\n | { kind: \"text\"; text: string }\n | { kind: \"tool_call\"; id: string; name: string; label: string; status: \"finished\" | \"failed\" }\n\nexport interface CopilotMessage {\n id: string\n seq: number\n turnId: string\n role: \"user\" | \"assistant\"\n createdAt: string\n parts: CopilotMessagePart[]\n}\n\n/** Open a thread on an existing workflow, or on one this call creates. */\nexport interface CreateCopilotThreadInput {\n /** The workflow to work on. Give this OR `prompt`. */\n workflowId?: string\n /** Start from nothing: the server creates a workflow seeded by this prompt. */\n prompt?: string\n /** Name for a workflow created by `prompt` (defaults to the prompt's head). */\n name?: string\n}\n\nexport interface CopilotStreamOptions {\n /** The user's turn. */\n message: string\n /** The workflow version this message was composed against — a newer one 409s. */\n baseVersion?: number\n /** The composer's echo of the thread's rung; the thread row stays authoritative. */\n tier?: CopilotModelTier\n /**\n * Ends the stream. The client's request timeout is NOT applied to a turn.\n *\n * Aborting REJECTS the iteration — with the platform's raw `AbortError`, not\n * a `NodaroError` — whether it fires before the first frame or between two of\n * them. Wrap the loop in `try`/`catch` if a cancelled turn is an ordinary\n * ending in your UI. (`media.downloadVideoProgress` behaves the same way.)\n */\n signal?: AbortSignal\n}\n\nexport interface CopilotToolCallFrameData {\n id: string\n name: string\n label: string\n status: \"started\" | \"finished\" | \"failed\"\n summary?: string\n}\n\nexport interface CopilotWorkflowUpdateFrameData {\n workflowId: string\n version: number\n updatedAt?: string\n note?: string | null\n addedNodeIds: string[]\n updatedNodeIds: string[]\n removedNodeIds: string[]\n addedNodeTypes: string[]\n nodeCount: number\n edgeCount: number\n adjustments: string[]\n}\n\n/** A file the turn wired onto a node — named on the run card, never counted. */\nexport interface CopilotWiredAsset {\n id: string\n kind: string\n filename: string\n nodeId: string\n}\n\nexport interface CopilotRunProposalNode {\n id: string\n type: string\n graphVersion: number\n label: string\n}\n\nexport interface CopilotRunProposalFrameData {\n workflowId: string\n addedNodeTypes: string[]\n wiredAssets?: CopilotWiredAsset[]\n note: string | null\n /** Present when ONE node was proposed rather than the whole graph. */\n node?: CopilotRunProposalNode | null\n}\n\n/** A workflow the turn created — a different one from the open canvas. */\nexport interface CopilotWorkflowCreatedFrameData {\n workflowId: string\n name: string\n projectId: string\n}\n\n/** One thing the assistant saved to memory this turn. */\nexport interface CopilotMemorySavedFrameData {\n id: string\n content: string\n}\n\nexport interface CopilotMetadataFrameData {\n threadId: string\n turnId: string\n jobId: string\n model: string\n baseVersion: number | null\n runMode: CopilotRunMode\n autoRunLimitCredits: number\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n}\n\n/**\n * One frame of a turn.\n *\n * The union covers the frame KINDS; a frame's `data` is passed through\n * untouched, so a field this package does not model still reaches the caller\n * rather than being stripped on the way.\n */\nexport type CopilotStreamFrame =\n | { type: \"metadata\"; data: CopilotMetadataFrameData }\n | { type: \"token\"; data: { text: string } }\n | { type: \"tool_call\"; data: CopilotToolCallFrameData }\n | { type: \"workflow_updated\"; data: CopilotWorkflowUpdateFrameData }\n | { type: \"workflow_created\"; data: CopilotWorkflowCreatedFrameData }\n | { type: \"run_proposed\"; data: CopilotRunProposalFrameData }\n | { type: \"memory_saved\"; data: CopilotMemorySavedFrameData }\n | { type: \"usage\"; data: { inputTokens: number; outputTokens: number; cacheReadTokens: number; creditsCharged: number | null } }\n | { type: \"done\"; data: { turnId: string; messageId: string | null; status: \"completed\" | \"capped\" | \"cancelled\"; finalVersion: number | null } }\n | { type: \"error\"; data: { code: string; message: string } }\n\n/** The kinds above, as the wire spells them — the whole of what `stream` yields. */\nconst COPILOT_FRAME_TYPES: ReadonlySet<string> = new Set([\n \"metadata\",\n \"token\",\n \"tool_call\",\n \"workflow_updated\",\n \"workflow_created\",\n \"run_proposed\",\n \"memory_saved\",\n \"usage\",\n \"done\",\n \"error\",\n])\n\nfunction isCopilotFrame(value: unknown): value is CopilotStreamFrame {\n if (typeof value !== \"object\" || value === null) return false\n const type = (value as { type?: unknown }).type\n return typeof type === \"string\" && COPILOT_FRAME_TYPES.has(type)\n}\n\nexport class CopilotResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Open a conversation (`POST /v1/copilot/threads`) — on `workflowId`, or on\n * a workflow the server creates from `prompt`. Re-opening a workflow that\n * already has an active thread answers THAT thread rather than a second one.\n */\n create(input: CreateCopilotThreadInput): Promise<{ data: { thread: CopilotThread; workflow: CopilotThreadWorkflow } }> {\n return this.client.request(\"POST\", \"/v1/copilot/threads\", { body: input })\n }\n\n /**\n * The active thread for a workflow (`GET /v1/copilot/threads?workflowId=…`),\n * or `null` when the user has none open on it.\n */\n list(params: { workflowId: string }): Promise<{ data: { thread: CopilotThread | null } }> {\n return this.client.request(\"GET\", \"/v1/copilot/threads\", { query: { workflowId: params.workflowId } })\n }\n\n /**\n * One thread with its messages (`GET /v1/copilot/threads/:id`). `after` reads\n * only what followed that sequence number (the panel's catch-up); `limit`\n * caps the page at the server's own ceiling.\n */\n get(\n id: string,\n opts: { after?: number; limit?: number } = {},\n ): Promise<{ data: { thread: CopilotThread; messages: CopilotMessage[] } }> {\n return this.client.request(\"GET\", `/v1/copilot/threads/${encodeURIComponent(id)}`, {\n query: { ...(opts.after !== undefined ? { after: opts.after } : {}), ...(opts.limit !== undefined ? { limit: opts.limit } : {}) },\n })\n }\n\n /**\n * Close a conversation (`DELETE /v1/copilot/threads/:id`). Archival, not\n * deletion — the messages stay readable. Refused while a turn is running.\n */\n archive(id: string): Promise<{ data: { archived: true } }> {\n return this.client.request(\"DELETE\", `/v1/copilot/threads/${encodeURIComponent(id)}`)\n }\n\n /**\n * Stop the running turn (`POST /v1/copilot/threads/:id/cancel`). Answers the\n * turn it asked to stop; the turn's own stream ends with a `done` frame.\n */\n cancel(id: string): Promise<{ data: { cancelling: true; turnId: string } }> {\n return this.client.request(\"POST\", `/v1/copilot/threads/${encodeURIComponent(id)}/cancel`)\n }\n\n /**\n * Send one message and iterate the turn's frames\n * (`POST /v1/copilot/threads/:id/messages`, server-sent events).\n *\n * Deliberately NOT routed through `client.request`: that path arms an abort\n * timer around the whole exchange, and a turn legitimately runs for minutes —\n * inheriting `timeoutMs` would cut the assistant off mid-answer. The caller\n * owns the lifetime instead: pass `signal` to end the stream, or stop\n * iterating (the reader cancels the body, which ends the request).\n *\n * A frame kind this package does not model is skipped rather than thrown, so\n * a newer server cannot break an older caller.\n */\n async *stream(threadId: string, opts: CopilotStreamOptions): AsyncGenerator<CopilotStreamFrame, void, undefined> {\n const url = `${this.client.baseUrl}/v1/copilot/threads/${encodeURIComponent(threadId)}/messages`\n const token = await this.client.auth.getToken()\n const res = await this.client.fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n body: JSON.stringify({\n message: opts.message,\n ...(opts.baseVersion !== undefined ? { baseVersion: opts.baseVersion } : {}),\n ...(opts.tier ? { tier: opts.tier } : {}),\n }),\n signal: opts.signal,\n })\n for await (const value of readSseStream<unknown>(res, { label: \"copilot stream\" })) {\n if (isCopilotFrame(value)) yield value\n }\n }\n}\n"]}
|
|
@@ -199,5 +199,5 @@ var CreaturesResource = class {
|
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
export { CREATURE_ASSET_TYPES, CreaturesResource };
|
|
202
|
-
//# sourceMappingURL=chunk-
|
|
203
|
-
//# sourceMappingURL=chunk-
|
|
202
|
+
//# sourceMappingURL=chunk-HUYI5G3D.js.map
|
|
203
|
+
//# sourceMappingURL=chunk-HUYI5G3D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/creatures.ts"],"names":[],"mappings":"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","file":"chunk-HUYI5G3D.js","sourcesContent":["import type { ObjectAspectRatio, CreatureAttachColumn } from \"@nodaro/shared/entities\"\nimport type { TtsProvider } from \"@nodaro/shared/models\"\nexport type { CreatureAttachColumn, ObjectAspectRatio as CreatureAspectRatio } from \"@nodaro/shared/entities\"\nexport { CREATURE_ATTACH_COLUMNS, OBJECT_ASPECT_OPTIONS as CREATURE_ASPECT_OPTIONS, OBJECT_ASPECT_DEFAULTS as CREATURE_ASPECT_DEFAULTS } from \"@nodaro/shared/entities\"\nimport type { NodaroClientCore } from \"../core.js\"\nimport type { GenerationSessionParams, Subject } from \"./nodes.js\"\nimport type { SetKeeperCatalogInput, SetKeeperCatalogResult } from \"./keepers.js\"\n\n/**\n * Creature voice — IDENTICAL shape + semantics to `Character[\"voice\"]` (the\n * \"talking creature\" stack reuses the character voice plumbing verbatim).\n * Render speech via `client.nodes.run(\"text-to-speech\", { text, voice:\n * voiceId, provider: ttsProvider, voiceType })`, then feed the audio + the\n * creature's `sourceImageUrl` to `client.nodes.run(\"lip-sync\", …)` (or\n * speech-to-video) for a talking-creature clip.\n */\nexport interface CreatureVoice {\n voiceId: string\n voiceName: string\n traits: string\n voiceType?: \"premade\" | \"library\" | \"custom\"\n /** Playable preview sample (client-played only). */\n previewUrl?: string\n /** Recommended TTS provider — send as `provider` on text-to-speech. */\n ttsProvider?: TtsProvider\n}\n\n/**\n * Re-export the shared `CreatureAttachColumn` union + its runtime tuple so SDK\n * consumers don't have to add `@nodaro/shared` as a second dependency just to\n * typecheck the `attachToColumn` field. Single source of truth lives in\n * `@nodaro/shared/entity-prompts` (`CREATURE_ATTACH_COLUMNS`).\n *\n * `CreatureAspectRatio` is re-exported as an alias of the shared\n * `ObjectAspectRatio` — `generateMotion`'s `aspectRatio` field is the 5-value\n * object enum (1:1 / 3:4 / 16:9 / 9:16 / 4:3). The creature motion route\n * deliberately REUSES `OBJECT_ASPECT_OPTIONS` server-side (a creature reference\n * clip is centered product-showcase framing, not cinematic 16:9), so the SDK\n * surfaces the same enum under a creature-friendly name. The runtime tuple is\n * re-exported as `CREATURE_ASPECT_OPTIONS` / `CREATURE_ASPECT_DEFAULTS` aliases.\n */\n\n/**\n * Creature asset-type enum — the kinds of variant a user can generate off a\n * creature's anchor main image. Mirrors the literal accepted by\n * `POST /v1/generate-creature-asset` (`backend/src/routes/generate-creature-asset.ts`).\n *\n * Delta vs `ObjectAssetType`: object's `materials` becomes `poses` (a creature\n * has poses, not materials), and there is NO `motion` value — creature motion\n * variants flow through the dedicated `/v1/generate-creature-motion` endpoint\n * (worker-side a different BullMQ job type). `custom` is the free-form bucket;\n * callers must supply `attachToColumn` explicitly since the worker can't infer\n * the destination from the asset type.\n *\n * The shared `@nodaro/shared` package does NOT export a `CREATURE_ASSET_TYPES`\n * tuple (the route validates an inline Zod enum), so the SDK defines its own\n * single-source-of-truth tuple here.\n */\nexport const CREATURE_ASSET_TYPES = [\"angles\", \"poses\", \"variations\", \"custom\"] as const\nexport type CreatureAssetType = (typeof CREATURE_ASSET_TYPES)[number]\n\n/**\n * Reference-photo kind discriminator — the mood-board roles a user can attach\n * to a creature. Mirrors the `reference_photos.kind` field accepted by\n * `backend/src/routes/creatures.ts` (the route accepts open strings; this SDK\n * type narrows to the 6 canonical roles surfaced by the Studio). `other` is\n * the free-form bucket.\n */\nexport type CreatureReferencePhotoKind =\n | \"front\"\n | \"side\"\n | \"detail\"\n | \"context\"\n | \"moodBoard\"\n | \"other\"\n\nexport interface CreatureReferencePhoto {\n url: string\n kind: CreatureReferencePhotoKind\n}\n\n/**\n * A creature record returned by Nodaro's REST API. Mirrors the camelCase\n * shape produced by `backend/src/routes/creatures.ts::toCamel()`.\n *\n * Asset buckets (`angles`, `poses`, `variations`, `motionClips`) are\n * independent JSONB arrays keyed by a human-readable variant name (e.g.\n * `\"front\"`, `\"walking\"`, `\"scarred\"`). Each entry's `url` points at an\n * R2-hosted asset.\n *\n * Creature delta vs object:\n * - `species` — free-text creature type (e.g. `\"dragon\"`, `\"wolf\"`). This is\n * the subject of the establishing-shot prompt and the primary creature\n * differentiator (object has no equivalent).\n * - `poses` (where object has `materials`) — the pose-variant asset bucket.\n * - `category` is free-text (NOT object's fixed 10-value enum) — a creature\n * can be any animal/type.\n *\n * Identity-foundation fields:\n * - `referencePhotos` — caller-supplied mood-board refs (cap 20).\n * - `canonicalDescription` — ~80–120-word LLM-authored visual caption,\n * populated by `approveMainImage()` / `recaption()`. The wire still sends\n * `\"\"` on caption sub-failure, but `get()` normalizes `\"\"` → `null` so\n * consumers see the same `string | null` semantics as characters.\n * - `styleLock` — whether asset gens should anchor to the canonical style\n * captured at approval time. Defaults to `true` on new rows.\n */\nexport interface Creature {\n id: string\n userId: string\n nodeId: string\n projectId: string | null\n name: string\n description: string | null\n /** Free-text creature type/species (e.g. \"dragon\", \"wolf\") — the creature\n * delta vs object. `null` when unset. */\n species: string | null\n category: string | null\n style: string | null\n sourceImageUrl: string | null\n /** MODEL_CATALOG image-model id the main image was generated with (or `null`).\n * Set on create + editable via the update route. */\n imageProvider: string | null\n angles: Array<{ name: string; url: string }>\n poses: Array<{ name: string; url: string }>\n variations: Array<{ name: string; url: string }>\n motionClips: Array<{ name: string; url: string }>\n /** Named Creature Boards — dense reference sheets, one per variant/mood\n * (the `generate-image/creature-board` factory preset rendered from the\n * creature's images). A first-class bucket: community publish snapshots it\n * and clone hands the consumer their own copy to extend. Defaults to `[]`.\n * `type` marks an image-collage `\"identity\"` sheet vs a plain `\"looks\"`\n * board; `sourceImages` are the R2 URLs it was collaged from. Both optional\n * + backward-compatible (legacy boards have neither). */\n boards?: Array<{ name: string; url: string; type?: \"looks\" | \"identity\"; sourceImages?: string[] }> | null\n /** The creature's voice (the \"talking creature\" stack) — same shape and\n * flow as `Character[\"voice\"]`. `null` when no voice is selected. */\n voice?: CreatureVoice | null\n referencePhotos: CreatureReferencePhoto[]\n /** `null` when no caption is set (or the LLM caption sub-failed) — the wire\n * sends `\"\"`, normalized to `null` in `get()` to match character semantics. */\n canonicalDescription: string | null\n styleLock: boolean\n /** The user's chosen DEFAULT asset take per variant (Studio version history).\n * OPAQUE map: key `\"<bucket>:<variant>\"` (e.g. `\"angles:front\"`) → the chosen\n * asset URL (one already present in that bucket). Stored verbatim — keys are\n * NOT normalized; soft-capped server-side at 200 keys / 2048-char values\n * (overflow dropped silently). Defaults to `{}`. */\n selectedAssetByVariant?: Record<string, string> | null\n /** Nodaro Keepers: whether this row is on the shared shelf (`client.keepers`).\n * Admin-set through `setCatalog`; `false` on everyone else's rows and on\n * every copy. Optional on the read surface for older servers. */\n catalog?: boolean\n /** The shelf order (lowest first); `0` when never set. */\n catalogSort?: number\n /** The shelf heading, or `null`. */\n catalogCategory?: string | null\n deletedAt: string | null\n createdAt: string\n updatedAt: string\n}\n\n/**\n * GET /v1/creatures/:id may append a `pendingJobs` bucket the studio uses to\n * rehydrate spinners after a reload. Optional on the SDK surface — it doesn't\n * appear on `list()` rows.\n */\nexport interface CreatureDetail extends Creature {\n pendingJobs?: Array<{\n jobId: string\n assetType: string\n name: string\n status: string\n }>\n}\n\n/**\n * Body for `client.creatures.create()`. Mirrors the INSERT branch of\n * `upsertCreatureBody` in `backend/src/routes/creatures.ts`. `name` + `nodeId`\n * are required on create.\n */\nexport interface CreateCreatureInput {\n nodeId: string\n name: string\n description?: string\n /** Free-text creature type/species (the creature delta vs object). */\n species?: string\n /** Free-text category (NOT object's fixed enum — a creature can be anything). */\n category?: string\n style?: string\n workflowId?: string\n projectId?: string\n sourceImageUrl?: string\n /** Persistent image-model id (a MODEL_CATALOG image model). Validated\n * server-side — unknown / non-image / \"\" is stored as `null`. */\n imageProvider?: string | null\n referencePhotos?: CreatureReferencePhoto[]\n canonicalDescription?: string\n styleLock?: boolean\n /** The user's chosen DEFAULT asset take per variant. OPAQUE\n * `\"<bucket>:<variant>\"` → chosen-URL map; a write REPLACES the whole map.\n * Keys stored verbatim; soft-capped server-side at 200 keys / 2048-char values. */\n selectedAssetByVariant?: Record<string, string>\n /** Initial voice selection (see `CreatureVoice`). Omit for a voiceless creature. */\n voice?: CreatureVoice | null\n}\n\n/**\n * Body for `client.creatures.update()`. Mirrors the UPDATE branch of\n * `upsertCreatureBody` in `backend/src/routes/creatures.ts`.\n *\n * Worker-owned asset buckets (`angles` / `poses` / `variations` /\n * `motionClips`) are deliberately omitted — the route drops them on UPDATE\n * so a Studio auto-save with a stale snapshot cannot clobber the worker's\n * atomic `append_creature_asset()` writes.\n *\n * `expectedUpdatedAt` is the optimistic-concurrency token: when present, the\n * UPDATE only succeeds if the row's `updated_at` still matches; on mismatch\n * the route returns 409 so the studio can re-fetch + merge.\n */\nexport interface UpdateCreatureInput {\n name?: string\n description?: string\n /** Free-text creature type/species (the creature delta vs object). */\n species?: string\n category?: string\n style?: string\n sourceImageUrl?: string\n /** Persistent image-model id (a MODEL_CATALOG image model). Validated\n * server-side — unknown / non-image / \"\" is stored as `null`. */\n imageProvider?: string | null\n referencePhotos?: CreatureReferencePhoto[]\n canonicalDescription?: string\n styleLock?: boolean\n /** The user's chosen DEFAULT asset take per variant. OPAQUE\n * `\"<bucket>:<variant>\"` → chosen-URL map; a write REPLACES the whole map\n * (omit to leave untouched). Keys stored verbatim; soft-capped server-side\n * at 200 keys / 2048-char values. */\n selectedAssetByVariant?: Record<string, string>\n /** Named Creature Boards (see `Creature.boards`) — whole-array replace,\n * USER-owned (unlike the worker-owned buckets it flows through UPDATE).\n * Server caps: 24 boards, 200-char names, 30 sourceImages per board. */\n boards?: Array<{ name: string; url: string; type?: \"looks\" | \"identity\"; sourceImages?: string[] }>\n /** Voice selection (see `CreatureVoice`) — whole-object replace; pass\n * `null` to clear the voice, omit to leave untouched. */\n voice?: CreatureVoice | null\n expectedUpdatedAt?: string\n}\n\nexport interface UpdateCreatureResult {\n id: string\n updatedAt: string\n}\n\n/**\n * Combined create + update body (parameter for both branches). Exported for\n * callers that want to drive a single `upsert` flow without picking between\n * `Create*` and `Update*`. Mirrors the `upsertCreatureBody` Zod schema in\n * `backend/src/routes/creatures.ts`. `nodeId` + `name` are required on INSERT;\n * `id` flips the route into UPDATE mode.\n */\nexport interface UpsertCreatureInput extends CreateCreatureInput {\n id?: string\n expectedUpdatedAt?: string\n}\n\nexport type UpsertCreatureResult = { id: string } | UpdateCreatureResult\n\nexport interface ListCreaturesParams {\n /** When true, return archived creatures instead of active ones. */\n archived?: boolean\n /** Optional project filter — server-scoped to the caller's user. */\n projectId?: string\n /**\n * Search words: only the creatures whose name or description contains\n * every word (split on spaces, the first 5), in any order, ignoring case.\n * Each word is matched as written (`%`, `_` and `*` are not wildcards;\n * punctuation is kept); blank means no search; up to 200 characters.\n * Combines with the other filters and with `cursor` paging.\n */\n q?: string\n /**\n * Max rows to return (cap 500). OPT-IN: omitted, the server returns the\n * full legacy listing with no `nextCursor`; supplied, the response is one\n * page plus `nextCursor` — keep passing it back until it is `null`.\n */\n limit?: number\n /** Opaque cursor from a prior page's `nextCursor` (fetches the next page). */\n cursor?: string\n}\n\n/**\n * Input for `client.creatures.generate()` — fires the\n * `POST /v1/generate-creature` route. Produces 1–10 candidate\n * main images; each lands as one `jobs` row in `pending` state and is then\n * enqueued for the worker.\n *\n * When `attachToCreatureId` is set AND `count === 1`, the worker writes the\n * resulting URL directly to `creatures.source_image_url` on completion —\n * caller doesn't need a separate `approveMainImage` call. Multi-candidate\n * batches MUST go through explicit approval so the user picks the winner.\n *\n * `seedPromptHint` flows the parameter-picker's prompt fragment through to the\n * worker so a catalog selection (e.g. \"armored frost dragon\") gets appended to\n * the generated prompt context.\n */\nexport interface GenerateCreatureInput extends GenerationSessionParams {\n name: string\n description?: string\n userPrompt?: string\n /** Free-text creature type/species (the creature delta vs object). */\n species?: string\n category?: string\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n sourceImageUrl?: string\n provider?: string\n /** Number of candidate images to generate (1–10; server-validated). */\n count?: number\n /** Auto-attach the result to this creature row (single-candidate only). */\n attachToCreatureId?: string\n /** Parameter-picker prompt-fragment pass-through. */\n seedPromptHint?: string\n /**\n * What the creature is, as picker-catalog ids ({@link Subject} — `animal`\n * above all; the same type and bounds as `generateImage`'s). The platform\n * writes the wording and folds it into the prompt after `description`, so\n * send ids rather than phrasing a pick yourself.\n */\n subject?: Subject\n /** Optional name to set on the attached row alongside the main image. */\n attachName?: string\n /** Optimistic-concurrency token for the single-candidate auto-attach path. */\n expectedUpdatedAt?: string\n}\n\n/**\n * `generate()` response — `jobIds` is ALWAYS present (the harmonized contract,\n * matching characters). `jobId` is a deprecated back-compat alias populated only\n * on `count === 1`; prefer `jobIds`. (Will be removed on the next major.)\n */\nexport interface GenerateCreatureResult {\n jobIds: string[]\n /** @deprecated count===1 back-compat alias — use `jobIds`. */\n jobId?: string\n}\n\n/**\n * Input for `client.creatures.generateAsset()` — fires the\n * `POST /v1/generate-creature-asset` route. Produces a single\n * angles / poses / variations / custom variant.\n *\n * When all three studio-path fields are set (`attachToCreatureId` +\n * `attachToColumn` + `attachName`), the worker appends\n * `{ name: attachName, url: <result> }` to the named JSONB array column on\n * the user's creature row on completion. `attachToColumn` is REQUIRED for\n * `assetType === \"custom\"` — the worker can't infer the bucket from the\n * asset type.\n */\nexport interface GenerateCreatureAssetInput extends GenerationSessionParams {\n assetType: CreatureAssetType\n variant: string\n name: string\n description?: string\n userPrompt?: string\n category?: string\n style?: string\n sourceImageUrl?: string\n provider?: string\n attachToCreatureId?: string\n attachToColumn?: CreatureAttachColumn\n attachName?: string\n /** Parameter-picker prompt-fragment pass-through. */\n seedPromptHint?: string\n}\n\nexport interface GenerateCreatureAssetResult {\n jobId: string\n}\n\n/**\n * Input for `client.creatures.generateMotion()` — fires the\n * `POST /v1/generate-creature-motion` route. Produces a single motion clip\n * (idle, prowl, attack, etc.) animated FROM a static creature-shot image.\n *\n * Mirrors `client.objects.generateMotion()` — the creature motion route reuses\n * the entity-agnostic object motion helpers server-side. The route hardcodes\n * the attach column to `motion_clips` — callers supply `attachToCreatureId` +\n * `attachName` only.\n *\n * `sourceImageUrl` is REQUIRED — image-to-video needs a source frame and the\n * route has no fallback (the studio path supplies the canonical creature-shot\n * URL explicitly).\n *\n * Defaults vs location:\n * - `provider` defaults to `\"kling-turbo\"` (not location's `\"kling\"`)\n * - `aspectRatio` defaults to `\"1:1\"` server-side via\n * `resolveObjectAspectRatio({ assetType: \"motion\" })` — creatures use\n * centered reference framing, not cinematic establishing shots.\n *\n * When the studio path is set (`attachToCreatureId` + `attachName`), the\n * worker appends `{ name: attachName, url: <result> }` to the creature row's\n * `motion_clips` JSONB column on completion.\n */\nexport interface GenerateCreatureMotionInput extends GenerationSessionParams {\n motionPrompt: string\n sourceImageUrl: string\n provider?: string\n name: string\n /** Source clip URL — when set, worker routes to video-to-video refine. */\n refineFromVideoUrl?: string\n category?: string\n style?: \"realistic\" | \"anime\" | \"3d-pixar\" | \"illustration\"\n canonicalDescription?: string\n /** Parameter-picker prompt-fragment pass-through. */\n seedPromptHint?: string\n attachToCreatureId?: string\n attachName?: string\n /**\n * Optional aspect ratio override. Defaults to 1:1 server-side. One of the\n * 5-value `CreatureAspectRatio` union (1:1 / 3:4 / 16:9 / 9:16 / 4:3) — the\n * creature route reuses the object aspect enum.\n */\n aspectRatio?: ObjectAspectRatio\n /**\n * Optional clip duration in seconds. Validated server-side against the chosen\n * provider's allowed durations (e.g. kling 5/10, wan-i2v 5/10/15); omitted →\n * the model's own default (no behavior change). Mirrors generate-video's\n * per-model i2v duration lever.\n */\n duration?: number\n}\n\nexport interface GenerateCreatureMotionResult {\n jobId: string\n}\n\nexport interface ApproveCreatureMainImageResult {\n sourceImageUrl: string\n /**\n * LLM-authored caption. `null` when the LLM caption sub-failed — the wire\n * sends `\"\"`, normalized to `null` here so consumers see the same\n * `string | null` semantics as characters. The main image is still set; call\n * `recaption()` to retry.\n */\n canonicalDescription: string | null\n}\n\nexport interface RecaptionCreatureResult {\n canonicalDescription: string\n}\n\nexport class CreaturesResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * List the caller's creatures. By default returns active creatures only;\n * pass `archived: true` to fetch soft-deleted rows for an \"archive\" view.\n * Optional `projectId` scopes the result to a single project; `q` keeps the\n * creatures whose name or description contains it.\n */\n list(params: ListCreaturesParams = {}): Promise<{ creatures: Creature[]; nextCursor?: string | null }> {\n const query: Record<string, string | undefined> = {}\n if (params.archived) query.archived = \"true\"\n if (params.projectId) query.projectId = params.projectId\n if (params.q) query.q = params.q\n if (params.limit !== undefined) query.limit = String(params.limit)\n if (params.cursor) query.cursor = params.cursor\n return this.client.request(\"GET\", \"/v1/creatures\", { query })\n }\n\n /**\n * Convenience wrapper for `list({ archived: true })`. Returns soft-deleted\n * rows so callers can drive a UI \"Archived\" tab without re-encoding the\n * query param.\n *\n * `archived` is omitted from the param type — it's always set to `true` here.\n */\n listArchived(params: Omit<ListCreaturesParams, \"archived\"> = {}): Promise<{ creatures: Creature[]; nextCursor?: string | null }> {\n return this.list({ ...params, archived: true })\n }\n\n /**\n * Fetch a single creature including in-flight asset job state. Soft-deleted\n * (archived) rows are NOT returned by id — the route enforces\n * `deleted_at IS NULL` so archived creatures 404 (uniform \"not_found\" — does\n * not leak the deleted vs non-existent distinction).\n */\n async get(id: string): Promise<CreatureDetail> {\n const res = await this.client.request<CreatureDetail>(\n \"GET\",\n `/v1/creatures/${encodeURIComponent(id)}`,\n )\n // Normalize the wire `\"\"` caption (DB null / LLM sub-failure) → null so\n // consumers see the same `string | null` semantics as characters. New\n // object — never mutate the response.\n return { ...res, canonicalDescription: res.canonicalDescription || null }\n }\n\n /**\n * Create a new creature. `name` + `nodeId` are required — the route 400s\n * otherwise. Returns the new row's id.\n *\n * Note: the underlying route is the same `POST /v1/creatures` upsert that\n * powers `update()`. This convenience wrapper enforces the INSERT-required\n * fields at the type level and never sends an `id`.\n */\n create(data: CreateCreatureInput): Promise<{ id: string }> {\n return this.client.request(\"POST\", \"/v1/creatures\", { body: data })\n }\n\n /**\n * Update a creature. Only the fields you pass are written — undefined keys\n * are NOT touched on the row. Worker-owned asset buckets are intentionally\n * not exposed on this surface (see `UpdateCreatureInput` for the rationale).\n *\n * Optimistic-concurrency: pass `expectedUpdatedAt` to require the row's\n * `updated_at` still matches; on mismatch the route returns 409\n * `concurrent_modification` carrying the fresh `updatedAt`. The SDK\n * surfaces that as a generic `NodaroError` with the same code.\n */\n update(id: string, data: UpdateCreatureInput): Promise<UpdateCreatureResult> {\n return this.client.request(\"POST\", \"/v1/creatures\", {\n body: { id, ...data },\n })\n }\n\n /**\n * Soft-delete (archive) a creature. The row is hidden from `list()` by\n * default but recoverable via `restore(id)` or visible under\n * `listArchived()`. Idempotent — repeating a delete on an already-archived\n * row is a no-op.\n */\n delete(id: string): Promise<{ success: true; archived: true }> {\n return this.client.request(\"DELETE\", `/v1/creatures/${encodeURIComponent(id)}`)\n }\n\n /**\n * Hard-delete (permanent) a creature — the row + every R2 asset it\n * references. Archived rows ONLY: active creatures return 400 `not_archived`.\n * Call `delete()` first to archive, then `permanentDelete()` to destroy.\n *\n * Mirrors the `app_runs` permanent-delete pattern (archive-first) so a\n * stray SDK / curl caller cannot bypass the studio's archive-first UI\n * flow.\n */\n permanentDelete(id: string): Promise<{ success: true; permanent: true }> {\n return this.client.request(\"DELETE\", `/v1/creatures/${encodeURIComponent(id)}`, {\n query: { permanent: \"true\" },\n })\n }\n\n /**\n * Un-archive a creature. If the original name now collides (case-\n * insensitive) with an active row, the server auto-suffixes \"(restored)\"\n * and returns the effective name.\n */\n restore(id: string): Promise<{ id: string; name: string }> {\n return this.client.request(\"POST\", `/v1/creatures/${encodeURIComponent(id)}/restore`)\n }\n\n /**\n * Admin only: put one of your own creatures on the shared Nodaro Keepers\n * shelf (`client.keepers.catalog()`), or take it off. A first-party session\n * or your personal token; `forbidden` for anyone who is not a platform\n * admin, `not_found` for a row that is not yours.\n */\n setCatalog(id: string, input: SetKeeperCatalogInput): Promise<SetKeeperCatalogResult> {\n return this.client.request(\"PUT\", `/v1/creatures/${encodeURIComponent(id)}/catalog`, { body: input })\n }\n\n /**\n * Fire `POST /v1/generate-creature` to produce one or more candidate main\n * images. With `count > 1`, all jobs are reserved up-front before any\n * is enqueued — mid-batch failures roll back atomically.\n *\n * When `attachToCreatureId` is set AND `count === 1`, the worker writes\n * the result directly to the row's `source_image_url`; otherwise you must\n * call `approveMainImage()` after picking a candidate.\n */\n async generate(data: GenerateCreatureInput): Promise<GenerateCreatureResult> {\n const res = await this.client.request<{ jobId?: string; jobIds?: string[] }>(\n \"POST\", \"/v1/generate-creature\", { body: data },\n )\n // Tolerate the legacy `{ jobId }`-only shape (older server): synthesize jobIds.\n const jobIds = res.jobIds ?? (res.jobId ? [res.jobId] : [])\n return res.jobId ? { jobIds, jobId: res.jobId } : { jobIds }\n }\n\n /**\n * Fire `POST /v1/generate-creature-asset` to produce a single variant.\n * When the studio path is set (`attachToCreatureId` + `attachToColumn` +\n * `attachName`), the worker appends `{ name: attachName, url: <result> }`\n * to the named JSONB array column on completion.\n *\n * Note: `attachToColumn` is REQUIRED for `assetType === \"custom\"` — the\n * worker can't infer the bucket from the asset type. For canonical asset\n * types (`angles` / `poses` / `variations`), the column is derived\n * automatically by the route.\n */\n generateAsset(\n data: GenerateCreatureAssetInput,\n ): Promise<GenerateCreatureAssetResult> {\n return this.client.request(\"POST\", \"/v1/generate-creature-asset\", { body: data })\n }\n\n /**\n * Fire `POST /v1/generate-creature-motion` to animate the creature's main\n * image into a motion clip. Image-to-video, single clip per call; the\n * attach column is hardcoded to `motion_clips` server-side (creatures have a\n * single motion bucket so the caller doesn't supply `attachToColumn`).\n * When the studio path is set (`attachToCreatureId` + `attachName`), the\n * worker appends `{ name: attachName, url: <result> }` to the row's\n * `motion_clips` column on completion.\n *\n * Defaults: `provider` → `\"kling-turbo\"`, `aspectRatio` → `\"1:1\"` (set\n * server-side via `resolveObjectAspectRatio({ assetType: \"motion\" })`).\n */\n generateMotion(\n data: GenerateCreatureMotionInput,\n ): Promise<GenerateCreatureMotionResult> {\n return this.client.request(\"POST\", \"/v1/generate-creature-motion\", { body: data })\n }\n\n /**\n * Approve a completed `generate-creature` job as the creature's main image.\n * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)\n * inline. Returns the new main-image URL plus the caption.\n *\n * Caption-failure semantics: the route still sends `\"\"` on LLM sub-failure,\n * but the SDK normalizes `\"\"` → `null` here so `canonicalDescription` carries\n * the same `string | null` semantics as characters. The main image is still\n * set; call `recaption()` to retry.\n *\n * Optimistic-concurrency: pass `expectedUpdatedAt` to gate the update on\n * the row's current `updated_at`; on mismatch the route returns 409\n * `concurrent_modification` carrying the fresh token.\n */\n async approveMainImage(\n id: string,\n candidateJobId: string,\n expectedUpdatedAt?: string,\n ): Promise<ApproveCreatureMainImageResult> {\n const res = await this.client.request<{ sourceImageUrl: string; canonicalDescription: string | null }>(\n \"POST\",\n `/v1/creatures/${encodeURIComponent(id)}/approve-main-image`,\n { body: { candidateJobId, expectedUpdatedAt } },\n )\n // Normalize the wire `\"\"` (LLM sub-failure) → null; build a new object\n // rather than mutating the response.\n return { sourceImageUrl: res.sourceImageUrl, canonicalDescription: res.canonicalDescription || null }\n }\n\n /**\n * Re-fire the LLM caption against the creature's current main image. 502s\n * on LLM failure (unlike `approveMainImage` which preserves the side-effect\n * and returns \"\"); returns 400 `main_image_required` if no main image is\n * set yet.\n *\n * The route is a pure idempotent retry — it does NOT accept an\n * `expectedUpdatedAt` token (backend route is idempotent retry, not gated on\n * optimistic-concurrency).\n */\n recaption(id: string): Promise<RecaptionCreatureResult> {\n return this.client.request(\n \"POST\",\n `/v1/creatures/${encodeURIComponent(id)}/llm-caption`,\n )\n }\n}\n"]}
|
|
@@ -205,5 +205,5 @@ Object.defineProperty(exports, "SURROUND_DIRECTIONS", {
|
|
|
205
205
|
get: function () { return entities.SURROUND_DIRECTIONS; }
|
|
206
206
|
});
|
|
207
207
|
exports.LocationsResource = LocationsResource;
|
|
208
|
-
//# sourceMappingURL=chunk-
|
|
209
|
-
//# sourceMappingURL=chunk-
|
|
208
|
+
//# sourceMappingURL=chunk-MIXRL6I2.cjs.map
|
|
209
|
+
//# sourceMappingURL=chunk-MIXRL6I2.cjs.map
|