@wavespeed/cli 0.4.2 → 0.4.3
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 +18 -9
- package/dist/cli.js +1 -1
- package/dist/commands/aliases.js +1 -1
- package/dist/commands/auth.js +3 -2
- package/dist/commands/init.js +1 -1
- package/dist/lib/api.js +3 -2
- package/dist/lib/client-headers.js +40 -0
- package/dist/lib/client.js +3 -2
- package/package.json +3 -3
- package/skills/SKILL.md +11 -9
package/README.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<a href="https://wavespeed.ai" target="_blank">
|
|
3
|
-
<
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/wavespeed-logo-dark.svg">
|
|
5
|
+
<img src="assets/wavespeed-logo-light.svg" alt="WaveSpeed" width="342" height="48"/>
|
|
6
|
+
</picture>
|
|
4
7
|
</a>
|
|
5
8
|
|
|
6
9
|
<h1>WaveSpeed CLI</h1>
|
|
@@ -74,14 +77,14 @@ wavespeed run ... -p "..." --json | jq '.outputs[0]'
|
|
|
74
77
|
|
|
75
78
|
```jsonc
|
|
76
79
|
{
|
|
77
|
-
"defaultModel": "
|
|
80
|
+
"defaultModel": "bytedance/seedream-v5.0-pro",
|
|
78
81
|
"outputDir": "wavespeed-output",
|
|
79
82
|
"aliases": {
|
|
80
|
-
"hero": { "model": "
|
|
83
|
+
"hero": { "model": "bytedance/seedream-v5.0-pro",
|
|
81
84
|
"input": { "aspect_ratio": "16:9", "resolution": "2k" } },
|
|
82
|
-
"social": { "model": "
|
|
85
|
+
"social": { "model": "bytedance/seedream-v5.0-pro",
|
|
83
86
|
"input": { "aspect_ratio": "1:1", "resolution": "1k" } },
|
|
84
|
-
"vid": { "model": "bytedance/seedance-2.
|
|
87
|
+
"vid": { "model": "bytedance/seedance-2.5/text-to-video",
|
|
85
88
|
"input": { "resolution": "720p", "duration": 5 } }
|
|
86
89
|
}
|
|
87
90
|
}
|
|
@@ -98,10 +101,12 @@ Resolution: positional with `/` is a model ID; otherwise looked up as an alias.
|
|
|
98
101
|
|
|
99
102
|
| Use case | Model |
|
|
100
103
|
|---|---|
|
|
101
|
-
| Text → image | `
|
|
102
|
-
| Image edit | `
|
|
103
|
-
| Text → video | `bytedance/seedance-2.
|
|
104
|
-
| Image → video | `bytedance/seedance-2.
|
|
104
|
+
| Text → image | `bytedance/seedream-v5.0-pro` |
|
|
105
|
+
| Image edit | `bytedance/seedream-v5.0-pro/edit` |
|
|
106
|
+
| Text → video | `bytedance/seedance-2.5/text-to-video` |
|
|
107
|
+
| Image → video | `bytedance/seedance-2.5/image-to-video` |
|
|
108
|
+
| Video edit | `bytedance/seedance-2.5/video-edit` |
|
|
109
|
+
| Video extend | `bytedance/seedance-2.5/video-extend` |
|
|
105
110
|
|
|
106
111
|
Browse alternatives with `wavespeed models <query>`.
|
|
107
112
|
|
|
@@ -115,6 +120,10 @@ wavespeed skill install # writes .claude/skills/wavespeed/SKILL.md
|
|
|
115
120
|
|
|
116
121
|
The skill teaches the agent the three-step pattern: `models` to find, `run <id> -h` to discover params, `run <id> -p "…" --json` to execute. Every command supports `--json` for clean piping.
|
|
117
122
|
|
|
123
|
+
**OpenCode** loads the same file with no extra steps — `.claude/skills/` is on its skill search path.
|
|
124
|
+
|
|
125
|
+
**DeepSeek Harness (dsh)**: the same skill is packaged for dsh's `.dsh/skills` layout at [WaveSpeedAI/wavespeed-dsh-skill](https://github.com/WaveSpeedAI/wavespeed-dsh-skill).
|
|
126
|
+
|
|
118
127
|
## Commands
|
|
119
128
|
|
|
120
129
|
```
|
package/dist/cli.js
CHANGED
|
@@ -44,7 +44,7 @@ ${chalk.bold('Quick start:')}
|
|
|
44
44
|
${chalk.cyan('$ wavespeed models # browse the catalog')}
|
|
45
45
|
${chalk.cyan('$ wavespeed run wavespeed-ai/z-image/turbo -h # see the model\'s flags')}
|
|
46
46
|
${chalk.cyan('$ wavespeed run wavespeed-ai/z-image/turbo -p "a cyberpunk skyline" # ~5s')}
|
|
47
|
-
${chalk.cyan('$ wavespeed run bytedance/seedance-2.
|
|
47
|
+
${chalk.cyan('$ wavespeed run bytedance/seedance-2.5/text-to-video -p "drone shot over snowy peaks"')}
|
|
48
48
|
|
|
49
49
|
${chalk.bold('Use from any coding agent (Claude Code, Cursor, Codex):')}
|
|
50
50
|
${chalk.cyan('$ wavespeed skill install')} ${chalk.gray('# drops a SKILL.md so the agent knows how to call wavespeed')}
|
package/dist/commands/aliases.js
CHANGED
|
@@ -23,7 +23,7 @@ export function registerAliases(program) {
|
|
|
23
23
|
console.log(chalk.gray(JSON.stringify({
|
|
24
24
|
aliases: {
|
|
25
25
|
hero: {
|
|
26
|
-
model: '
|
|
26
|
+
model: 'bytedance/seedream-v5.0-pro',
|
|
27
27
|
input: { aspect_ratio: '16:9', resolution: '2k' },
|
|
28
28
|
},
|
|
29
29
|
},
|
package/dist/commands/auth.js
CHANGED
|
@@ -5,6 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
import clipboard from 'clipboardy';
|
|
6
6
|
import { userConfig, getBaseUrl, getApiKey, loadProjectConfig, PROJECT_FILE } from '../lib/config.js';
|
|
7
7
|
import { LINKS } from '../lib/links.js';
|
|
8
|
+
import { clientAttributionHeaders } from '../lib/client-headers.js';
|
|
8
9
|
const KEY_URL = 'https://wavespeed.ai/accesskey';
|
|
9
10
|
function mask(key) {
|
|
10
11
|
if (key.length < 12)
|
|
@@ -40,7 +41,7 @@ async function validateKey(apiKey, baseUrl) {
|
|
|
40
41
|
let res = null;
|
|
41
42
|
try {
|
|
42
43
|
res = await fetch(`${baseUrl}/api/v3/balance`, {
|
|
43
|
-
headers: { Authorization: `Bearer ${apiKey}
|
|
44
|
+
headers: { Authorization: `Bearer ${apiKey}`, ...clientAttributionHeaders() },
|
|
44
45
|
});
|
|
45
46
|
}
|
|
46
47
|
catch (err) {
|
|
@@ -108,7 +109,7 @@ async function loginFlow(opts) {
|
|
|
108
109
|
console.log(chalk.bold('Try it:'));
|
|
109
110
|
console.log(' ' + chalk.cyan('wavespeed models # browse the catalog'));
|
|
110
111
|
console.log(' ' + chalk.cyan('wavespeed run wavespeed-ai/z-image/turbo -p "a cyberpunk skyline at golden hour"'));
|
|
111
|
-
console.log(' ' + chalk.cyan('wavespeed run bytedance/seedance-2.
|
|
112
|
+
console.log(' ' + chalk.cyan('wavespeed run bytedance/seedance-2.5/text-to-video -p "drone shot over snowy peaks"'));
|
|
112
113
|
console.log();
|
|
113
114
|
}
|
|
114
115
|
export function registerAuth(program) {
|
package/dist/commands/init.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { input, confirm } from '@inquirer/prompts';
|
|
5
5
|
import { PROJECT_FILE } from '../lib/config.js';
|
|
6
|
-
const STARTER_MODEL = '
|
|
6
|
+
const STARTER_MODEL = 'bytedance/seedream-v5.0-pro';
|
|
7
7
|
export function registerInit(program) {
|
|
8
8
|
program
|
|
9
9
|
.command('init')
|
package/dist/lib/api.js
CHANGED
|
@@ -5,6 +5,7 @@ import fs from 'node:fs';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import { getApiKey, getBaseUrl } from './config.js';
|
|
8
|
+
import { clientAttributionHeaders } from './client-headers.js';
|
|
8
9
|
const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
9
10
|
function cachePath() {
|
|
10
11
|
return path.join(os.homedir(), '.cache', 'wavespeed', 'models.json');
|
|
@@ -44,7 +45,7 @@ export async function fetchModels(opts = {}) {
|
|
|
44
45
|
if (!apiKey)
|
|
45
46
|
throw new Error('No API key configured. Run `wavespeed login`.');
|
|
46
47
|
const res = await fetch(`${baseUrl}/api/v3/models`, {
|
|
47
|
-
headers: { Authorization: `Bearer ${apiKey}
|
|
48
|
+
headers: { Authorization: `Bearer ${apiKey}`, ...clientAttributionHeaders() },
|
|
48
49
|
});
|
|
49
50
|
if (!res.ok) {
|
|
50
51
|
throw await httpError(res, 'GET', '/api/v3/models');
|
|
@@ -70,7 +71,7 @@ function authHeaders() {
|
|
|
70
71
|
const apiKey = getApiKey();
|
|
71
72
|
if (!apiKey)
|
|
72
73
|
throw new Error('No API key configured. Run `wavespeed login`.');
|
|
73
|
-
return { Authorization: `Bearer ${apiKey}
|
|
74
|
+
return { Authorization: `Bearer ${apiKey}`, ...clientAttributionHeaders() };
|
|
74
75
|
}
|
|
75
76
|
// Non-2xx responses still carry the platform's error envelope, and for
|
|
76
77
|
// permission failures that body is the whole point: it names the role that
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Channel-attribution headers (X-Client-Name / X-Client-Version / X-Client-OS)
|
|
2
|
+
// for the CLI's direct REST calls, matching the convention wavespeed-desktop
|
|
3
|
+
// uses. Calls that go through the `wavespeed` SDK get the same headers from
|
|
4
|
+
// the SDK itself (via the clientName option in client.ts).
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import os from 'node:os';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
export const CLI_CLIENT_NAME = 'wavespeed-cli';
|
|
10
|
+
// Read version from package.json at runtime so a bump in package.json is
|
|
11
|
+
// reflected automatically (same approach as cli.ts).
|
|
12
|
+
function cliVersion() {
|
|
13
|
+
try {
|
|
14
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
// dist/lib/client-headers.js → ../../package.json
|
|
16
|
+
const pkgPath = path.resolve(here, '..', '..', 'package.json');
|
|
17
|
+
return JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return '0.0.0';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Lowercase OS name: darwin / linux / windows (win32 is reported as windows).
|
|
24
|
+
function operatingSystem() {
|
|
25
|
+
const platform = os.platform();
|
|
26
|
+
return platform === 'win32' ? 'windows' : platform;
|
|
27
|
+
}
|
|
28
|
+
// The WAVESPEED_CLIENT_NAME environment variable takes priority so wrapper
|
|
29
|
+
// channels (dsh skill, Claude plugin, Gemini extension) can brand themselves
|
|
30
|
+
// without code changes.
|
|
31
|
+
export function resolveClientName() {
|
|
32
|
+
return process.env.WAVESPEED_CLIENT_NAME || CLI_CLIENT_NAME;
|
|
33
|
+
}
|
|
34
|
+
export function clientAttributionHeaders() {
|
|
35
|
+
return {
|
|
36
|
+
'X-Client-Name': resolveClientName(),
|
|
37
|
+
'X-Client-Version': cliVersion(),
|
|
38
|
+
'X-Client-OS': operatingSystem(),
|
|
39
|
+
};
|
|
40
|
+
}
|
package/dist/lib/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Client } from 'wavespeed';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { getApiKey, getBaseUrl } from './config.js';
|
|
4
|
+
import { CLI_CLIENT_NAME } from './client-headers.js';
|
|
4
5
|
export function requireClient() {
|
|
5
6
|
const apiKey = getApiKey();
|
|
6
7
|
if (!apiKey) {
|
|
@@ -9,11 +10,11 @@ export function requireClient() {
|
|
|
9
10
|
console.error(chalk.gray('Or set ') + chalk.cyan('WAVESPEED_API_KEY') + chalk.gray(' in your environment.\n'));
|
|
10
11
|
process.exit(1);
|
|
11
12
|
}
|
|
12
|
-
return new Client(apiKey, { baseUrl: getBaseUrl() });
|
|
13
|
+
return new Client(apiKey, { baseUrl: getBaseUrl(), clientName: CLI_CLIENT_NAME });
|
|
13
14
|
}
|
|
14
15
|
export function maybeClient() {
|
|
15
16
|
const apiKey = getApiKey();
|
|
16
17
|
if (!apiKey)
|
|
17
18
|
return null;
|
|
18
|
-
return new Client(apiKey, { baseUrl: getBaseUrl() });
|
|
19
|
+
return new Client(apiKey, { baseUrl: getBaseUrl(), clientName: CLI_CLIENT_NAME });
|
|
19
20
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wavespeed/cli",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "WaveSpeed CLI
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"description": "WaveSpeed CLI \u2014 one command to run any WaveSpeed AI model from your terminal.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"conf": "^13.0.0",
|
|
57
57
|
"open": "^10.1.0",
|
|
58
58
|
"ora": "^8.1.0",
|
|
59
|
-
"wavespeed": "^0.
|
|
59
|
+
"wavespeed": "^0.3.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/node": "^20.14.0",
|
package/skills/SKILL.md
CHANGED
|
@@ -11,14 +11,14 @@ You have access to the `wavespeed` CLI. Every generation flows through one verb.
|
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
13
|
# 1. FIND a model — search the live catalog
|
|
14
|
-
wavespeed models "
|
|
14
|
+
wavespeed models "seedream"
|
|
15
15
|
wavespeed models --type image-to-video --popular
|
|
16
16
|
|
|
17
17
|
# 2. INSPECT its inputs — dynamic schema, per model
|
|
18
|
-
wavespeed run
|
|
18
|
+
wavespeed run bytedance/seedream-v5.0-pro -h
|
|
19
19
|
|
|
20
20
|
# 3. RUN it — always pass --json so you can read the result
|
|
21
|
-
wavespeed run
|
|
21
|
+
wavespeed run bytedance/seedream-v5.0-pro \
|
|
22
22
|
-p "a cyberpunk skyline at golden hour" \
|
|
23
23
|
-i aspect_ratio="16:9" -i resolution="2k" --json
|
|
24
24
|
```
|
|
@@ -29,10 +29,12 @@ wavespeed run google/nano-banana-2/text-to-image \
|
|
|
29
29
|
|
|
30
30
|
| Use case | Model |
|
|
31
31
|
|---|---|
|
|
32
|
-
| Text → image | `
|
|
33
|
-
| Image edit (instruction-driven) | `
|
|
34
|
-
| Text → video | `bytedance/seedance-2.
|
|
35
|
-
| Image → video | `bytedance/seedance-2.
|
|
32
|
+
| Text → image | `bytedance/seedream-v5.0-pro` |
|
|
33
|
+
| Image edit (instruction-driven) | `bytedance/seedream-v5.0-pro/edit` — requires `images: [url, ...]` |
|
|
34
|
+
| Text → video | `bytedance/seedance-2.5/text-to-video` |
|
|
35
|
+
| Image → video | `bytedance/seedance-2.5/image-to-video` — requires `image: url` |
|
|
36
|
+
| Video edit (instruction-driven) | `bytedance/seedance-2.5/video-edit` — requires `video: url` |
|
|
37
|
+
| Video extend | `bytedance/seedance-2.5/video-extend` — requires `video: url` |
|
|
36
38
|
|
|
37
39
|
These are good starting points. Browse alternatives with `wavespeed models <query>`.
|
|
38
40
|
|
|
@@ -40,12 +42,12 @@ These are good starting points. Browse alternatives with `wavespeed models <quer
|
|
|
40
42
|
|
|
41
43
|
```bash
|
|
42
44
|
# Edit an existing image — @path uploads the file and passes its URL (one step)
|
|
43
|
-
wavespeed run
|
|
45
|
+
wavespeed run bytedance/seedream-v5.0-pro/edit \
|
|
44
46
|
-p "replace the background with a sunlit kitchen" \
|
|
45
47
|
-i images='["@./input.jpg"]' --json
|
|
46
48
|
|
|
47
49
|
# Image-to-video — same @ marker for single-URL fields
|
|
48
|
-
wavespeed run bytedance/seedance-2.
|
|
50
|
+
wavespeed run bytedance/seedance-2.5/image-to-video \
|
|
49
51
|
-p "subtle parallax, gentle wind" \
|
|
50
52
|
-i image=@./hero.jpg -i duration=5 --json
|
|
51
53
|
|