From 3c89cf2d27cc6d9979c2f9cbbb6feade2c42e26f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:30:49 +0000 Subject: [PATCH 1/7] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 9a0231e..720cb80 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 14 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml%2Frunwayml-b3276a8508268090b14e297f5cb18448da7a763653c6d38c23f0eea0984d8008.yml openapi_spec_hash: 95ae975f17217c8d144c4ba80846beca -config_hash: 3a3a9803a21ef667a2d3a91023a5cb9d +config_hash: 803d5c0aa94eea0a7981b91728218d3f From bdc20f12c6558a6f405f0790b1601d4bbf2b9078 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:04:16 +0000 Subject: [PATCH 2/7] chore(internal): move stringifyQuery implementation to internal function --- src/client.ts | 22 +++++----------------- src/internal/utils.ts | 1 + src/internal/utils/query.ts | 23 +++++++++++++++++++++++ tests/stringifyQuery.test.ts | 6 ++---- 4 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 src/internal/utils/query.ts diff --git a/src/client.ts b/src/client.ts index 7f18718..6013426 100644 --- a/src/client.ts +++ b/src/client.ts @@ -11,6 +11,7 @@ import type { APIResponseProps } from './internal/parse'; import { getPlatformHeaders } from './internal/detect-platform'; import * as Shims from './internal/shims'; import * as Opts from './internal/request-options'; +import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; import * as UploadsCore from './core/uploads'; @@ -273,21 +274,8 @@ export class RunwayML { /** * Basic re-implementation of `qs.stringify` for primitive types. */ - protected stringifyQuery(query: Record): string { - return Object.entries(query) - .filter(([_, value]) => typeof value !== 'undefined') - .map(([key, value]) => { - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { - return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; - } - if (value === null) { - return `${encodeURIComponent(key)}=`; - } - throw new Errors.RunwayMLError( - `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, - ); - }) - .join('&'); + protected stringifyQuery(query: object | Record): string { + return stringifyQuery(query); } private getUserAgent(): string { @@ -324,7 +312,7 @@ export class RunwayML { } if (typeof query === 'object' && query && !Array.isArray(query)) { - url.search = this.stringifyQuery(query as Record); + url.search = this.stringifyQuery(query); } return url.toString(); @@ -764,7 +752,7 @@ export class RunwayML { ) { return { bodyHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, - body: this.stringifyQuery(body as Record), + body: this.stringifyQuery(body), }; } else { return this.#encoder({ body, headers }); diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 3cbfacc..c591353 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -6,3 +6,4 @@ export * from './utils/env'; export * from './utils/log'; export * from './utils/uuid'; export * from './utils/sleep'; +export * from './utils/query'; diff --git a/src/internal/utils/query.ts b/src/internal/utils/query.ts new file mode 100644 index 0000000..a316c98 --- /dev/null +++ b/src/internal/utils/query.ts @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { RunwayMLError } from '../../core/error'; + +/** + * Basic re-implementation of `qs.stringify` for primitive types. + */ +export function stringifyQuery(query: object | Record) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new RunwayMLError( + `Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`, + ); + }) + .join('&'); +} diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 22c1d3f..7e7614b 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -1,8 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { RunwayML } from '@runwayml/sdk'; - -const { stringifyQuery } = RunwayML.prototype as any; +import { stringifyQuery } from '@runwayml/sdk/internal/utils/query'; describe(stringifyQuery, () => { for (const [input, expected] of [ @@ -15,7 +13,7 @@ describe(stringifyQuery, () => { 'e=f', )}=${encodeURIComponent('g&h')}`, ], - ]) { + ] as const) { it(`${JSON.stringify(input)} -> ${expected}`, () => { expect(stringifyQuery(input)).toEqual(expected); }); From 322c513a65a9250c65215cc636ee1ca061c1592a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:12:03 +0000 Subject: [PATCH 3/7] chore(docs): add missing descriptions --- src/client.ts | 33 ++++++++++++++++++++++++++ src/resources/character-performance.ts | 3 +++ src/resources/image-to-video.ts | 3 +++ src/resources/sound-effect.ts | 3 +++ src/resources/speech-to-speech.ts | 3 +++ src/resources/tasks.ts | 3 +++ src/resources/text-to-image.ts | 3 +++ src/resources/text-to-speech.ts | 3 +++ src/resources/text-to-video.ts | 3 +++ src/resources/video-to-video.ts | 3 +++ src/resources/voice-dubbing.ts | 3 +++ src/resources/voice-isolation.ts | 3 +++ 12 files changed, 66 insertions(+) diff --git a/src/client.ts b/src/client.ts index 6013426..4904a5f 100644 --- a/src/client.ts +++ b/src/client.ts @@ -778,16 +778,49 @@ export class RunwayML { static toFile = UploadsCore.toFile; + /** + * Endpoints for managing tasks that have been submitted. + */ tasks: API.Tasks = new API.Tasks(this); + /** + * These endpoints all kick off tasks to create generations. + */ imageToVideo: API.ImageToVideo = new API.ImageToVideo(this); + /** + * These endpoints all kick off tasks to create generations. + */ videoToVideo: API.VideoToVideo = new API.VideoToVideo(this); + /** + * These endpoints all kick off tasks to create generations. + */ textToVideo: API.TextToVideo = new API.TextToVideo(this); + /** + * These endpoints all kick off tasks to create generations. + */ textToImage: API.TextToImage = new API.TextToImage(this); + /** + * These endpoints all kick off tasks to create generations. + */ characterPerformance: API.CharacterPerformance = new API.CharacterPerformance(this); + /** + * These endpoints all kick off tasks to create generations. + */ textToSpeech: API.TextToSpeech = new API.TextToSpeech(this); + /** + * These endpoints all kick off tasks to create generations. + */ soundEffect: API.SoundEffect = new API.SoundEffect(this); + /** + * These endpoints all kick off tasks to create generations. + */ voiceIsolation: API.VoiceIsolation = new API.VoiceIsolation(this); + /** + * These endpoints all kick off tasks to create generations. + */ voiceDubbing: API.VoiceDubbing = new API.VoiceDubbing(this); + /** + * These endpoints all kick off tasks to create generations. + */ speechToSpeech: API.SpeechToSpeech = new API.SpeechToSpeech(this); organization: API.Organization = new API.Organization(this); uploads: API.Uploads = new API.Uploads(this); diff --git a/src/resources/character-performance.ts b/src/resources/character-performance.ts index f14bfd5..bc15269 100644 --- a/src/resources/character-performance.ts +++ b/src/resources/character-performance.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class CharacterPerformance extends APIResource { /** * This endpoint will start a new task to control a character's facial expressions diff --git a/src/resources/image-to-video.ts b/src/resources/image-to-video.ts index 31c0e77..b53f124 100644 --- a/src/resources/image-to-video.ts +++ b/src/resources/image-to-video.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class ImageToVideo extends APIResource { /** * This endpoint will start a new task to generate a video from an image. diff --git a/src/resources/sound-effect.ts b/src/resources/sound-effect.ts index ebf48fb..8d60c49 100644 --- a/src/resources/sound-effect.ts +++ b/src/resources/sound-effect.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class SoundEffect extends APIResource { /** * This endpoint will start a new task to generate sound effects from a text diff --git a/src/resources/speech-to-speech.ts b/src/resources/speech-to-speech.ts index ec35929..ac13c32 100644 --- a/src/resources/speech-to-speech.ts +++ b/src/resources/speech-to-speech.ts @@ -3,6 +3,9 @@ import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/poll import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; +/** + * These endpoints all kick off tasks to create generations. + */ export class SpeechToSpeech extends APIResource { /** * This endpoint will start a new task to convert speech from one voice to another diff --git a/src/resources/tasks.ts b/src/resources/tasks.ts index c1bc280..b6b53e4 100644 --- a/src/resources/tasks.ts +++ b/src/resources/tasks.ts @@ -7,6 +7,9 @@ import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * Endpoints for managing tasks that have been submitted. + */ export class Tasks extends APIResource { /** * Return details about a task. Consumers of this API should not expect updates diff --git a/src/resources/text-to-image.ts b/src/resources/text-to-image.ts index aa4b269..0821eea 100644 --- a/src/resources/text-to-image.ts +++ b/src/resources/text-to-image.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class TextToImage extends APIResource { /** * This endpoint will start a new task to generate images from text and/or image(s) diff --git a/src/resources/text-to-speech.ts b/src/resources/text-to-speech.ts index 2e0837c..f02d026 100644 --- a/src/resources/text-to-speech.ts +++ b/src/resources/text-to-speech.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class TextToSpeech extends APIResource { /** * This endpoint will start a new task to generate speech from text. diff --git a/src/resources/text-to-video.ts b/src/resources/text-to-video.ts index f8a7fb2..f2434a1 100644 --- a/src/resources/text-to-video.ts +++ b/src/resources/text-to-video.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class TextToVideo extends APIResource { /** * This endpoint will start a new task to generate a video from a text prompt. diff --git a/src/resources/video-to-video.ts b/src/resources/video-to-video.ts index 43cf1e2..947bc11 100644 --- a/src/resources/video-to-video.ts +++ b/src/resources/video-to-video.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class VideoToVideo extends APIResource { /** * This endpoint will start a new task to generate a video from a video. diff --git a/src/resources/voice-dubbing.ts b/src/resources/voice-dubbing.ts index 2936baf..1acc2ab 100644 --- a/src/resources/voice-dubbing.ts +++ b/src/resources/voice-dubbing.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class VoiceDubbing extends APIResource { /** * This endpoint will start a new task to dub audio content to a target language. diff --git a/src/resources/voice-isolation.ts b/src/resources/voice-isolation.ts index ff2387b..78eea0b 100644 --- a/src/resources/voice-isolation.ts +++ b/src/resources/voice-isolation.ts @@ -4,6 +4,9 @@ import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { APIPromiseWithAwaitableTask, wrapAsWaitableResource } from '../lib/polling'; +/** + * These endpoints all kick off tasks to create generations. + */ export class VoiceIsolation extends APIResource { /** * This endpoint will start a new task to isolate the voice from the background From 0a0a653562760410cbe9425ab6ef118ee8682546 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:24:42 +0000 Subject: [PATCH 4/7] fix: fix request delays for retrying to be more respectful of high requested delays --- src/client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.ts b/src/client.ts index 4904a5f..d5fd3c1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -617,9 +617,9 @@ export class RunwayML { } } - // If the API asks us to wait a certain amount of time (and it's a reasonable amount), - // just do what it says, but otherwise calculate a default - if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + // If the API asks us to wait a certain amount of time, just do what it + // says, but otherwise calculate a default + if (timeoutMillis === undefined) { const maxRetries = options.maxRetries ?? this.maxRetries; timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); } From a5761c04cc605146aa284eeefcaf1f23bd7ab0ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 11:44:52 +0000 Subject: [PATCH 5/7] chore(test): do not count install time for mock server timeout --- scripts/mock | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/mock b/scripts/mock index 0b28f6e..bcf3b39 100755 --- a/scripts/mock +++ b/scripts/mock @@ -21,11 +21,22 @@ echo "==> Starting mock server with URL ${URL}" # Run prism mock on the given spec if [ "$1" == "--daemon" ]; then + # Pre-install the package so the download doesn't eat into the startup timeout + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & - # Wait for server to come online + # Wait for server to come online (max 30s) echo -n "Waiting for server" + attempts=0 while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + attempts=$((attempts + 1)) + if [ "$attempts" -ge 300 ]; then + echo + echo "Timed out waiting for Prism server to start" + cat .prism.log + exit 1 + fi echo -n "." sleep 0.1 done From 9534a7e892b9b11d7c2420a0b79b4c065b820a42 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:50:17 +0000 Subject: [PATCH 6/7] feat(api): add avatar, voice, document, and realtime session endpoints --- .stats.yml | 8 +- MIGRATION.md | 38 + README.md | 31 + api.md | 62 + src/client.ts | 115 + src/core/pagination.ts | 157 ++ src/index.ts | 1 + src/pagination.ts | 2 + src/resources/avatars.ts | 2049 +++++++++++++++++ src/resources/documents.ts | 270 +++ src/resources/index.ts | 37 + src/resources/organization.ts | 6 +- src/resources/realtime-sessions.ts | 251 ++ src/resources/voices.ts | 345 +++ tests/api-resources/avatars.test.ts | 108 + tests/api-resources/documents.test.ts | 68 + tests/api-resources/realtime-sessions.test.ts | 54 + tests/api-resources/voices.test.ts | 98 + 18 files changed, 3695 insertions(+), 5 deletions(-) create mode 100644 src/core/pagination.ts create mode 100644 src/pagination.ts create mode 100644 src/resources/avatars.ts create mode 100644 src/resources/documents.ts create mode 100644 src/resources/realtime-sessions.ts create mode 100644 src/resources/voices.ts create mode 100644 tests/api-resources/avatars.test.ts create mode 100644 tests/api-resources/documents.test.ts create mode 100644 tests/api-resources/realtime-sessions.test.ts create mode 100644 tests/api-resources/voices.test.ts diff --git a/.stats.yml b/.stats.yml index 720cb80..e306cf4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml%2Frunwayml-b3276a8508268090b14e297f5cb18448da7a763653c6d38c23f0eea0984d8008.yml -openapi_spec_hash: 95ae975f17217c8d144c4ba80846beca -config_hash: 803d5c0aa94eea0a7981b91728218d3f +configured_endpoints: 31 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runwayml%2Frunwayml-4ddc8e3d83c8601fc378c702bbcb5af2976b481db513bd389a5f57645a20cd04.yml +openapi_spec_hash: 5795c6af9e9404765bda670e781fe500 +config_hash: 3c88fcd4dd6f3a7d7f6e94b57b430243 diff --git a/MIGRATION.md b/MIGRATION.md index 1795f32..e7b187e 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -54,6 +54,7 @@ client.example.list(undefined, { headers: { ... } }); This affects the following methods: - `client.organization.retrieveUsage()` +- `client.avatars.update()` ### Removed `httpAgent` in favor of `fetchOptions` @@ -151,6 +152,43 @@ import RunwayML from '@runwayml/sdk'; The `@runwayml/sdk/shims` imports have been removed. Your global types must now be [correctly configured](#minimum-types-requirements). +### Pagination changes + +The `for await` syntax **is not affected**. This still works as-is: + +```ts +// Automatically fetches more pages as needed. +for await (const avatarListResponse of client.avatars.list({ limit: 1 })) { + console.log(avatarListResponse); +} +``` + +The interface for manually paginating through list results has been simplified: + +```ts +// Before +page.nextPageParams(); +page.nextPageInfo(); +// Required manually handling { url } | { params } type + +// After +page.nextPageRequestOptions(); +``` + +#### Removed unnecessary classes + +Page classes for individual methods are now type aliases: + +```ts +// Before +export class AvatarListResponsesCursorPage extends CursorPage {} + +// After +export type AvatarListResponsesCursorPage = CursorPage; +``` + +If you were importing these classes at runtime, you'll need to switch to importing the base class or only import them at the type-level. + ### `@runwayml/sdk/src` directory removed Previously IDEs may have auto-completed imports from the `@runwayml/sdk/src` directory, however this diff --git a/README.md b/README.md index 2d81afc..bfaff95 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,37 @@ On timeout, an `APIConnectionTimeoutError` is thrown. Note that requests which time out will be [retried twice by default](#retries). +## Auto-pagination + +List methods in the RunwayML API are paginated. +You can use the `for await … of` syntax to iterate through items across all pages: + +```ts +async function fetchAllAvatarListResponses(params) { + const allAvatarListResponses = []; + // Automatically fetches more pages as needed. + for await (const avatarListResponse of client.avatars.list({ limit: 1 })) { + allAvatarListResponses.push(avatarListResponse); + } + return allAvatarListResponses; +} +``` + +Alternatively, you can request a single page at a time: + +```ts +let page = await client.avatars.list({ limit: 1 }); +for (const avatarListResponse of page.data) { + console.log(avatarListResponse); +} + +// Convenience methods are provided for manually paginating: +while (page.hasNextPage()) { + page = await page.getNextPage(); + // ... +} +``` + ## Advanced Usage ### Accessing raw Response data (e.g., headers) diff --git a/api.md b/api.md index 620f9ca..e07d3df 100644 --- a/api.md +++ b/api.md @@ -120,3 +120,65 @@ Methods: - client.organization.retrieve() -> OrganizationRetrieveResponse - client.organization.retrieveUsage({ ...params }) -> OrganizationRetrieveUsageResponse + +# Avatars + +Types: + +- AvatarCreateResponse +- AvatarRetrieveResponse +- AvatarUpdateResponse +- AvatarListResponse + +Methods: + +- client.avatars.create({ ...params }) -> AvatarCreateResponse +- client.avatars.retrieve(id) -> AvatarRetrieveResponse +- client.avatars.update(id, { ...params }) -> AvatarUpdateResponse +- client.avatars.list({ ...params }) -> AvatarListResponsesCursorPage +- client.avatars.delete(id) -> void + +# Documents + +Types: + +- DocumentCreateResponse +- DocumentRetrieveResponse +- DocumentListResponse + +Methods: + +- client.documents.create({ ...params }) -> DocumentCreateResponse +- client.documents.retrieve(id) -> DocumentRetrieveResponse +- client.documents.list({ ...params }) -> DocumentListResponsesCursorPage +- client.documents.delete(id) -> void + +# RealtimeSessions + +Types: + +- RealtimeSessionCreateResponse +- RealtimeSessionRetrieveResponse + +Methods: + +- client.realtimeSessions.create({ ...params }) -> RealtimeSessionCreateResponse +- client.realtimeSessions.retrieve(id) -> RealtimeSessionRetrieveResponse +- client.realtimeSessions.delete(id) -> void + +# Voices + +Types: + +- VoiceCreateResponse +- VoiceRetrieveResponse +- VoiceListResponse +- VoicePreviewResponse + +Methods: + +- client.voices.create({ ...params }) -> VoiceCreateResponse +- client.voices.retrieve(id) -> VoiceRetrieveResponse +- client.voices.list({ ...params }) -> VoiceListResponsesCursorPage +- client.voices.delete(id) -> void +- client.voices.preview({ ...params }) -> VoicePreviewResponse diff --git a/src/client.ts b/src/client.ts index d5fd3c1..99d2f98 100644 --- a/src/client.ts +++ b/src/client.ts @@ -14,14 +14,36 @@ import * as Opts from './internal/request-options'; import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; +import * as Pagination from './core/pagination'; +import { AbstractPage, type CursorPageParams, CursorPageResponse } from './core/pagination'; import * as UploadsCore from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; +import { + AvatarCreateParams, + AvatarCreateResponse, + AvatarListParams, + AvatarListResponse, + AvatarListResponsesCursorPage, + AvatarRetrieveResponse, + AvatarUpdateParams, + AvatarUpdateResponse, + Avatars, +} from './resources/avatars'; import { CharacterPerformance, CharacterPerformanceCreateParams, CharacterPerformanceCreateResponse, } from './resources/character-performance'; +import { + DocumentCreateParams, + DocumentCreateResponse, + DocumentListParams, + DocumentListResponse, + DocumentListResponsesCursorPage, + DocumentRetrieveResponse, + Documents, +} from './resources/documents'; import { ImageToVideo, ImageToVideoCreateParams, @@ -33,6 +55,12 @@ import { OrganizationRetrieveUsageParams, OrganizationRetrieveUsageResponse, } from './resources/organization'; +import { + RealtimeSessionCreateParams, + RealtimeSessionCreateResponse, + RealtimeSessionRetrieveResponse, + RealtimeSessions, +} from './resources/realtime-sessions'; import { SoundEffect, SoundEffectCreateParams, SoundEffectCreateResponse } from './resources/sound-effect'; import { SpeechToSpeech, @@ -63,6 +91,17 @@ import { VoiceIsolationCreateResponse, } from './resources/voice-isolation'; import { Uploads, UploadsCreateEphemeralParams, UploadCreateEphemeralResponse } from './resources/uploads'; +import { + VoiceCreateParams, + VoiceCreateResponse, + VoiceListParams, + VoiceListResponse, + VoiceListResponsesCursorPage, + VoicePreviewParams, + VoicePreviewResponse, + VoiceRetrieveResponse, + Voices, +} from './resources/voices'; import { type Fetch } from './internal/builtin-types'; import { isRunningInBrowser } from './internal/detect-platform'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; @@ -530,6 +569,30 @@ export class RunwayML { return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; } + getAPIList = Pagination.AbstractPage>( + path: string, + Page: new (...args: any[]) => PageClass, + opts?: PromiseOrValue, + ): Pagination.PagePromise { + return this.requestAPIList( + Page, + opts && 'then' in opts ? + opts.then((opts) => ({ method: 'get', path, ...opts })) + : { method: 'get', path, ...opts }, + ); + } + + requestAPIList< + Item = unknown, + PageClass extends Pagination.AbstractPage = Pagination.AbstractPage, + >( + Page: new (...args: ConstructorParameters) => PageClass, + options: PromiseOrValue, + ): Pagination.PagePromise { + const request = this.makeRequest(options, null, undefined); + return new Pagination.PagePromise(this as any as RunwayML, request, Page); + } + async fetchWithTimeout( url: RequestInfo, init: RequestInit | undefined, @@ -823,6 +886,10 @@ export class RunwayML { */ speechToSpeech: API.SpeechToSpeech = new API.SpeechToSpeech(this); organization: API.Organization = new API.Organization(this); + avatars: API.Avatars = new API.Avatars(this); + documents: API.Documents = new API.Documents(this); + realtimeSessions: API.RealtimeSessions = new API.RealtimeSessions(this); + voices: API.Voices = new API.Voices(this); uploads: API.Uploads = new API.Uploads(this); } @@ -838,11 +905,18 @@ RunwayML.VoiceIsolation = VoiceIsolation; RunwayML.VoiceDubbing = VoiceDubbing; RunwayML.SpeechToSpeech = SpeechToSpeech; RunwayML.Organization = Organization; +RunwayML.Avatars = Avatars; +RunwayML.Documents = Documents; +RunwayML.RealtimeSessions = RealtimeSessions; +RunwayML.Voices = Voices; RunwayML.Uploads = Uploads; export declare namespace RunwayML { export type RequestOptions = Opts.RequestOptions; + export import CursorPage = Pagination.CursorPage; + export { type CursorPageParams as CursorPageParams, type CursorPageResponse as CursorPageResponse }; + export { Tasks as Tasks, type TaskRetrieveResponse as TaskRetrieveResponse }; export { @@ -912,6 +986,47 @@ export declare namespace RunwayML { type OrganizationRetrieveUsageParams as OrganizationRetrieveUsageParams, }; + export { + Avatars as Avatars, + type AvatarCreateResponse as AvatarCreateResponse, + type AvatarRetrieveResponse as AvatarRetrieveResponse, + type AvatarUpdateResponse as AvatarUpdateResponse, + type AvatarListResponse as AvatarListResponse, + type AvatarListResponsesCursorPage as AvatarListResponsesCursorPage, + type AvatarCreateParams as AvatarCreateParams, + type AvatarUpdateParams as AvatarUpdateParams, + type AvatarListParams as AvatarListParams, + }; + + export { + Documents as Documents, + type DocumentCreateResponse as DocumentCreateResponse, + type DocumentRetrieveResponse as DocumentRetrieveResponse, + type DocumentListResponse as DocumentListResponse, + type DocumentListResponsesCursorPage as DocumentListResponsesCursorPage, + type DocumentCreateParams as DocumentCreateParams, + type DocumentListParams as DocumentListParams, + }; + + export { + RealtimeSessions as RealtimeSessions, + type RealtimeSessionCreateResponse as RealtimeSessionCreateResponse, + type RealtimeSessionRetrieveResponse as RealtimeSessionRetrieveResponse, + type RealtimeSessionCreateParams as RealtimeSessionCreateParams, + }; + + export { + Voices as Voices, + type VoiceCreateResponse as VoiceCreateResponse, + type VoiceRetrieveResponse as VoiceRetrieveResponse, + type VoiceListResponse as VoiceListResponse, + type VoicePreviewResponse as VoicePreviewResponse, + type VoiceListResponsesCursorPage as VoiceListResponsesCursorPage, + type VoiceCreateParams as VoiceCreateParams, + type VoiceListParams as VoiceListParams, + type VoicePreviewParams as VoicePreviewParams, + }; + export { Uploads as Uploads, type UploadCreateEphemeralResponse as UploadCreateEphemeralResponse, diff --git a/src/core/pagination.ts b/src/core/pagination.ts new file mode 100644 index 0000000..c2f15a7 --- /dev/null +++ b/src/core/pagination.ts @@ -0,0 +1,157 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { RunwayMLError } from './error'; +import { FinalRequestOptions } from '../internal/request-options'; +import { defaultParseResponse } from '../internal/parse'; +import { type RunwayML } from '../client'; +import { APIPromise } from './api-promise'; +import { type APIResponseProps } from '../internal/parse'; +import { maybeObj } from '../internal/utils/values'; + +export type PageRequestOptions = Pick; + +export abstract class AbstractPage implements AsyncIterable { + #client: RunwayML; + protected options: FinalRequestOptions; + + protected response: Response; + protected body: unknown; + + constructor(client: RunwayML, response: Response, body: unknown, options: FinalRequestOptions) { + this.#client = client; + this.options = options; + this.response = response; + this.body = body; + } + + abstract nextPageRequestOptions(): PageRequestOptions | null; + + abstract getPaginatedItems(): Item[]; + + hasNextPage(): boolean { + const items = this.getPaginatedItems(); + if (!items.length) return false; + return this.nextPageRequestOptions() != null; + } + + async getNextPage(): Promise { + const nextOptions = this.nextPageRequestOptions(); + if (!nextOptions) { + throw new RunwayMLError( + 'No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.', + ); + } + + return await this.#client.requestAPIList(this.constructor as any, nextOptions); + } + + async *iterPages(): AsyncGenerator { + let page: this = this; + yield page; + while (page.hasNextPage()) { + page = await page.getNextPage(); + yield page; + } + } + + async *[Symbol.asyncIterator](): AsyncGenerator { + for await (const page of this.iterPages()) { + for (const item of page.getPaginatedItems()) { + yield item; + } + } + } +} + +/** + * This subclass of Promise will resolve to an instantiated Page once the request completes. + * + * It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ +export class PagePromise< + PageClass extends AbstractPage, + Item = ReturnType[number], + > + extends APIPromise + implements AsyncIterable +{ + constructor( + client: RunwayML, + request: Promise, + Page: new (...args: ConstructorParameters) => PageClass, + ) { + super( + client, + request, + async (client, props) => + new Page(client, props.response, await defaultParseResponse(client, props), props.options), + ); + } + + /** + * Allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ + async *[Symbol.asyncIterator](): AsyncGenerator { + const page = await this; + for await (const item of page) { + yield item; + } + } +} + +export interface CursorPageResponse { + data: Array; + + nextCursor: string; +} + +export interface CursorPageParams { + cursor?: string; + + limit?: number; +} + +export class CursorPage extends AbstractPage implements CursorPageResponse { + data: Array; + + nextCursor: string; + + constructor( + client: RunwayML, + response: Response, + body: CursorPageResponse, + options: FinalRequestOptions, + ) { + super(client, response, body, options); + + this.data = body.data || []; + this.nextCursor = body.nextCursor || ''; + } + + getPaginatedItems(): Item[] { + return this.data ?? []; + } + + nextPageRequestOptions(): PageRequestOptions | null { + const cursor = this.nextCursor; + if (!cursor) { + return null; + } + + return { + ...this.options, + query: { + ...maybeObj(this.options.query), + cursor, + }, + }; + } +} diff --git a/src/index.ts b/src/index.ts index 24b1bfe..65dbe80 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ export { RunwayML as default } from './client'; export { type Uploadable, toFile } from './core/uploads'; export { APIPromise } from './core/api-promise'; export { RunwayML, type ClientOptions } from './client'; +export { PagePromise } from './core/pagination'; export { RunwayMLError, APIError, diff --git a/src/pagination.ts b/src/pagination.ts new file mode 100644 index 0000000..90bf015 --- /dev/null +++ b/src/pagination.ts @@ -0,0 +1,2 @@ +/** @deprecated Import from ./core/pagination instead */ +export * from './core/pagination'; diff --git a/src/resources/avatars.ts b/src/resources/avatars.ts new file mode 100644 index 0000000..2c29542 --- /dev/null +++ b/src/resources/avatars.ts @@ -0,0 +1,2049 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Avatars extends APIResource { + /** + * Create a new avatar with a reference image and voice. + * + * @example + * ```ts + * const avatar = await client.avatars.create({ + * name: 'x', + * personality: + * 'You are a helpful support agent assisting users with their account questions. Be friendly, patient, and provide clear step-by-step guidance.', + * referenceImage: 'https://example.com/reference.jpg', + * voice: { presetId: 'adrian', type: 'runway-live-preset' }, + * }); + * ``` + */ + create(body: AvatarCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/avatars', { body, ...options }); + } + + /** + * Get details of a specific avatar. + * + * @example + * ```ts + * const avatar = await client.avatars.retrieve( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * ); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/avatars/${id}`, options); + } + + /** + * Update an existing avatar. At least one field must be provided. + * + * @example + * ```ts + * const avatar = await client.avatars.update( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * ); + * ``` + */ + update( + id: string, + body: AvatarUpdateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.patch(path`/v1/avatars/${id}`, { body, ...options }); + } + + /** + * List avatars for the authenticated user with cursor-based pagination. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const avatarListResponse of client.avatars.list({ + * limit: 1, + * })) { + * // ... + * } + * ``` + */ + list( + query: AvatarListParams, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/v1/avatars', CursorPage, { query, ...options }); + } + + /** + * Delete an avatar. + * + * @example + * ```ts + * await client.avatars.delete( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * ); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/v1/avatars/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export type AvatarListResponsesCursorPage = CursorPage; + +/** + * An avatar that is still being processed. + */ +export type AvatarCreateResponse = + | AvatarCreateResponse.Processing + | AvatarCreateResponse.Ready + | AvatarCreateResponse.Failed; + +export namespace AvatarCreateResponse { + /** + * An avatar that is still being processed. + */ + export interface Processing { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'PROCESSING'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Processing.RunwayLivePreset | Processing.Custom; + } + + export namespace Processing { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that is ready for use in sessions. + */ + export interface Ready { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'READY'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Ready.RunwayLivePreset | Ready.Custom; + } + + export namespace Ready { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that failed to finish processing. + */ + export interface Failed { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failureReason: string; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'FAILED'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Failed.RunwayLivePreset | Failed.Custom; + } + + export namespace Failed { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } +} + +/** + * An avatar that is still being processed. + */ +export type AvatarRetrieveResponse = + | AvatarRetrieveResponse.Processing + | AvatarRetrieveResponse.Ready + | AvatarRetrieveResponse.Failed; + +export namespace AvatarRetrieveResponse { + /** + * An avatar that is still being processed. + */ + export interface Processing { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'PROCESSING'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Processing.RunwayLivePreset | Processing.Custom; + } + + export namespace Processing { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that is ready for use in sessions. + */ + export interface Ready { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'READY'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Ready.RunwayLivePreset | Ready.Custom; + } + + export namespace Ready { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that failed to finish processing. + */ + export interface Failed { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failureReason: string; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'FAILED'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Failed.RunwayLivePreset | Failed.Custom; + } + + export namespace Failed { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } +} + +/** + * An avatar that is still being processed. + */ +export type AvatarUpdateResponse = + | AvatarUpdateResponse.Processing + | AvatarUpdateResponse.Ready + | AvatarUpdateResponse.Failed; + +export namespace AvatarUpdateResponse { + /** + * An avatar that is still being processed. + */ + export interface Processing { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'PROCESSING'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Processing.RunwayLivePreset | Processing.Custom; + } + + export namespace Processing { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that is ready for use in sessions. + */ + export interface Ready { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'READY'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Ready.RunwayLivePreset | Ready.Custom; + } + + export namespace Ready { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that failed to finish processing. + */ + export interface Failed { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failureReason: string; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'FAILED'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Failed.RunwayLivePreset | Failed.Custom; + } + + export namespace Failed { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } +} + +/** + * An avatar that is still being processed. + */ +export type AvatarListResponse = + | AvatarListResponse.Processing + | AvatarListResponse.Ready + | AvatarListResponse.Failed; + +export namespace AvatarListResponse { + /** + * An avatar that is still being processed. + */ + export interface Processing { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'PROCESSING'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Processing.RunwayLivePreset | Processing.Custom; + } + + export namespace Processing { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that is ready for use in sessions. + */ + export interface Ready { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'READY'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Ready.RunwayLivePreset | Ready.Custom; + } + + export namespace Ready { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } + + /** + * An avatar that failed to finish processing. + */ + export interface Failed { + /** + * The unique identifier of the avatar. + */ + id: string; + + /** + * When the avatar was created. + */ + createdAt: string; + + /** + * IDs of knowledge documents attached to this avatar. + */ + documentIds: Array; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failureReason: string; + + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A URI pointing to a low-resolution preview of the processed reference image. + */ + processedImageUri: string | null; + + /** + * A URI pointing to a low-resolution preview of the avatar's reference image. + */ + referenceImageUri: string | null; + + /** + * Opening message that the avatar will say when a session starts, or null if not + * set. + */ + startScript: string | null; + + status: 'FAILED'; + + /** + * When the avatar was last updated. + */ + updatedAt: string; + + /** + * The voice configured for this avatar. + */ + voice: Failed.RunwayLivePreset | Failed.Custom; + } + + export namespace Failed { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * A brief description of the voice characteristics. + */ + description: string; + + /** + * The display name of the voice. + */ + name: string; + + /** + * The preset voice identifier. + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The unique identifier of the custom voice. + */ + id: string; + + /** + * Whether the voice has been deleted. When true, name and description are omitted. + */ + deleted: boolean; + + type: 'custom'; + + /** + * A brief description of the voice characteristics. + */ + description?: string | null; + + /** + * The display name of the voice. + */ + name?: string; + } + } +} + +export interface AvatarCreateParams { + /** + * The character name for the avatar. + */ + name: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality: string; + + /** + * A HTTPS URL. + */ + referenceImage: string; + + /** + * The voice configuration for the avatar. + */ + voice: AvatarCreateParams.RunwayLivePreset | AvatarCreateParams.Custom; + + /** + * Optional list of knowledge document IDs to attach to this avatar. Documents + * provide additional context during conversations. + */ + documentIds?: Array; + + /** + * Controls image preprocessing. `optimize` improves the image for better avatar + * results. `none` uses the image as-is; quality not guaranteed. + */ + imageProcessing?: 'optimize' | 'none'; + + /** + * Optional opening message that the avatar will say when a session starts. + */ + startScript?: string; +} + +export namespace AvatarCreateParams { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * The ID of a preset voice. Available voices: `victoria` (Victoria), `vincent` + * (Vincent), `clara` (Clara), `drew` (Drew), `skye` (Skye), `max` (Max), `morgan` + * (Morgan), `felix` (Felix), `mia` (Mia), `marcus` (Marcus), `summer` (Summer), + * `ruby` (Ruby), `aurora` (Aurora), `jasper` (Jasper), `leo` (Leo), `adrian` + * (Adrian), `nina` (Nina), `emma` (Emma), `blake` (Blake), `david` (David), `maya` + * (Maya), `nathan` (Nathan), `sam` (Sam), `georgia` (Georgia), `petra` (Petra), + * `adam` (Adam), `zach` (Zach), `violet` (Violet), `roman` (Roman), `luna` (Luna). + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The ID of a custom voice created via the Voices API. + */ + id: string; + + type: 'custom'; + } +} + +export interface AvatarUpdateParams { + /** + * List of knowledge document IDs to attach to this avatar. Replaces all current + * attachments. Documents provide additional context during conversations. + */ + documentIds?: Array; + + /** + * Controls image preprocessing. `optimize` improves the image for better avatar + * results. `none` uses the image as-is; quality not guaranteed. + */ + imageProcessing?: 'optimize' | 'none'; + + /** + * The character name for the avatar. + */ + name?: string; + + /** + * System prompt defining how the avatar should behave in conversations. + */ + personality?: string; + + /** + * A HTTPS URL. + */ + referenceImage?: string; + + /** + * Optional opening message that the avatar will say when a session starts. Set to + * null to clear. + */ + startScript?: string | null; + + /** + * The voice configuration for the avatar. + */ + voice?: AvatarUpdateParams.RunwayLivePreset | AvatarUpdateParams.Custom; +} + +export namespace AvatarUpdateParams { + /** + * A preset voice from the Runway API. + */ + export interface RunwayLivePreset { + /** + * The ID of a preset voice. Available voices: `victoria` (Victoria), `vincent` + * (Vincent), `clara` (Clara), `drew` (Drew), `skye` (Skye), `max` (Max), `morgan` + * (Morgan), `felix` (Felix), `mia` (Mia), `marcus` (Marcus), `summer` (Summer), + * `ruby` (Ruby), `aurora` (Aurora), `jasper` (Jasper), `leo` (Leo), `adrian` + * (Adrian), `nina` (Nina), `emma` (Emma), `blake` (Blake), `david` (David), `maya` + * (Maya), `nathan` (Nathan), `sam` (Sam), `georgia` (Georgia), `petra` (Petra), + * `adam` (Adam), `zach` (Zach), `violet` (Violet), `roman` (Roman), `luna` (Luna). + */ + presetId: + | 'victoria' + | 'vincent' + | 'clara' + | 'drew' + | 'skye' + | 'max' + | 'morgan' + | 'felix' + | 'mia' + | 'marcus' + | 'summer' + | 'ruby' + | 'aurora' + | 'jasper' + | 'leo' + | 'adrian' + | 'nina' + | 'emma' + | 'blake' + | 'david' + | 'maya' + | 'nathan' + | 'sam' + | 'georgia' + | 'petra' + | 'adam' + | 'zach' + | 'violet' + | 'roman' + | 'luna'; + + type: 'runway-live-preset'; + } + + /** + * A custom voice created via the Voices API. + */ + export interface Custom { + /** + * The ID of a custom voice created via the Voices API. + */ + id: string; + + type: 'custom'; + } +} + +export interface AvatarListParams extends CursorPageParams {} + +export declare namespace Avatars { + export { + type AvatarCreateResponse as AvatarCreateResponse, + type AvatarRetrieveResponse as AvatarRetrieveResponse, + type AvatarUpdateResponse as AvatarUpdateResponse, + type AvatarListResponse as AvatarListResponse, + type AvatarListResponsesCursorPage as AvatarListResponsesCursorPage, + type AvatarCreateParams as AvatarCreateParams, + type AvatarUpdateParams as AvatarUpdateParams, + type AvatarListParams as AvatarListParams, + }; +} diff --git a/src/resources/documents.ts b/src/resources/documents.ts new file mode 100644 index 0000000..6bd9bbb --- /dev/null +++ b/src/resources/documents.ts @@ -0,0 +1,270 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Documents extends APIResource { + /** + * Create a new knowledge document. Documents can be attached to avatars to provide + * additional context during conversations. + * + * @example + * ```ts + * const document = await client.documents.create({ + * content: + * '# Product FAQ\n\n## What is your return policy?\n\nWe offer a 30-day return policy...', + * name: 'Product FAQ', + * }); + * ``` + */ + create(body: DocumentCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/documents', { body, ...options }); + } + + /** + * Get details of a specific knowledge document. + * + * @example + * ```ts + * const document = await client.documents.retrieve( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * ); + * ``` + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/documents/${id}`, options); + } + + /** + * List knowledge documents for the authenticated user with cursor-based + * pagination. + * + * @example + * ```ts + * // Automatically fetches more pages as needed. + * for await (const documentListResponse of client.documents.list( + * { limit: 1 }, + * )) { + * // ... + * } + * ``` + */ + list( + query: DocumentListParams, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/v1/documents', CursorPage, { query, ...options }); + } + + /** + * Delete a knowledge document. This also removes it from all avatars it was + * attached to. + * + * @example + * ```ts + * await client.documents.delete( + * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + * ); + * ``` + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/v1/documents/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export type DocumentListResponsesCursorPage = CursorPage; + +export interface DocumentCreateResponse { + /** + * The unique identifier of the document. + */ + id: string; + + /** + * The full content of the document. + */ + content: string; + + /** + * When the document was created. + */ + createdAt: string; + + /** + * The name of the document. + */ + name: string; + + /** + * The type of document. + */ + type: 'text' | 'file'; + + /** + * When the document was last updated. + */ + updatedAt: string; + + /** + * Avatars that use this document. Always empty for newly created documents. + */ + usedBy: Array; +} + +export namespace DocumentCreateResponse { + export interface UsedBy { + /** + * The avatar ID. + */ + id: string; + + /** + * URL to the avatar image, or null if not yet processed. + */ + imageUrl: string | null; + + /** + * The avatar name. + */ + name: string; + } +} + +export interface DocumentRetrieveResponse { + /** + * The unique identifier of the document. + */ + id: string; + + /** + * The full content of the document. + */ + content: string; + + /** + * When the document was created. + */ + createdAt: string; + + /** + * The name of the document. + */ + name: string; + + /** + * The type of document. + */ + type: 'text' | 'file'; + + /** + * When the document was last updated. + */ + updatedAt: string; + + /** + * Avatars that use this document. + */ + usedBy: Array; +} + +export namespace DocumentRetrieveResponse { + export interface UsedBy { + /** + * The avatar ID. + */ + id: string; + + /** + * URL to the avatar image, or null if not yet processed. + */ + imageUrl: string | null; + + /** + * The avatar name. + */ + name: string; + } +} + +export interface DocumentListResponse { + /** + * The unique identifier of the document. + */ + id: string; + + /** + * When the document was created. + */ + createdAt: string; + + /** + * The name of the document. + */ + name: string; + + /** + * The type of document. + */ + type: 'text' | 'file'; + + /** + * When the document was last updated. + */ + updatedAt: string; + + /** + * Avatars that use this document. + */ + usedBy: Array; +} + +export namespace DocumentListResponse { + export interface UsedBy { + /** + * The avatar ID. + */ + id: string; + + /** + * URL to the avatar image, or null if not yet processed. + */ + imageUrl: string | null; + + /** + * The avatar name. + */ + name: string; + } +} + +export interface DocumentCreateParams { + /** + * The markdown or plain text content of the document. + */ + content: string; + + /** + * A descriptive name for the document. + */ + name: string; +} + +export interface DocumentListParams extends CursorPageParams {} + +export declare namespace Documents { + export { + type DocumentCreateResponse as DocumentCreateResponse, + type DocumentRetrieveResponse as DocumentRetrieveResponse, + type DocumentListResponse as DocumentListResponse, + type DocumentListResponsesCursorPage as DocumentListResponsesCursorPage, + type DocumentCreateParams as DocumentCreateParams, + type DocumentListParams as DocumentListParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index c2069f0..1943bb2 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,10 +1,30 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export { + Avatars, + type AvatarCreateResponse, + type AvatarRetrieveResponse, + type AvatarUpdateResponse, + type AvatarListResponse, + type AvatarCreateParams, + type AvatarUpdateParams, + type AvatarListParams, + type AvatarListResponsesCursorPage, +} from './avatars'; export { CharacterPerformance, type CharacterPerformanceCreateResponse, type CharacterPerformanceCreateParams, } from './character-performance'; +export { + Documents, + type DocumentCreateResponse, + type DocumentRetrieveResponse, + type DocumentListResponse, + type DocumentCreateParams, + type DocumentListParams, + type DocumentListResponsesCursorPage, +} from './documents'; export { ImageToVideo, type ImageToVideoCreateResponse, @@ -16,6 +36,12 @@ export { type OrganizationRetrieveUsageResponse, type OrganizationRetrieveUsageParams, } from './organization'; +export { + RealtimeSessions, + type RealtimeSessionCreateResponse, + type RealtimeSessionRetrieveResponse, + type RealtimeSessionCreateParams, +} from './realtime-sessions'; export { SoundEffect, type SoundEffectCreateResponse, type SoundEffectCreateParams } from './sound-effect'; export { SpeechToSpeech, @@ -45,4 +71,15 @@ export { type VoiceIsolationCreateResponse, type VoiceIsolationCreateParams, } from './voice-isolation'; +export { + Voices, + type VoiceCreateResponse, + type VoiceRetrieveResponse, + type VoiceListResponse, + type VoicePreviewResponse, + type VoiceCreateParams, + type VoiceListParams, + type VoicePreviewParams, + type VoiceListResponsesCursorPage, +} from './voices'; export { Uploads, type UploadCreateEphemeralResponse, type UploadsCreateEphemeralParams } from './uploads'; diff --git a/src/resources/organization.ts b/src/resources/organization.ts index 45078e0..940c8dd 100644 --- a/src/resources/organization.ts +++ b/src/resources/organization.ts @@ -117,6 +117,8 @@ export interface OrganizationRetrieveUsageResponse { | 'eleven_voice_isolation' | 'eleven_voice_dubbing' | 'eleven_multilingual_sts_v2' + | 'gwm1_avatars' + | 'voice_processing' >; results: Array; @@ -162,7 +164,9 @@ export namespace OrganizationRetrieveUsageResponse { | 'eleven_text_to_sound_v2' | 'eleven_voice_isolation' | 'eleven_voice_dubbing' - | 'eleven_multilingual_sts_v2'; + | 'eleven_multilingual_sts_v2' + | 'gwm1_avatars' + | 'voice_processing'; } } } diff --git a/src/resources/realtime-sessions.ts b/src/resources/realtime-sessions.ts new file mode 100644 index 0000000..3523921 --- /dev/null +++ b/src/resources/realtime-sessions.ts @@ -0,0 +1,251 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class RealtimeSessions extends APIResource { + /** + * Create a new realtime session with the specified model configuration. + */ + create( + body: RealtimeSessionCreateParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v1/realtime_sessions', { body, ...options }); + } + + /** + * Get the status of a realtime session. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/realtime_sessions/${id}`, options); + } + + /** + * Cancel an active realtime session. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/v1/realtime_sessions/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } +} + +export interface RealtimeSessionCreateResponse { + /** + * The ID of the created realtime session. + */ + id: string; +} + +/** + * A session that is being provisioned. + */ +export type RealtimeSessionRetrieveResponse = + | RealtimeSessionRetrieveResponse.NotReady + | RealtimeSessionRetrieveResponse.Ready + | RealtimeSessionRetrieveResponse.Running + | RealtimeSessionRetrieveResponse.Completed + | RealtimeSessionRetrieveResponse.Failed + | RealtimeSessionRetrieveResponse.Cancelled; + +export namespace RealtimeSessionRetrieveResponse { + /** + * A session that is being provisioned. + */ + export interface NotReady { + /** + * The realtime session ID. + */ + id: string; + + /** + * When the session was created. + */ + createdAt: string; + + status: 'NOT_READY'; + + /** + * When true, the session is waiting in a queue for available capacity. When false + * or absent, the session is actively being provisioned. + */ + queued?: boolean; + } + + /** + * A session that is ready to connect. + */ + export interface Ready { + /** + * The realtime session ID. + */ + id: string; + + /** + * When the session was created. + */ + createdAt: string; + + /** + * When the session credentials expire. + */ + expiresAt: string; + + /** + * Session key for authenticating the /consume endpoint. Use as Bearer token. + */ + sessionKey: string; + + status: 'READY'; + } + + /** + * A session with an active WebRTC connection. + */ + export interface Running { + /** + * The realtime session ID. + */ + id: string; + + /** + * When the session was created. + */ + createdAt: string; + + status: 'RUNNING'; + } + + /** + * A session that ended normally. + */ + export interface Completed { + /** + * The realtime session ID. + */ + id: string; + + /** + * When the session was created. + */ + createdAt: string; + + /** + * The session duration in seconds. + */ + duration: number; + + status: 'COMPLETED'; + } + + /** + * A session that encountered an error. + */ + export interface Failed { + /** + * The realtime session ID. + */ + id: string; + + /** + * When the session was created. + */ + createdAt: string; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failure: string; + + /** + * A stable, machine-readable error code. See + * https://docs.dev.runwayml.com/errors/task-failures/ for more information. + */ + failureCode: string; + + status: 'FAILED'; + } + + /** + * A session that was explicitly cancelled. + */ + export interface Cancelled { + /** + * The realtime session ID. + */ + id: string; + + /** + * When the session was created. + */ + createdAt: string; + + status: 'CANCELLED'; + } +} + +export interface RealtimeSessionCreateParams { + /** + * The avatar configuration for the session. + */ + avatar: RealtimeSessionCreateParams.RunwayPreset | RealtimeSessionCreateParams.Custom; + + /** + * The realtime session model type. + */ + model: 'gwm1_avatars'; + + /** + * Maximum session duration in seconds. + */ + maxDuration?: number; +} + +export namespace RealtimeSessionCreateParams { + /** + * A preset avatar from Runway. + */ + export interface RunwayPreset { + /** + * ID of a preset avatar. + */ + presetId: + | 'game-character' + | 'music-superstar' + | 'game-character-man' + | 'cat-character' + | 'influencer' + | 'tennis-coach' + | 'human-resource' + | 'fashion-designer' + | 'cooking-teacher'; + + type: 'runway-preset'; + } + + /** + * A user-created avatar. + */ + export interface Custom { + /** + * ID of a user-created avatar. + */ + avatarId: string; + + type: 'custom'; + } +} + +export declare namespace RealtimeSessions { + export { + type RealtimeSessionCreateResponse as RealtimeSessionCreateResponse, + type RealtimeSessionRetrieveResponse as RealtimeSessionRetrieveResponse, + type RealtimeSessionCreateParams as RealtimeSessionCreateParams, + }; +} diff --git a/src/resources/voices.ts b/src/resources/voices.ts new file mode 100644 index 0000000..097e0d2 --- /dev/null +++ b/src/resources/voices.ts @@ -0,0 +1,345 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { APIPromise } from '../core/api-promise'; +import { CursorPage, type CursorPageParams, PagePromise } from '../core/pagination'; +import { buildHeaders } from '../internal/headers'; +import { RequestOptions } from '../internal/request-options'; +import { path } from '../internal/utils/path'; + +export class Voices extends APIResource { + /** + * Create a custom voice from a text description. + */ + create(body: VoiceCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/voices', { body, ...options }); + } + + /** + * Get details about a specific custom voice. + */ + retrieve(id: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/voices/${id}`, options); + } + + /** + * List custom voices for the authenticated organization with cursor-based + * pagination. + */ + list( + query: VoiceListParams, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/v1/voices', CursorPage, { query, ...options }); + } + + /** + * Delete a custom voice. + */ + delete(id: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/v1/voices/${id}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } + + /** + * Generate a short audio preview of a voice from a text description. Use this to + * audition a voice before creating it. + */ + preview(body: VoicePreviewParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/voices/preview', { body, ...options }); + } +} + +export type VoiceListResponsesCursorPage = CursorPage; + +export interface VoiceCreateResponse { + /** + * The ID of the voice that was created. + */ + id: string; +} + +/** + * A voice that is still being processed. + */ +export type VoiceRetrieveResponse = + | VoiceRetrieveResponse.Processing + | VoiceRetrieveResponse.Ready + | VoiceRetrieveResponse.Failed; + +export namespace VoiceRetrieveResponse { + /** + * A voice that is still being processed. + */ + export interface Processing { + /** + * The unique identifier of the voice. + */ + id: string; + + /** + * When the voice was created. + */ + createdAt: string; + + /** + * A description of the voice, or null if not set. + */ + description: string | null; + + /** + * The name of the voice. + */ + name: string; + + status: 'PROCESSING'; + } + + /** + * A voice that is ready for use. + */ + export interface Ready { + /** + * The unique identifier of the voice. + */ + id: string; + + /** + * When the voice was created. + */ + createdAt: string; + + /** + * A description of the voice, or null if not set. + */ + description: string | null; + + /** + * The name of the voice. + */ + name: string; + + /** + * A signed URL to an MP3 audio sample of the voice, or null if no sample is + * available. + */ + previewUrl: string | null; + + status: 'READY'; + } + + /** + * A voice that failed to finish processing. + */ + export interface Failed { + /** + * The unique identifier of the voice. + */ + id: string; + + /** + * When the voice was created. + */ + createdAt: string; + + /** + * A description of the voice, or null if not set. + */ + description: string | null; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failureReason: string; + + /** + * The name of the voice. + */ + name: string; + + status: 'FAILED'; + } +} + +/** + * A voice that is still being processed. + */ +export type VoiceListResponse = + | VoiceListResponse.Processing + | VoiceListResponse.Ready + | VoiceListResponse.Failed; + +export namespace VoiceListResponse { + /** + * A voice that is still being processed. + */ + export interface Processing { + /** + * The unique identifier of the voice. + */ + id: string; + + /** + * When the voice was created. + */ + createdAt: string; + + /** + * A description of the voice, or null if not set. + */ + description: string | null; + + /** + * The name of the voice. + */ + name: string; + + status: 'PROCESSING'; + } + + /** + * A voice that is ready for use. + */ + export interface Ready { + /** + * The unique identifier of the voice. + */ + id: string; + + /** + * When the voice was created. + */ + createdAt: string; + + /** + * A description of the voice, or null if not set. + */ + description: string | null; + + /** + * The name of the voice. + */ + name: string; + + /** + * A signed URL to an MP3 audio sample of the voice, or null if no sample is + * available. + */ + previewUrl: string | null; + + status: 'READY'; + } + + /** + * A voice that failed to finish processing. + */ + export interface Failed { + /** + * The unique identifier of the voice. + */ + id: string; + + /** + * When the voice was created. + */ + createdAt: string; + + /** + * A description of the voice, or null if not set. + */ + description: string | null; + + /** + * A human-readable error message. This value is not stable and should not be + * matched against programmatically. + */ + failureReason: string; + + /** + * The name of the voice. + */ + name: string; + + status: 'FAILED'; + } +} + +export interface VoicePreviewResponse { + /** + * Duration of the audio preview in seconds. + */ + durationSecs: number; + + /** + * A presigned URL to the audio preview. The URL expires after 24 hours. + */ + url: string; +} + +export interface VoiceCreateParams { + /** + * The source configuration for creating the voice. + */ + from: VoiceCreateParams.From; + + /** + * A name for the voice. + */ + name: string; + + /** + * An optional description of the voice. + */ + description?: string | null; +} + +export namespace VoiceCreateParams { + /** + * The source configuration for creating the voice. + */ + export interface From { + /** + * The voice design model to use. + */ + model: 'eleven_multilingual_ttv_v2' | 'eleven_ttv_v3'; + + /** + * A text description of the desired voice characteristics. Must be at least 20 + * characters. + */ + prompt: string; + + type: 'text'; + } +} + +export interface VoiceListParams extends CursorPageParams {} + +export interface VoicePreviewParams { + /** + * The voice design model to use. + */ + model: 'eleven_multilingual_ttv_v2' | 'eleven_ttv_v3'; + + /** + * A text description of the desired voice characteristics. Must be at least 20 + * characters. + */ + prompt: string; +} + +export declare namespace Voices { + export { + type VoiceCreateResponse as VoiceCreateResponse, + type VoiceRetrieveResponse as VoiceRetrieveResponse, + type VoiceListResponse as VoiceListResponse, + type VoicePreviewResponse as VoicePreviewResponse, + type VoiceListResponsesCursorPage as VoiceListResponsesCursorPage, + type VoiceCreateParams as VoiceCreateParams, + type VoiceListParams as VoiceListParams, + type VoicePreviewParams as VoicePreviewParams, + }; +} diff --git a/tests/api-resources/avatars.test.ts b/tests/api-resources/avatars.test.ts new file mode 100644 index 0000000..e96b9b9 --- /dev/null +++ b/tests/api-resources/avatars.test.ts @@ -0,0 +1,108 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import RunwayML from '@runwayml/sdk'; + +const client = new RunwayML({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource avatars', () => { + test('create: only required params', async () => { + const responsePromise = client.avatars.create({ + name: 'x', + personality: + 'You are a helpful support agent assisting users with their account questions. Be friendly, patient, and provide clear step-by-step guidance.', + referenceImage: 'https://example.com/reference.jpg', + voice: { presetId: 'adrian', type: 'runway-live-preset' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.avatars.create({ + name: 'x', + personality: + 'You are a helpful support agent assisting users with their account questions. Be friendly, patient, and provide clear step-by-step guidance.', + referenceImage: 'https://example.com/reference.jpg', + voice: { presetId: 'adrian', type: 'runway-live-preset' }, + documentIds: ['182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'], + imageProcessing: 'optimize', + startScript: 'Hello! How can I help you today?', + }); + }); + + test('retrieve', async () => { + const responsePromise = client.avatars.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update', async () => { + const responsePromise = client.avatars.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.avatars.update( + '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + { + documentIds: ['182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'], + imageProcessing: 'optimize', + name: 'x', + personality: + 'You are a helpful support agent assisting users with their account questions. Be friendly, patient, and provide clear step-by-step guidance.', + referenceImage: 'https://example.com/reference.jpg', + startScript: 'Hello! How can I help you today?', + voice: { presetId: 'adrian', type: 'runway-live-preset' }, + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(RunwayML.NotFoundError); + }); + + test('list: only required params', async () => { + const responsePromise = client.avatars.list({ limit: 1 }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: required and optional params', async () => { + const response = await client.avatars.list({ limit: 1, cursor: 'x' }); + }); + + test('delete', async () => { + const responsePromise = client.avatars.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts new file mode 100644 index 0000000..8a3eae6 --- /dev/null +++ b/tests/api-resources/documents.test.ts @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import RunwayML from '@runwayml/sdk'; + +const client = new RunwayML({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource documents', () => { + test('create: only required params', async () => { + const responsePromise = client.documents.create({ + content: '# Product FAQ\n\n## What is your return policy?\n\nWe offer a 30-day return policy...', + name: 'Product FAQ', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.documents.create({ + content: '# Product FAQ\n\n## What is your return policy?\n\nWe offer a 30-day return policy...', + name: 'Product FAQ', + }); + }); + + test('retrieve', async () => { + const responsePromise = client.documents.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: only required params', async () => { + const responsePromise = client.documents.list({ limit: 1 }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: required and optional params', async () => { + const response = await client.documents.list({ limit: 1, cursor: 'x' }); + }); + + test('delete', async () => { + const responsePromise = client.documents.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/realtime-sessions.test.ts b/tests/api-resources/realtime-sessions.test.ts new file mode 100644 index 0000000..6a12f9d --- /dev/null +++ b/tests/api-resources/realtime-sessions.test.ts @@ -0,0 +1,54 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import RunwayML from '@runwayml/sdk'; + +const client = new RunwayML({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource realtimeSessions', () => { + test('create: only required params', async () => { + const responsePromise = client.realtimeSessions.create({ + avatar: { presetId: 'game-character', type: 'runway-preset' }, + model: 'gwm1_avatars', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.realtimeSessions.create({ + avatar: { presetId: 'game-character', type: 'runway-preset' }, + model: 'gwm1_avatars', + maxDuration: 10, + }); + }); + + test('retrieve', async () => { + const responsePromise = client.realtimeSessions.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('delete', async () => { + const responsePromise = client.realtimeSessions.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}); diff --git a/tests/api-resources/voices.test.ts b/tests/api-resources/voices.test.ts new file mode 100644 index 0000000..5c5a2af --- /dev/null +++ b/tests/api-resources/voices.test.ts @@ -0,0 +1,98 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import RunwayML from '@runwayml/sdk'; + +const client = new RunwayML({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource voices', () => { + test('create: only required params', async () => { + const responsePromise = client.voices.create({ + from: { + model: 'eleven_multilingual_ttv_v2', + prompt: 'xxxxxxxxxxxxxxxxxxxx', + type: 'text', + }, + name: 'x', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: required and optional params', async () => { + const response = await client.voices.create({ + from: { + model: 'eleven_multilingual_ttv_v2', + prompt: 'xxxxxxxxxxxxxxxxxxxx', + type: 'text', + }, + name: 'x', + description: 'x', + }); + }); + + test('retrieve', async () => { + const responsePromise = client.voices.retrieve('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: only required params', async () => { + const responsePromise = client.voices.list({ limit: 1 }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: required and optional params', async () => { + const response = await client.voices.list({ limit: 1, cursor: 'x' }); + }); + + test('delete', async () => { + const responsePromise = client.voices.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('preview: only required params', async () => { + const responsePromise = client.voices.preview({ + model: 'eleven_multilingual_ttv_v2', + prompt: 'xxxxxxxxxxxxxxxxxxxx', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('preview: required and optional params', async () => { + const response = await client.voices.preview({ + model: 'eleven_multilingual_ttv_v2', + prompt: 'xxxxxxxxxxxxxxxxxxxx', + }); + }); +}); From 454fbde70f6ca8eb15925963b079609bce13a654 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:18:06 +0000 Subject: [PATCH 7/7] release: 3.15.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 20 ++++++++++++++++++++ package.json | 2 +- src/version.ts | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 20f621d..9c10c70 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.14.3" + ".": "3.15.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index c28ad43..fffb8f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## 3.15.0 (2026-03-06) + +Full Changelog: [v3.14.3...v3.15.0](https://github.com/runwayml/sdk-node/compare/v3.14.3...v3.15.0) + +### Features + +* **api:** add avatar, voice, document, and realtime session endpoints ([9534a7e](https://github.com/runwayml/sdk-node/commit/9534a7e892b9b11d7c2420a0b79b4c065b820a42)) + + +### Bug Fixes + +* fix request delays for retrying to be more respectful of high requested delays ([0a0a653](https://github.com/runwayml/sdk-node/commit/0a0a653562760410cbe9425ab6ef118ee8682546)) + + +### Chores + +* **docs:** add missing descriptions ([322c513](https://github.com/runwayml/sdk-node/commit/322c513a65a9250c65215cc636ee1ca061c1592a)) +* **internal:** move stringifyQuery implementation to internal function ([bdc20f1](https://github.com/runwayml/sdk-node/commit/bdc20f12c6558a6f405f0790b1601d4bbf2b9078)) +* **test:** do not count install time for mock server timeout ([a5761c0](https://github.com/runwayml/sdk-node/commit/a5761c04cc605146aa284eeefcaf1f23bd7ab0ff)) + ## 3.14.3 (2026-02-23) Full Changelog: [v3.14.2...v3.14.3](https://github.com/runwayml/sdk-node/compare/v3.14.2...v3.14.3) diff --git a/package.json b/package.json index b7c508a..b4ef39a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@runwayml/sdk", - "version": "3.14.3", + "version": "3.15.0", "description": "The official TypeScript library for the RunwayML API", "author": "RunwayML ", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 14e5403..888b16f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '3.14.3'; // x-release-please-version +export const VERSION = '3.15.0'; // x-release-please-version