Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions Runware/Runware-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ export class RunwareBase {
}

// We moving to an array format, it make sense to consolidate all request to an array here
protected send = async (msg: Object) => {
protected send = async (msg: Record<string, unknown>) => {
const taskType = (msg as { taskType?: string })?.taskType ?? "unknown";
const taskUUID = (msg as { taskUUID?: string })?.taskUUID;

Expand All @@ -483,9 +483,19 @@ export class RunwareBase {
await this.ensureConnection();
}
this._logger.messageSent(taskType, taskUUID);
this._ws.send(JSON.stringify([msg]));
this._ws.send(this.serializeWebsocketMessage(msg));
};

protected serializeWebsocketMessage(msg: Record<string, unknown>) {
const {
skipResponse: _skipResponse,
additionalProperties: _additionalProperties,
...websocketMessage
} = msg;

return JSON.stringify([websocketMessage]);
}

private destroy(lis: any) {
removeFromAray(this._listeners, lis);
}
Expand Down
4 changes: 2 additions & 2 deletions Runware/Runware-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export class RunwareServer extends RunwareBase {
});
}

protected send = async (msg: Object) => {
protected send = async (msg: Record<string, unknown>) => {
const taskType = (msg as { taskType?: string })?.taskType ?? "unknown";
const taskUUID = (msg as { taskUUID?: string })?.taskUUID;

Expand All @@ -137,7 +137,7 @@ export class RunwareServer extends RunwareBase {
await this.ensureConnection();
}
this._logger.messageSent(taskType, taskUUID);
this._ws.send(JSON.stringify([msg]));
this._ws.send(this.serializeWebsocketMessage(msg));
};

protected handleClose() {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@runware/sdk-js",
"version": "1.3.2",
"version": "1.3.3",
"description": "The SDK is used to run image inference with the Runware API, powered by the RunWare inference platform. It can be used to generate imaged with text-to-image and image-to-image. It also allows the use of an existing gallery of models or selecting any model or LoRA from the CivitAI gallery. The API also supports upscaling, background removal, inpainting and outpainting, and a series of other ControlNet models.",
"main": "dist/index.js",
"module": "dist/index.js",
Expand All @@ -24,6 +24,7 @@
"test": "vitest run --reporter verbose",
"test:single": "vitest run --reporter verbose tests/Runware/upscale-gan.test.ts",
"debug": "tsx tests/script.ts",
"prepublishOnly": "npm run build",
"beta:tag": "npm publish --tag beta"
},
"keywords": [
Expand Down
60 changes: 58 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,59 @@
# Runware Javascript & Typescript SDK

> [!NOTE]
> A new official SDK is available at [runware-typescript](https://github.com/runware/runware-typescript) (published as [`@runware/sdk`](https://www.npmjs.com/package/@runware/sdk)). It covers the full inference and utility surface with REST or WebSocket transports and gets all new features going forward. This library remains supported during the transition.
> [!CAUTION]
> **`@runware/sdk-js` is deprecated and reaches end of life on 2027-01-31.** v1.3.3 is the final release. The package receives no further features, fixes or security updates after that date, and this repository is archived.
> Migrate to the new official SDK, [`@runware/sdk`](https://www.npmjs.com/package/@runware/sdk) ([runware-typescript](https://github.com/runware/runware-typescript)). It covers the full inference and utility surface with REST or WebSocket transports and gets all new features. See [Migrating to @runware/sdk](#migrating-to-runwaresdk) below.

> This SDK is used to run AI image generation with the Runware API, powered by the RunWare inference platform. With this SDK you can generate images with text-to-image and image-to-image with sub-second inference times. It also allows the use of an existing library of more than 150k models, including any model or LoRA from the CivitAI gallery. The API also supports upscaling, background removal, inpainting, outpainting, ControlNets, and more. Visit the Runware site for [detailed feature breakdown](https://runware.ai/features/).

## Migrating to @runware/sdk

The new SDK talks to the same Runware API with the same task parameters, so most request payloads carry over unchanged. What changes is the client surface: one `createClient()` and one `run()` method instead of a method per task. Full reference: [TypeScript SDK docs](https://runware.ai/docs/tools/typescript).

```sh
npm uninstall @runware/sdk-js
npm install @runware/sdk
```

```js
// Before: @runware/sdk-js
import { Runware } from "@runware/sdk-js";

const runware = new Runware({ apiKey: "API_KEY" });
const images = await runware.requestImages({
model: "runware:101@1",
positivePrompt: "A serene mountain landscape at sunset",
width: 1024,
height: 1024,
});

// After: @runware/sdk
import { createClient } from "@runware/sdk";

const client = await createClient({ apiKey: "API_KEY", transport: "websocket" }); // or "rest"
await client.connect(); // WebSocket only. REST needs no connect().
const images = await client.run({
model: "runware:101@1",
positivePrompt: "A serene mountain landscape at sunset",
width: 1024,
height: 1024,
});
await client.disconnect();
```

| `@runware/sdk-js` | `@runware/sdk` |
| --- | --- |
| `new Runware({ apiKey })`, `Runware.initialize()`, `RunwareServer` | `await createClient({ apiKey, transport: "websocket" \| "rest" })` |
| `ensureConnection()` / `disconnect()` | `client.connect()` / `client.disconnect()` |
| `requestImages()`, `videoInference()`, `audioInference()`, `textInference()`, `threeDInference()`, `photoMaker()` | `client.run({ model, ...params })`. The task type is inferred from the model identifier. |
| `upscaleGan()`, `removeImageBackground()`, `requestImageToText()`, `enhancePrompt()`, `controlNetPreProcess()`, `imageMasking()`, `vectorize()`, `training()` | `client.run({ taskType, ...params })` with the API task type this SDK sent on the wire (`upscale`, `removeBackground`, `caption`, `promptEnhance`, `controlNetPreprocess`, `imageMasking`, `vectorize`, `training`). For ControlNet preprocessing, pass `model` and `inputs: { image }`, e.g. `client.run({ taskType: "controlNetPreprocess", model, inputs: { image } })`. |
| `imageUpload()`, `mediaStorage()` | `client.mediaStorage({ operation: "upload", media })` |
| `modelSearch()`, `modelUpload()`, `getTaskDetails()`, `getResponse()` | Same names on `client`. |
| `skipResponse` | No direct equivalent: `run()` resolves after the final result, not after the submission acknowledgement/task UUID. Async delivery is the default and the SDK polls for the result; pass `deliveryMethod: "sync"` for fast tasks. |
| Per-request `retry` / `timeoutDuration` | Second argument to `run()`: `{ timeout, signal }` with an `AbortController`. |
| `onPartialImages` | `onResult(item)` in the second argument to `run()`. |
| Local file path as an input | Wrap it with `fileToBase64()` or `fileToDataURI()` from `@runware/sdk`. The new SDK never reads the filesystem on its own. |

## Get API access

For an API Key and free trial credits, [create a free account](https://my.runware.ai/) with [Runware](https://runware.ai)
Expand Down Expand Up @@ -742,6 +791,13 @@ export type TImageMaskingResponse = {

## Changelog

### - v1.3.3 (final release)

- `@runware/sdk-js` is deprecated in favour of [`@runware/sdk`](https://www.npmjs.com/package/@runware/sdk). End of life: 2027-01-31. See [Migrating to @runware/sdk](#migrating-to-runwaresdk).
- Security: update `ws` to 8.21.3 and `uuid` to 11.x (the last `uuid` line that ships a CommonJS build).
- Prevent SDK-only `skipResponse` and `additionalProperties` parameters from being sent in WebSocket payloads.
- Build before publish via `prepublishOnly`.

### - v1.3.2

- Support `async` ControlNet Preprocess delivery
Expand Down
29 changes: 29 additions & 0 deletions tests/Runware/connection/websocket-payload.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, expect, test, vi } from "vitest";
import { RunwareBase } from "../../../Runware/Runware-base";

describe("WebSocket payload serialization", () => {
test("does not send SDK-only request parameters", async () => {
const send = vi.fn();
const sdk = new RunwareBase({ apiKey: "test-api-key" });

(sdk as any)._ws = { readyState: 1, send };
(sdk as any)._connectionSessionUUID = "test-connection-session";

await (sdk as any).send({
taskType: "test",
taskUUID: "test-task",
model: "test-model",
skipResponse: true,
additionalProperties: { internal: true },
});

expect(send).toHaveBeenCalledOnce();
expect(JSON.parse(send.mock.calls[0][0])).toEqual([
{
taskType: "test",
taskUUID: "test-task",
model: "test-model",
},
]);
});
});