@teith/openclaw-runware-provider 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @runware/openclaw-provider
2
+
3
+ OpenClaw provider plugin for [Runware](https://runware.ai) — a unified
4
+ OpenAI-compatible endpoint that proxies Claude, GPT, Gemini, Qwen, GLM,
5
+ MiniMax, Kimi, and Gemma models.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ openclaw plugins install git:github.com/runware/openclaw-provider@v0.1.0
11
+ ```
12
+
13
+ Set your API key:
14
+
15
+ ```bash
16
+ export RUNWARE_API_KEY=...your key...
17
+ ```
18
+
19
+ Register the provider — this fetches the model catalog from Runware and
20
+ writes it into your OpenClaw config:
21
+
22
+ ```bash
23
+ openclaw models auth login --provider runware
24
+ ```
25
+
26
+ Restart the Gateway if it's running. All Runware models appear in the
27
+ Control UI picker.
28
+
29
+ ## Configuration
30
+
31
+ | Variable | Required | Default | Purpose |
32
+ |---|---|---|---|
33
+ | `RUNWARE_API_KEY` | yes | — | API key, used for `/v1/models` discovery and inference |
34
+ | `RUNWARE_BASE_URL` | no | `https://api.runware.ai/v1` | Override for dev / staging |
35
+
36
+ Switching environments:
37
+
38
+ ```bash
39
+ # dev
40
+ export RUNWARE_BASE_URL=https://api.runware.dev/v1
41
+ export RUNWARE_API_KEY=...dev key...
42
+ openclaw models auth login --provider runware
43
+
44
+ # prod (unset override)
45
+ unset RUNWARE_BASE_URL
46
+ export RUNWARE_API_KEY=...prod key...
47
+ openclaw models auth login --provider runware
48
+ ```
49
+
50
+ ## What this plugin does
51
+
52
+ - Registers `runware` as an OpenAI-compatible provider in OpenClaw.
53
+ - Discovers the model catalog live from `GET /v1/models` on registration.
54
+ TTL-cached for 5 minutes; last-known-good on transient failures.
55
+ - Injects `extra_body: { reasoning_effort: "high" }` into every chat
56
+ completions request, so reasoning-capable models stream thinking content.
57
+
58
+ ## Architecture
59
+
60
+ Two-file core:
61
+
62
+ - `src/index.ts` — plugin entry. Registers the provider, defines the
63
+ auth flow, and builds the model catalog.
64
+ - `src/catalog.ts` — TTL-cached `GET /v1/models` fetcher with concurrent
65
+ request deduplication and last-known-good fallback.
66
+
67
+ OpenClaw API surface is described locally in `src/openclaw-api.ts` —
68
+ the plugin does not import from the `openclaw` package at runtime.
69
+
70
+ ## Development
71
+
72
+ ```bash
73
+ pnpm install
74
+ pnpm test
75
+ pnpm typecheck
76
+ pnpm build
77
+ ```
78
+
79
+ Local install for testing:
80
+
81
+ ```bash
82
+ openclaw plugins install -l /absolute/path/to/this/repo
83
+ ```
84
+
85
+ Use `-l` to symlink — rebuilds become visible after `pnpm build` and a
86
+ Gateway restart, without reinstalling.
87
+
88
+ ## Release
89
+
90
+ ```bash
91
+ pnpm test && pnpm build
92
+ git add . && git commit -m "Release v0.1.0"
93
+ git tag v0.1.0
94
+ git push origin main --tags
95
+ ```
96
+
97
+ `dist/` is committed to the repository because OpenClaw installs plugins
98
+ with `npm install --ignore-scripts` and cannot run a build step.
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,3 @@
1
+ export declare function fetchModelIds(baseUrl: string, apiKey: string): Promise<string[]>;
2
+ export declare function resetCache(): void;
3
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAeA,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBtF;AAwBD,wBAAgB,UAAU,IAAI,IAAI,CAGjC"}
@@ -0,0 +1,54 @@
1
+ const CACHE_TTL_MS = 5 * 60 * 1000;
2
+ const FETCH_TIMEOUT_MS = 5000;
3
+ let cache = null;
4
+ let inflight = null;
5
+ export async function fetchModelIds(baseUrl, apiKey) {
6
+ const now = Date.now();
7
+ if (cache && now - cache.fetchedAt < CACHE_TTL_MS) {
8
+ return cache.modelIds;
9
+ }
10
+ if (inflight)
11
+ return inflight;
12
+ inflight = (async () => {
13
+ try {
14
+ const ids = await fetchFromUpstream(baseUrl, apiKey);
15
+ cache = { modelIds: ids, fetchedAt: Date.now() };
16
+ return ids;
17
+ }
18
+ catch (err) {
19
+ if (cache)
20
+ return cache.modelIds;
21
+ throw err;
22
+ }
23
+ finally {
24
+ inflight = null;
25
+ }
26
+ })();
27
+ return inflight;
28
+ }
29
+ async function fetchFromUpstream(baseUrl, apiKey) {
30
+ const url = `${baseUrl.replace(/\/+$/, "")}/models`;
31
+ const controller = new AbortController();
32
+ const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
33
+ try {
34
+ const res = await fetch(url, {
35
+ headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
36
+ signal: controller.signal,
37
+ });
38
+ if (!res.ok) {
39
+ throw new Error(`Runware /models returned ${res.status} ${res.statusText}`);
40
+ }
41
+ const body = (await res.json());
42
+ return (body.data ?? [])
43
+ .map((m) => (typeof m.id === "string" ? m.id : null))
44
+ .filter((id) => id !== null && id.length > 0);
45
+ }
46
+ finally {
47
+ clearTimeout(timeout);
48
+ }
49
+ }
50
+ export function resetCache() {
51
+ cache = null;
52
+ inflight = null;
53
+ }
54
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACnC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAW9B,IAAI,KAAK,GAAsB,IAAI,CAAC;AACpC,IAAI,QAAQ,GAA6B,IAAI,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,MAAc;IACjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,KAAK,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC,QAAQ,CAAC;IACxB,CAAC;IAED,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,QAAQ,GAAG,CAAC,KAAK,IAAI,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACrD,KAAK,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACjD,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC,QAAQ,CAAC;YACjC,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc;IAC9D,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC;IACpD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAEvE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAC1E,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;aACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACpD,MAAM,CAAC,CAAC,EAAE,EAAgB,EAAE,CAAC,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAChE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,KAAK,GAAG,IAAI,CAAC;IACb,QAAQ,GAAG,IAAI,CAAC;AAClB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { PluginEntry } from "./openclaw-api.js";
2
+ declare const entry: PluginEntry;
3
+ export default entry;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,WAAW,EAEZ,MAAM,mBAAmB,CAAC;AA6F3B,QAAA,MAAM,KAAK,EAAE,WA2DZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,137 @@
1
+ import { fetchModelIds } from "./catalog.js";
2
+ const PLUGIN_ID = "runware-openclaw-provider";
3
+ const PROVIDER_ID = "runware";
4
+ const PROVIDER_LABEL = "Runware";
5
+ const DEFAULT_BASE_URL = "https://api.runware.ai/v1";
6
+ const DEFAULT_MODEL = "runware/anthropic-claude-sonnet-4-6";
7
+ const API_KEY_ENV_VAR = "RUNWARE_API_KEY";
8
+ const BASE_URL_ENV_VAR = "RUNWARE_BASE_URL";
9
+ const REQUEST_TIMEOUT_SECONDS = 600;
10
+ const MODEL_CONTEXT_WINDOW = 200_000;
11
+ const MODEL_MAX_TOKENS = 32_768;
12
+ const MODEL_INPUT_MODALITIES = ["text"];
13
+ const MODEL_PARAMS = { extra_body: { reasoning_effort: "high" } };
14
+ const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
15
+ function getBaseUrl(env) {
16
+ const override = (env?.[BASE_URL_ENV_VAR] ?? process.env[BASE_URL_ENV_VAR])?.trim();
17
+ return override && override.length > 0 ? override : DEFAULT_BASE_URL;
18
+ }
19
+ function resolveApiKey(ctx) {
20
+ return ctx?.env?.[API_KEY_ENV_VAR] ?? process.env[API_KEY_ENV_VAR];
21
+ }
22
+ function humanizeModelId(id) {
23
+ return id
24
+ .replace(/[-_:@]/g, " ")
25
+ .replace(/\bfp8\b/gi, "FP8")
26
+ .trim()
27
+ .split(/\s+/)
28
+ .map((word) => (word.length > 0 ? word[0].toUpperCase() + word.slice(1) : word))
29
+ .join(" ");
30
+ }
31
+ function buildModelEntry(id) {
32
+ return {
33
+ id,
34
+ name: humanizeModelId(id),
35
+ reasoning: true,
36
+ input: MODEL_INPUT_MODALITIES,
37
+ contextWindow: MODEL_CONTEXT_WINDOW,
38
+ maxTokens: MODEL_MAX_TOKENS,
39
+ cost: ZERO_COST,
40
+ params: MODEL_PARAMS,
41
+ };
42
+ }
43
+ async function buildProvider(apiKey, baseUrl) {
44
+ const ids = await fetchModelIds(baseUrl, apiKey);
45
+ return {
46
+ baseUrl,
47
+ apiKey,
48
+ api: "openai-completions",
49
+ timeoutSeconds: REQUEST_TIMEOUT_SECONDS,
50
+ models: ids.map(buildModelEntry),
51
+ };
52
+ }
53
+ function buildAgentModelsPatch(provider) {
54
+ const patch = {};
55
+ for (const model of provider.models) {
56
+ const key = `${PROVIDER_ID}/${model.id}`;
57
+ patch[key] = model.params ? { params: model.params } : {};
58
+ }
59
+ return patch;
60
+ }
61
+ async function authFlow(ctx) {
62
+ const apiKey = resolveApiKey(ctx);
63
+ if (!apiKey) {
64
+ throw new Error(`${API_KEY_ENV_VAR} is not set. Export it before running auth.`);
65
+ }
66
+ const provider = await buildProvider(apiKey, getBaseUrl(ctx.env));
67
+ return {
68
+ profiles: [
69
+ {
70
+ profileId: `${PROVIDER_ID}:default`,
71
+ provider: PROVIDER_ID,
72
+ credential: { type: "api-key", provider: PROVIDER_ID, apiKey },
73
+ },
74
+ ],
75
+ defaultModel: DEFAULT_MODEL,
76
+ configPatch: {
77
+ models: { providers: { [PROVIDER_ID]: provider } },
78
+ agents: { defaults: { models: buildAgentModelsPatch(provider) } },
79
+ },
80
+ };
81
+ }
82
+ const entry = {
83
+ id: PLUGIN_ID,
84
+ name: "Runware",
85
+ description: "Runware — unified OpenAI-compatible access to Claude, GPT, Gemini, Qwen, GLM, MiniMax, Kimi, and Gemma.",
86
+ register(api) {
87
+ api.registerProvider({
88
+ id: PROVIDER_ID,
89
+ label: PROVIDER_LABEL,
90
+ docsPath: "https://docs.runware.ai",
91
+ envVars: [API_KEY_ENV_VAR, BASE_URL_ENV_VAR],
92
+ auth: [
93
+ {
94
+ id: "api-key",
95
+ kind: "api-key",
96
+ label: PROVIDER_LABEL,
97
+ hint: `Runware API key — set ${API_KEY_ENV_VAR} or get one at https://runware.ai`,
98
+ envVar: API_KEY_ENV_VAR,
99
+ flagName: "--runware-api-key",
100
+ optionKey: "runwareApiKey",
101
+ promptMessage: "Enter your Runware API key",
102
+ defaultModel: DEFAULT_MODEL,
103
+ run: authFlow,
104
+ runNonInteractive: authFlow,
105
+ },
106
+ ],
107
+ discovery: {
108
+ order: "late",
109
+ run: async (ctx) => {
110
+ const apiKey = resolveApiKey(ctx);
111
+ if (!apiKey)
112
+ return null;
113
+ return { provider: await buildProvider(apiKey, getBaseUrl(ctx.env)) };
114
+ },
115
+ },
116
+ wizard: {
117
+ setup: {
118
+ choiceId: "runware",
119
+ choiceLabel: "Runware",
120
+ choiceHint: "Runware multi-model gateway",
121
+ groupId: "runware",
122
+ groupLabel: "Runware",
123
+ groupHint: "Runware multi-model gateway",
124
+ methodId: "api-key",
125
+ },
126
+ modelPicker: {
127
+ label: "Runware",
128
+ hint: "Enter your Runware API key",
129
+ methodId: "api-key",
130
+ },
131
+ },
132
+ buildUnknownModelHint: () => `Runware requires authentication. Set ${API_KEY_ENV_VAR} or run "openclaw models auth login --provider runware".`,
133
+ });
134
+ },
135
+ };
136
+ export default entry;
137
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Local description of the OpenClaw plugin API surface we use.
3
+ *
4
+ * Derived from inspecting bundled provider plugins in OpenClaw 2026.4.29.
5
+ * We do not import these types from `openclaw` — a plugin is a contract,
6
+ * not a dependency. If/when an official @openclaw/plugin-sdk ships, swap
7
+ * the interfaces below for imports in one place.
8
+ */
9
+ import type { ModelCost } from "./types.js";
10
+ export type DiscoveryOrder = "simple" | "profile" | "paired" | "late";
11
+ export type ProviderApi = "openai-completions" | "openai-responses" | "anthropic-by-model" | "google-gemini" | "passthrough-gemini" | "hybrid-anthropic-openai" | "amazon-bedrock";
12
+ export interface ModelEntry {
13
+ id: string;
14
+ name: string;
15
+ reasoning: boolean;
16
+ input: string[];
17
+ contextWindow: number;
18
+ maxTokens: number;
19
+ cost: ModelCost;
20
+ params?: Record<string, unknown>;
21
+ }
22
+ export interface ProviderShape {
23
+ baseUrl: string;
24
+ apiKey: string;
25
+ api: ProviderApi;
26
+ timeoutSeconds?: number;
27
+ models: ModelEntry[];
28
+ }
29
+ export interface DiscoveryResult {
30
+ provider?: ProviderShape;
31
+ providers?: Record<string, ProviderShape>;
32
+ }
33
+ export interface DiscoveryContext {
34
+ config?: unknown;
35
+ env?: Record<string, string | undefined>;
36
+ resolveProviderApiKey?: (providerId: string) => {
37
+ apiKey?: string;
38
+ };
39
+ }
40
+ export interface AuthRunContext {
41
+ prompter?: unknown;
42
+ config?: unknown;
43
+ env?: Record<string, string | undefined>;
44
+ }
45
+ export interface AuthMethod {
46
+ id: string;
47
+ kind: string;
48
+ label: string;
49
+ hint?: string;
50
+ envVar?: string;
51
+ flagName?: string;
52
+ optionKey?: string;
53
+ promptMessage?: string;
54
+ defaultModel?: string;
55
+ run?: (ctx: AuthRunContext) => Promise<unknown>;
56
+ runNonInteractive?: (ctx: AuthRunContext) => Promise<unknown>;
57
+ }
58
+ export interface WizardSetup {
59
+ choiceId: string;
60
+ choiceLabel: string;
61
+ choiceHint?: string;
62
+ groupId?: string;
63
+ groupLabel?: string;
64
+ groupHint?: string;
65
+ methodId: string;
66
+ }
67
+ export interface WizardModelPicker {
68
+ label: string;
69
+ hint?: string;
70
+ methodId: string;
71
+ }
72
+ export interface ProviderSpec {
73
+ id: string;
74
+ label: string;
75
+ docsPath?: string;
76
+ envVars?: string[];
77
+ auth: AuthMethod[];
78
+ discovery?: {
79
+ order: DiscoveryOrder;
80
+ run: (ctx: DiscoveryContext) => Promise<DiscoveryResult | null>;
81
+ };
82
+ wizard?: {
83
+ setup?: WizardSetup;
84
+ modelPicker?: WizardModelPicker;
85
+ };
86
+ buildUnknownModelHint?: () => string;
87
+ }
88
+ export interface PluginApi {
89
+ registerProvider: (spec: ProviderSpec) => void;
90
+ }
91
+ export interface PluginEntry {
92
+ id: string;
93
+ name: string;
94
+ description?: string;
95
+ register: (api: PluginApi) => void;
96
+ }
97
+ //# sourceMappingURL=openclaw-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-api.d.ts","sourceRoot":"","sources":["../src/openclaw-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Local description of the OpenClaw plugin API surface we use.
3
+ *
4
+ * Derived from inspecting bundled provider plugins in OpenClaw 2026.4.29.
5
+ * We do not import these types from `openclaw` — a plugin is a contract,
6
+ * not a dependency. If/when an official @openclaw/plugin-sdk ships, swap
7
+ * the interfaces below for imports in one place.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=openclaw-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-api.js","sourceRoot":"","sources":["../src/openclaw-api.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,7 @@
1
+ export interface ModelCost {
2
+ input: number;
3
+ output: number;
4
+ cacheRead: number;
5
+ cacheWrite: number;
6
+ }
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ {
2
+ "id": "runware-openclaw-provider",
3
+ "name": "@runware/openclaw-provider",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "configSchema": {
7
+ "$schema": "http://json-schema.org/draft-07/schema#",
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {}
11
+ },
12
+ "activation": { "onStartup": true },
13
+ "providers": ["runware"],
14
+ "providerRequest": {
15
+ "providers": {
16
+ "runware": {
17
+ "family": "runware",
18
+ "openAICompletions": { "supportsStreamingUsage": true }
19
+ }
20
+ }
21
+ },
22
+ "setup": {
23
+ "providers": [{ "id": "runware", "envVars": ["RUNWARE_API_KEY"] }]
24
+ },
25
+ "providerAuthChoices": [
26
+ {
27
+ "provider": "runware",
28
+ "method": "api-key",
29
+ "choiceId": "runware",
30
+ "choiceLabel": "Runware",
31
+ "choiceHint": "Runware multi-model gateway",
32
+ "groupId": "runware",
33
+ "groupLabel": "Runware",
34
+ "groupHint": "Runware multi-model gateway"
35
+ }
36
+ ],
37
+ "modelPricing": {
38
+ "providers": { "runware": { "external": false } }
39
+ },
40
+ "openclaw": {
41
+ "id": "runware-openclaw-provider",
42
+ "extensions": ["./dist/index.js"],
43
+ "providers": ["runware"]
44
+ }
45
+ }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@teith/openclaw-runware-provider",
3
+ "version": "0.1.0",
4
+ "description": "OpenClaw provider plugin for Runware — unified OpenAI-compatible access to Claude, GPT, Gemini, Qwen, GLM, MiniMax, Kimi, and Gemma.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ },
15
+ "./openclaw.plugin.json": "./openclaw.plugin.json"
16
+ },
17
+ "files": ["dist", "openclaw.plugin.json", "README.md", "LICENSE"],
18
+ "scripts": {
19
+ "build": "tsc -p tsconfig.build.json",
20
+ "dev": "tsc -p tsconfig.build.json --watch",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest",
23
+ "typecheck": "tsc --noEmit",
24
+ "clean": "rm -rf dist",
25
+ "prepublishOnly": "pnpm run clean && pnpm run build && pnpm run test"
26
+ },
27
+ "openclaw": {
28
+ "id": "runware-openclaw-provider",
29
+ "extensions": ["./dist/index.js"],
30
+ "providers": ["runware"]
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/runware/openclaw-provider.git"
35
+ },
36
+ "keywords": ["openclaw", "openclaw-plugin", "runware", "llm", "ai-provider"],
37
+ "engines": { "node": ">=20" },
38
+ "devDependencies": {
39
+ "@types/node": "^22.0.0",
40
+ "typescript": "^5.6.0",
41
+ "vitest": "^2.0.0"
42
+ }
43
+ }