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
188 changes: 188 additions & 0 deletions SDK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# MiniMax SDK

TypeScript SDK for the [MiniMax](https://www.minimaxi.com) AI platform.

## Installation

```bash
npm install mmx-cli
```

## Quick Start

```typescript
import { MiniMaxSDK } from 'mmx-cli/sdk';

const sdk = new MiniMaxSDK({
apiKey: 'sk-xxxxx',
region: 'global', // or 'cn'
});
```

You can also omit `apiKey` if it's already configured via `mmx config set api-key <key>`.

## Modules

### Text

```typescript
const response = await sdk.text.chat({
model: 'MiniMax-M2.7',
messages: [{ role: 'user', content: 'Hello!' }],
max_tokens: 4096,
});

// Streaming
const stream = await sdk.text.chat({
model: 'MiniMax-M2.7',
messages: [{ role: 'user', content: 'Write a poem' }],
stream: true,
});

for await (const event of stream) {
console.log(event.choices[0]?.delta?.content);
}
```

### Image

```typescript
const result = await sdk.image.generate({
model: 'image-01',
prompt: 'A cat in a spacesuit',
width: 1024,
height: 1024,
n: 1,
});
```

### Video

```typescript
// Synchronous — waits for completion
const video = await sdk.video.generate({
model: 'MiniMax-Hailuo-2.3',
prompt: 'Ocean waves at sunset',
});

// Asynchronous — returns task ID immediately
const { taskId } = await sdk.video.generate({
prompt: 'A robot painting',
async: true,
});

const task = await sdk.video.getTask({ taskId });

// Download
const { size, save, downloadUrl } = await sdk.video.download({
fileId: '176844028768320',
outPath: './video.mp4',
});
```

### Speech

```typescript
const speech = await sdk.speech.synthesize({
model: 'speech-2.8-hd',
text: 'Hello, world!',
voice_setting: { voice_id: 'English_expressive_narrator' },
audio_setting: { format: 'mp3', sample_rate: 32000, bitrate: 128000, channel: 1 },
});

// Streaming
const stream = await sdk.speech.synthesize({
text: 'Stream me',
stream: true,
});

for await (const chunk of stream) {
// process audio chunks
}

// List voices
const voices = await sdk.speech.voices();
const englishVoices = await sdk.speech.voices('en');
```

### Music

```typescript
const music = await sdk.music.generate({
model: 'music-2.6',
prompt: 'Upbeat pop song',
lyrics: '[verse] La da dee, sunny day',
output_format: 'hex',
});

// Instrumental
const instrumental = await sdk.music.generate({
prompt: 'Cinematic orchestral',
instrumental: true,
});

// Auto-generate lyrics
const autoLyrics = await sdk.music.generate({
prompt: 'Indie folk, melancholic, rainy night',
lyrics_optimizer: true,
});

// Streaming
const stream = await sdk.music.generate({
prompt: 'Upbeat pop',
lyrics: '[verse] Hello world',
stream: true,
});

for await (const chunk of stream) {
// process audio chunks
}

// Structured prompt
const structured = await sdk.music.generate({
prompt: 'A beautiful song',
vocals: 'warm male baritone',
genre: 'jazz',
mood: 'relaxing',
instruments: 'piano, saxophone',
bpm: 120,
key: 'C major',
});
```

### Vision

```typescript
const result = await sdk.vision.describe({
image: 'https://example.com/photo.jpg',
prompt: 'What breed is this dog?',
});

console.log(result.content);
```

### Search

```typescript
const results = await sdk.search.query('MiniMax AI latest news');

for (const item of results.organic) {
console.log(item.title, item.link, item.snippet);
}
```

### Quota

```typescript
const quota = await sdk.quota.info();
console.log(quota);
```

## Custom Base URL

```typescript
const sdk = new MiniMaxSDK({
apiKey: 'sk-xxxxx',
baseUrl: 'https://api.minimax.io',
});
```
15 changes: 15 additions & 0 deletions build.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { readFileSync, writeFileSync } from 'fs';
import dts from 'bun-plugin-dts';

const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
const VERSION = process.env.VERSION ?? pkg.version;
const OUT = 'dist/mmx.mjs';
const SDK_OUT = 'dist/sdk.mjs';
const DEV_BUILD = process.argv.includes('--dev');

await Bun.build({
Expand All @@ -19,3 +21,16 @@ writeFileSync(OUT, Buffer.concat([Buffer.from('#!/usr/bin/env node\n'), content]

const size = (content.length / 1024).toFixed(0);
console.log(`dist/mmx.mjs ${size}KB`);

await Bun.build({
entrypoints: ['src/sdk/index.ts'],
outdir: 'dist',
naming: 'sdk.mjs',
target: 'node',
minify: false,
plugins: [dts()],
});

const sdkContent = readFileSync(SDK_OUT);
const sdkSize = (sdkContent.length / 1024).toFixed(0);
console.log(`dist/sdk.mjs ${sdkSize}KB`);
40 changes: 40 additions & 0 deletions bun.lock

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

15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@
"mmx": "dist/mmx.mjs"
},
"files": [
"dist/mmx.mjs"
"dist/mmx.mjs",
"dist/sdk.mjs",
"dist/index.d.ts"
],
"exports": {
"./sdk": {
"import": "./dist/sdk.mjs",
"types": "./dist/index.d.ts"
},
"./package.json": "./package.json"
},
"scripts": {
"dev": "bun run src/main.ts",
"build": "bun run build.ts",
Expand All @@ -23,7 +32,9 @@
"test:watch": "bun test --watch"
},
"dependencies": {
"@clack/prompts": "^0.7.0"
"@clack/prompts": "^0.7.0",
"bun-plugin-dts": "^0.4.0",
"es-toolkit": "^1.46.1"
},
"devDependencies": {
"@eslint/js": "^9.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/speech/voices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function extractLanguage(voiceId: string): string {
return match ? match[1] : voiceId;
}

function filterByLanguage(voices: SystemVoiceInfo[], language: string): SystemVoiceInfo[] {
export function filterByLanguage(voices: SystemVoiceInfo[], language: string): SystemVoiceInfo[] {
const lang = language.toLowerCase();
return voices.filter(v => {
const voiceLang = extractLanguage(v.voice_id).toLowerCase();
Expand Down
2 changes: 1 addition & 1 deletion src/commands/vision/describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const MIME_TYPES: Record<string, string> = {

const MAX_IMAGE_SIZE_BYTES = 50 * 1024 * 1024; // 50 MB limit

async function toDataUri(image: string): Promise<string> {
export async function toDataUri(image: string): Promise<string> {
if (image.startsWith('data:')) return image;

if (image.startsWith('http://') || image.startsWith('https://')) {
Expand Down
12 changes: 12 additions & 0 deletions src/errors/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,15 @@ export class CLIError extends Error {
};
}
}

export class SDKError extends CLIError {
readonly exitCode: ExitCode;
readonly hint?: string;

constructor(message: string, exitCode: ExitCode = ExitCode.GENERAL, hint?: string) {
super(message);
this.name = 'SDKError';
this.exitCode = exitCode;
this.hint = hint;
}
}
Loading