Skip to content
Open
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
23 changes: 18 additions & 5 deletions src/sdk/client.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { loadConfig } from "../config/loader";
import { Config } from "../config/schema";
import { request as requestClient, requestJson as requestJsonClient, RequestOpts } from "../client/http";
import type { Config } from "../config/schema";
import { request as requestClient, requestJson as requestJsonClient } from "../client/http";
import type { RequestOpts } from "../client/http";
import { parseSSE } from "../client/stream";
import { SDKError } from "../errors/base";
import { ExitCode } from "../errors/codes";
import { MiniMaxSDKOptions } from "./types";
import type { MiniMaxSDKOptions } from "./types";

export class Client {
protected config: Config;
export class ClientContext {
readonly config: Config;

constructor(options: MiniMaxSDKOptions) {
const { apiKey, region, baseUrl } = options;
Expand All @@ -25,6 +26,18 @@ export class Client {
async: false,
});
}
}

export class Client {
protected readonly context: ClientContext;
protected readonly config: Config;

constructor(optionsOrContext: MiniMaxSDKOptions | ClientContext) {
this.context = optionsOrContext instanceof ClientContext
? optionsOrContext
: new ClientContext(optionsOrContext);
this.config = this.context.config;
}

protected request(opts: RequestOpts) {
return requestClient(this.config, opts);
Expand Down
20 changes: 10 additions & 10 deletions src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { VisionSDK } from "./vision";
import { QuotaSDK } from "./quota";
import { FileSDK } from "./file";
import { Client } from "./client";
import { MiniMaxSDKOptions } from "./types";
import type { MiniMaxSDKOptions } from "./types";

export class MiniMaxSDK extends Client {
readonly text: TextSDK;
Expand All @@ -23,14 +23,14 @@ export class MiniMaxSDK extends Client {

constructor(options: MiniMaxSDKOptions) {
super(options);
this.text = new TextSDK(options);
this.speech = new SpeechSDK(options);
this.image = new ImageSDK(options);
this.video = new VideoSDK(options);
this.music = new MusicSDK(options);
this.search = new SearchSDK(options);
this.vision = new VisionSDK(options);
this.quota = new QuotaSDK(options);
this.file = new FileSDK(options);
this.text = new TextSDK(this.context);
this.speech = new SpeechSDK(this.context);
this.image = new ImageSDK(this.context);
this.video = new VideoSDK(this.context);
this.music = new MusicSDK(this.context);
this.search = new SearchSDK(this.context);
this.vision = new VisionSDK(this.context);
this.quota = new QuotaSDK(this.context);
this.file = new FileSDK(this.context);
}
}
75 changes: 75 additions & 0 deletions test/sdk/client.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { afterEach, describe, expect, it } from 'bun:test';
import type { Config } from '../../src/config/schema';
import { MiniMaxSDK } from '../../src/sdk';
import { TextSDK } from '../../src/sdk/text';
import { createMockServer, jsonResponse, type MockServer } from '../helpers/mock-server';

interface ClientState {
context: object;
config: Config;
}

function clientState(client: object): ClientState {
return client as ClientState;
}

describe('SDK client context', () => {
let server: MockServer;

afterEach(() => {
server?.close();
});

it('shares one resolved context and config across all child SDKs', () => {
const sdk = new MiniMaxSDK({
apiKey: 'test-key',
baseUrl: 'https://example.com',
});
const rootState = clientState(sdk);
const childClients = [
sdk.text,
sdk.speech,
sdk.image,
sdk.video,
sdk.music,
sdk.search,
sdk.vision,
sdk.quota,
sdk.file,
];

for (const child of childClients) {
expect(clientState(child).context).toBe(rootState.context);
expect(clientState(child).config).toBe(rootState.config);
}

expect(rootState.config.apiKey).toBe('test-key');
expect(rootState.config.baseUrl).toBe('https://example.com');
});

it('preserves direct child SDK construction and request behavior', async () => {
server = createMockServer({
routes: {
'/anthropic/v1/messages': () => jsonResponse({
id: 'msg-direct',
type: 'message',
role: 'assistant',
content: [{ type: 'text', text: 'Hello!' }],
model: 'MiniMax-M3',
stop_reason: 'end_turn',
usage: { input_tokens: 1, output_tokens: 1 },
}),
},
});

const sdk = new TextSDK({
apiKey: 'test-key',
baseUrl: server.url,
});
const result = await sdk.chat({
messages: [{ role: 'user', content: 'Hello' }],
});

expect(result.id).toBe('msg-direct');
});
});
Loading