@ai-sdk/gmicloud 0.0.0 → 1.0.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/CHANGELOG.md +1 -0
- package/LICENSE +13 -0
- package/README.md +48 -2
- package/dist/index.d.mts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +121 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +98 -0
- package/dist/index.mjs.map +1 -0
- package/docs/100-gmicloud.mdx +72 -0
- package/package.json +70 -10
- package/src/gmicloud-chat-language-model-options.ts +3 -0
- package/src/gmicloud-chat-language-model.ts +9 -0
- package/src/gmicloud-chat-options.ts +8 -0
- package/src/gmicloud-error.ts +44 -0
- package/src/gmicloud-provider.ts +103 -0
- package/src/index.ts +7 -0
- package/src/version.ts +6 -0
- package/index.js +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @ai-sdk/gmicloud
|
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2023 Vercel, Inc.
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AI SDK - GMI Cloud Provider
|
|
2
2
|
|
|
3
|
-
AI SDK
|
|
3
|
+
The **GMI Cloud provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for [GMI Cloud](https://www.gmicloud.ai), offering GPU inference for open-weight models over an OpenAI-compatible API.
|
|
4
|
+
|
|
5
|
+
> **Deploying to Vercel?** With Vercel's AI Gateway you can access GMI Cloud (and hundreds of models from other providers) — no additional packages, API keys, or extra cost. [Get started with AI Gateway](https://vercel.com/ai-gateway).
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
The GMI Cloud provider is available in the `@ai-sdk/gmicloud` module. You can install it with
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i @ai-sdk/gmicloud
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Provider Instance
|
|
16
|
+
|
|
17
|
+
You can import the default provider instance `gmicloud` from `@ai-sdk/gmicloud`:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The GMI Cloud API key is read from the `GMI_CLOUD_APIKEY` environment variable by default. For custom configuration, use `createGmicloud`:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { createGmicloud } from '@ai-sdk/gmicloud';
|
|
27
|
+
|
|
28
|
+
const gmicloud = createGmicloud({
|
|
29
|
+
apiKey: process.env.GMI_CLOUD_APIKEY ?? '',
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Language Models
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
37
|
+
import { generateText } from 'ai';
|
|
38
|
+
|
|
39
|
+
const { text } = await generateText({
|
|
40
|
+
model: gmicloud('deepseek-ai/DeepSeek-V4-Flash-0731'),
|
|
41
|
+
prompt: 'What is the capital of France?',
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
GMI Cloud serves an evolving catalog of open-weight models over chat completions, so model ids are typed as `string`. Embedding and image models are not supported.
|
|
46
|
+
|
|
47
|
+
## Error diagnostics
|
|
48
|
+
|
|
49
|
+
GMI Cloud's edge reports a generic banner in `error.message` on rejections and nests the backend engine's diagnostic in `error.details`. This provider unwraps the nested diagnostic, so `AI_APICallError.message` carries the engine's reason (e.g. `The request is invalid: Invalid max_tokens value, the valid range of max_tokens is [1, 393216].`) instead of `Backend request failed with status 400`.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ProviderV2, LanguageModelV2 } from '@ai-sdk/provider';
|
|
2
|
+
import { FetchFunction } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { z } from 'zod/v4';
|
|
4
|
+
|
|
5
|
+
type GmicloudChatModelId = 'deepseek-ai/DeepSeek-V4-Flash-0731' | 'Qwen/Qwen3.8-Max' | 'moonshotai/kimi-k3' | 'zai-org/GLM-5.2-FP8' | 'MiniMaxAI/MiniMax-M3' | (string & {});
|
|
6
|
+
|
|
7
|
+
interface GmicloudProviderSettings {
|
|
8
|
+
/**
|
|
9
|
+
* GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment
|
|
10
|
+
* variable (matching GMI's own SDK package).
|
|
11
|
+
*/
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Base URL for the API calls. Defaults to
|
|
15
|
+
* `https://api.gmi-serving.com/v1`.
|
|
16
|
+
*/
|
|
17
|
+
baseURL?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Custom headers to include in the requests.
|
|
20
|
+
*/
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Custom fetch implementation. You can use it as a middleware to intercept
|
|
24
|
+
* requests, or to provide a custom fetch implementation for e.g. testing.
|
|
25
|
+
*/
|
|
26
|
+
fetch?: FetchFunction;
|
|
27
|
+
}
|
|
28
|
+
interface GmicloudProvider extends ProviderV2 {
|
|
29
|
+
/**
|
|
30
|
+
* Creates a GMI Cloud model for text generation.
|
|
31
|
+
*/
|
|
32
|
+
(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a GMI Cloud model for text generation.
|
|
35
|
+
*/
|
|
36
|
+
languageModel(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a GMI Cloud chat model for text generation.
|
|
39
|
+
*/
|
|
40
|
+
chat(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
41
|
+
}
|
|
42
|
+
declare function createGmicloud(options?: GmicloudProviderSettings): GmicloudProvider;
|
|
43
|
+
declare const gmicloud: GmicloudProvider;
|
|
44
|
+
|
|
45
|
+
declare const gmicloudErrorDataSchema: z.ZodObject<{
|
|
46
|
+
error: z.ZodObject<{
|
|
47
|
+
message: z.ZodString;
|
|
48
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
param: z.ZodOptional<z.ZodNullable<z.ZodAny>>;
|
|
50
|
+
code: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
51
|
+
details: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;
|
|
55
|
+
|
|
56
|
+
declare const VERSION: string;
|
|
57
|
+
|
|
58
|
+
export { type GmicloudErrorData, type GmicloudProvider, type GmicloudProviderSettings, VERSION, createGmicloud, gmicloud };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ProviderV2, LanguageModelV2 } from '@ai-sdk/provider';
|
|
2
|
+
import { FetchFunction } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { z } from 'zod/v4';
|
|
4
|
+
|
|
5
|
+
type GmicloudChatModelId = 'deepseek-ai/DeepSeek-V4-Flash-0731' | 'Qwen/Qwen3.8-Max' | 'moonshotai/kimi-k3' | 'zai-org/GLM-5.2-FP8' | 'MiniMaxAI/MiniMax-M3' | (string & {});
|
|
6
|
+
|
|
7
|
+
interface GmicloudProviderSettings {
|
|
8
|
+
/**
|
|
9
|
+
* GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment
|
|
10
|
+
* variable (matching GMI's own SDK package).
|
|
11
|
+
*/
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Base URL for the API calls. Defaults to
|
|
15
|
+
* `https://api.gmi-serving.com/v1`.
|
|
16
|
+
*/
|
|
17
|
+
baseURL?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Custom headers to include in the requests.
|
|
20
|
+
*/
|
|
21
|
+
headers?: Record<string, string>;
|
|
22
|
+
/**
|
|
23
|
+
* Custom fetch implementation. You can use it as a middleware to intercept
|
|
24
|
+
* requests, or to provide a custom fetch implementation for e.g. testing.
|
|
25
|
+
*/
|
|
26
|
+
fetch?: FetchFunction;
|
|
27
|
+
}
|
|
28
|
+
interface GmicloudProvider extends ProviderV2 {
|
|
29
|
+
/**
|
|
30
|
+
* Creates a GMI Cloud model for text generation.
|
|
31
|
+
*/
|
|
32
|
+
(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a GMI Cloud model for text generation.
|
|
35
|
+
*/
|
|
36
|
+
languageModel(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a GMI Cloud chat model for text generation.
|
|
39
|
+
*/
|
|
40
|
+
chat(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
41
|
+
}
|
|
42
|
+
declare function createGmicloud(options?: GmicloudProviderSettings): GmicloudProvider;
|
|
43
|
+
declare const gmicloud: GmicloudProvider;
|
|
44
|
+
|
|
45
|
+
declare const gmicloudErrorDataSchema: z.ZodObject<{
|
|
46
|
+
error: z.ZodObject<{
|
|
47
|
+
message: z.ZodString;
|
|
48
|
+
type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
49
|
+
param: z.ZodOptional<z.ZodNullable<z.ZodAny>>;
|
|
50
|
+
code: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
51
|
+
details: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;
|
|
55
|
+
|
|
56
|
+
declare const VERSION: string;
|
|
57
|
+
|
|
58
|
+
export { type GmicloudErrorData, type GmicloudProvider, type GmicloudProviderSettings, VERSION, createGmicloud, gmicloud };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
VERSION: () => VERSION,
|
|
24
|
+
createGmicloud: () => createGmicloud,
|
|
25
|
+
gmicloud: () => gmicloud
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/gmicloud-provider.ts
|
|
30
|
+
var import_provider = require("@ai-sdk/provider");
|
|
31
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
32
|
+
|
|
33
|
+
// src/gmicloud-chat-language-model.ts
|
|
34
|
+
var import_openai_compatible = require("@ai-sdk/openai-compatible");
|
|
35
|
+
var GmicloudChatLanguageModel = class extends import_openai_compatible.OpenAICompatibleChatLanguageModel {
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/gmicloud-error.ts
|
|
39
|
+
var import_v4 = require("zod/v4");
|
|
40
|
+
var gmicloudErrorDataSchema = import_v4.z.object({
|
|
41
|
+
error: import_v4.z.object({
|
|
42
|
+
message: import_v4.z.string(),
|
|
43
|
+
type: import_v4.z.string().nullish(),
|
|
44
|
+
param: import_v4.z.any().nullish(),
|
|
45
|
+
code: import_v4.z.union([import_v4.z.string(), import_v4.z.number()]).nullish(),
|
|
46
|
+
details: import_v4.z.string().nullish()
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
function tryParseDetails(details) {
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(details);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function unwrapDetailsMessage(details) {
|
|
57
|
+
var _a, _b;
|
|
58
|
+
if (details == null || details === "") {
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
const message = (_b = (_a = tryParseDetails(details)) == null ? void 0 : _a.error) == null ? void 0 : _b.message;
|
|
62
|
+
return typeof message === "string" && message.trim() !== "" ? message : void 0;
|
|
63
|
+
}
|
|
64
|
+
var gmicloudErrorStructure = {
|
|
65
|
+
errorSchema: gmicloudErrorDataSchema,
|
|
66
|
+
errorToMessage: (data) => {
|
|
67
|
+
var _a;
|
|
68
|
+
return (_a = unwrapDetailsMessage(data.error.details)) != null ? _a : data.error.message;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// src/version.ts
|
|
73
|
+
var VERSION = true ? "1.0.0" : "0.0.0-test";
|
|
74
|
+
|
|
75
|
+
// src/gmicloud-provider.ts
|
|
76
|
+
function createGmicloud(options = {}) {
|
|
77
|
+
var _a;
|
|
78
|
+
const baseURL = (0, import_provider_utils.withoutTrailingSlash)(
|
|
79
|
+
(_a = options.baseURL) != null ? _a : "https://api.gmi-serving.com/v1"
|
|
80
|
+
);
|
|
81
|
+
const getHeaders = () => (0, import_provider_utils.withUserAgentSuffix)(
|
|
82
|
+
{
|
|
83
|
+
Authorization: `Bearer ${(0, import_provider_utils.loadApiKey)({
|
|
84
|
+
apiKey: options.apiKey,
|
|
85
|
+
environmentVariableName: "GMI_CLOUD_APIKEY",
|
|
86
|
+
description: "GMI Cloud API key"
|
|
87
|
+
})}`,
|
|
88
|
+
...options.headers
|
|
89
|
+
},
|
|
90
|
+
`ai-sdk/gmicloud/${VERSION}`
|
|
91
|
+
);
|
|
92
|
+
const createLanguageModel = (modelId) => {
|
|
93
|
+
return new GmicloudChatLanguageModel(modelId, {
|
|
94
|
+
provider: `gmicloud.chat`,
|
|
95
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
96
|
+
headers: getHeaders,
|
|
97
|
+
fetch: options.fetch,
|
|
98
|
+
errorStructure: gmicloudErrorStructure,
|
|
99
|
+
includeUsage: true
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
const provider = (modelId) => createLanguageModel(modelId);
|
|
103
|
+
provider.specificationVersion = "v2";
|
|
104
|
+
provider.languageModel = createLanguageModel;
|
|
105
|
+
provider.chat = createLanguageModel;
|
|
106
|
+
provider.textEmbeddingModel = (modelId) => {
|
|
107
|
+
throw new import_provider.NoSuchModelError({ modelId, modelType: "textEmbeddingModel" });
|
|
108
|
+
};
|
|
109
|
+
provider.imageModel = (modelId) => {
|
|
110
|
+
throw new import_provider.NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
111
|
+
};
|
|
112
|
+
return provider;
|
|
113
|
+
}
|
|
114
|
+
var gmicloud = createGmicloud();
|
|
115
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
116
|
+
0 && (module.exports = {
|
|
117
|
+
VERSION,
|
|
118
|
+
createGmicloud,
|
|
119
|
+
gmicloud
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/gmicloud-provider.ts","../src/gmicloud-chat-language-model.ts","../src/gmicloud-error.ts","../src/version.ts"],"sourcesContent":["export { createGmicloud, gmicloud } from './gmicloud-provider';\nexport type {\n GmicloudProvider,\n GmicloudProviderSettings,\n} from './gmicloud-provider';\nexport type { GmicloudErrorData } from './gmicloud-error';\nexport { VERSION } from './version';\n","import {\n NoSuchModelError,\n type LanguageModelV2,\n type ProviderV2,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { GmicloudChatLanguageModel } from './gmicloud-chat-language-model';\nimport type { GmicloudChatModelId } from './gmicloud-chat-options';\nimport { gmicloudErrorStructure } from './gmicloud-error';\nimport { VERSION } from './version';\n\nexport interface GmicloudProviderSettings {\n /**\n * GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment\n * variable (matching GMI's own SDK package).\n */\n apiKey?: string;\n /**\n * Base URL for the API calls. Defaults to\n * `https://api.gmi-serving.com/v1`.\n */\n baseURL?: string;\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface GmicloudProvider extends ProviderV2 {\n /**\n * Creates a GMI Cloud model for text generation.\n */\n (modelId: GmicloudChatModelId): LanguageModelV2;\n\n /**\n * Creates a GMI Cloud model for text generation.\n */\n languageModel(modelId: GmicloudChatModelId): LanguageModelV2;\n\n /**\n * Creates a GMI Cloud chat model for text generation.\n */\n chat(modelId: GmicloudChatModelId): LanguageModelV2;\n}\n\nexport function createGmicloud(\n options: GmicloudProviderSettings = {},\n): GmicloudProvider {\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? 'https://api.gmi-serving.com/v1',\n );\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'GMI_CLOUD_APIKEY',\n description: 'GMI Cloud API key',\n })}`,\n ...options.headers,\n },\n `ai-sdk/gmicloud/${VERSION}`,\n );\n\n const createLanguageModel = (modelId: GmicloudChatModelId) => {\n return new GmicloudChatLanguageModel(modelId, {\n provider: `gmicloud.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n errorStructure: gmicloudErrorStructure,\n includeUsage: true,\n });\n };\n\n const provider = (modelId: GmicloudChatModelId) =>\n createLanguageModel(modelId);\n\n provider.specificationVersion = 'v2' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.textEmbeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n\n return provider;\n}\n\nexport const gmicloud = createGmicloud();\n","import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';\n\n/**\n * GMI Cloud chat completions over the OpenAI-compatible protocol. The only\n * customization is the error structure (see ./gmicloud-error.ts): GMI's edge\n * nests the backend engine's diagnostic in `error.details`, which the default\n * OpenAI-compatible error handling drops.\n */\nexport class GmicloudChatLanguageModel extends OpenAICompatibleChatLanguageModel {}\n","import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';\nimport { z } from 'zod/v4';\n\nexport const gmicloudErrorDataSchema = z.object({\n error: z.object({\n message: z.string(),\n type: z.string().nullish(),\n param: z.any().nullish(),\n code: z.union([z.string(), z.number()]).nullish(),\n details: z.string().nullish(),\n }),\n});\n\nexport type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;\n\n// The parsed value is only read, never merged, so a guarded parse\n// (secureJsonParse) is not required here; the v5 provider-utils package does\n// not re-export it.\nfunction tryParseDetails(details: string): unknown {\n try {\n return JSON.parse(details);\n } catch {\n return undefined;\n }\n}\n\nfunction unwrapDetailsMessage(details: string | null | undefined) {\n if (details == null || details === '') {\n return undefined;\n }\n const message = (\n tryParseDetails(details) as { error?: { message?: unknown } } | undefined\n )?.error?.message;\n return typeof message === 'string' && message.trim() !== ''\n ? message\n : undefined;\n}\n\nexport const gmicloudErrorStructure: ProviderErrorStructure<GmicloudErrorData> =\n {\n errorSchema: gmicloudErrorDataSchema,\n errorToMessage: data =>\n unwrapDetailsMessage(data.error.details) ?? data.error.message,\n };\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sBAIO;AACP,4BAKO;;;ACVP,+BAAkD;AAQ3C,IAAM,4BAAN,cAAwC,2DAAkC;AAAC;;;ACPlF,gBAAkB;AAEX,IAAM,0BAA0B,YAAE,OAAO;AAAA,EAC9C,OAAO,YAAE,OAAO;AAAA,IACd,SAAS,YAAE,OAAO;AAAA,IAClB,MAAM,YAAE,OAAO,EAAE,QAAQ;AAAA,IACzB,OAAO,YAAE,IAAI,EAAE,QAAQ;AAAA,IACvB,MAAM,YAAE,MAAM,CAAC,YAAE,OAAO,GAAG,YAAE,OAAO,CAAC,CAAC,EAAE,QAAQ;AAAA,IAChD,SAAS,YAAE,OAAO,EAAE,QAAQ;AAAA,EAC9B,CAAC;AACH,CAAC;AAOD,SAAS,gBAAgB,SAA0B;AACjD,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,SAAoC;AA1BlE;AA2BE,MAAI,WAAW,QAAQ,YAAY,IAAI;AACrC,WAAO;AAAA,EACT;AACA,QAAM,WACJ,2BAAgB,OAAO,MAAvB,mBACC,UADD,mBACQ;AACV,SAAO,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,KACrD,UACA;AACN;AAEO,IAAM,yBACX;AAAA,EACE,aAAa;AAAA,EACb,gBAAgB,UAAK;AAzCzB;AA0CM,sCAAqB,KAAK,MAAM,OAAO,MAAvC,YAA4C,KAAK,MAAM;AAAA;AAC3D;;;ACzCK,IAAM,UACX,OACI,UACA;;;AHkDC,SAAS,eACd,UAAoC,CAAC,GACnB;AAzDpB;AA0DE,QAAM,cAAU;AAAA,KACd,aAAQ,YAAR,YAAmB;AAAA,EACrB;AACA,QAAM,aAAa,UACjB;AAAA,IACE;AAAA,MACE,eAAe,cAAU,kCAAW;AAAA,QAClC,QAAQ,QAAQ;AAAA,QAChB,yBAAyB;AAAA,QACzB,aAAa;AAAA,MACf,CAAC,CAAC;AAAA,MACF,GAAG,QAAQ;AAAA,IACb;AAAA,IACA,mBAAmB,OAAO;AAAA,EAC5B;AAEF,QAAM,sBAAsB,CAAC,YAAiC;AAC5D,WAAO,IAAI,0BAA0B,SAAS;AAAA,MAC5C,UAAU;AAAA,MACV,KAAK,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,GAAG,IAAI;AAAA,MACpC,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,MACf,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,CAAC,YAChB,oBAAoB,OAAO;AAE7B,WAAS,uBAAuB;AAChC,WAAS,gBAAgB;AACzB,WAAS,OAAO;AAEhB,WAAS,qBAAqB,CAAC,YAAoB;AACjD,UAAM,IAAI,iCAAiB,EAAE,SAAS,WAAW,qBAAqB,CAAC;AAAA,EACzE;AACA,WAAS,aAAa,CAAC,YAAoB;AACzC,UAAM,IAAI,iCAAiB,EAAE,SAAS,WAAW,aAAa,CAAC;AAAA,EACjE;AAEA,SAAO;AACT;AAEO,IAAM,WAAW,eAAe;","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/gmicloud-provider.ts
|
|
2
|
+
import {
|
|
3
|
+
NoSuchModelError
|
|
4
|
+
} from "@ai-sdk/provider";
|
|
5
|
+
import {
|
|
6
|
+
loadApiKey,
|
|
7
|
+
withoutTrailingSlash,
|
|
8
|
+
withUserAgentSuffix
|
|
9
|
+
} from "@ai-sdk/provider-utils";
|
|
10
|
+
|
|
11
|
+
// src/gmicloud-chat-language-model.ts
|
|
12
|
+
import { OpenAICompatibleChatLanguageModel } from "@ai-sdk/openai-compatible";
|
|
13
|
+
var GmicloudChatLanguageModel = class extends OpenAICompatibleChatLanguageModel {
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/gmicloud-error.ts
|
|
17
|
+
import { z } from "zod/v4";
|
|
18
|
+
var gmicloudErrorDataSchema = z.object({
|
|
19
|
+
error: z.object({
|
|
20
|
+
message: z.string(),
|
|
21
|
+
type: z.string().nullish(),
|
|
22
|
+
param: z.any().nullish(),
|
|
23
|
+
code: z.union([z.string(), z.number()]).nullish(),
|
|
24
|
+
details: z.string().nullish()
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
function tryParseDetails(details) {
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(details);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
return void 0;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function unwrapDetailsMessage(details) {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
if (details == null || details === "") {
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
39
|
+
const message = (_b = (_a = tryParseDetails(details)) == null ? void 0 : _a.error) == null ? void 0 : _b.message;
|
|
40
|
+
return typeof message === "string" && message.trim() !== "" ? message : void 0;
|
|
41
|
+
}
|
|
42
|
+
var gmicloudErrorStructure = {
|
|
43
|
+
errorSchema: gmicloudErrorDataSchema,
|
|
44
|
+
errorToMessage: (data) => {
|
|
45
|
+
var _a;
|
|
46
|
+
return (_a = unwrapDetailsMessage(data.error.details)) != null ? _a : data.error.message;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/version.ts
|
|
51
|
+
var VERSION = true ? "1.0.0" : "0.0.0-test";
|
|
52
|
+
|
|
53
|
+
// src/gmicloud-provider.ts
|
|
54
|
+
function createGmicloud(options = {}) {
|
|
55
|
+
var _a;
|
|
56
|
+
const baseURL = withoutTrailingSlash(
|
|
57
|
+
(_a = options.baseURL) != null ? _a : "https://api.gmi-serving.com/v1"
|
|
58
|
+
);
|
|
59
|
+
const getHeaders = () => withUserAgentSuffix(
|
|
60
|
+
{
|
|
61
|
+
Authorization: `Bearer ${loadApiKey({
|
|
62
|
+
apiKey: options.apiKey,
|
|
63
|
+
environmentVariableName: "GMI_CLOUD_APIKEY",
|
|
64
|
+
description: "GMI Cloud API key"
|
|
65
|
+
})}`,
|
|
66
|
+
...options.headers
|
|
67
|
+
},
|
|
68
|
+
`ai-sdk/gmicloud/${VERSION}`
|
|
69
|
+
);
|
|
70
|
+
const createLanguageModel = (modelId) => {
|
|
71
|
+
return new GmicloudChatLanguageModel(modelId, {
|
|
72
|
+
provider: `gmicloud.chat`,
|
|
73
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
74
|
+
headers: getHeaders,
|
|
75
|
+
fetch: options.fetch,
|
|
76
|
+
errorStructure: gmicloudErrorStructure,
|
|
77
|
+
includeUsage: true
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const provider = (modelId) => createLanguageModel(modelId);
|
|
81
|
+
provider.specificationVersion = "v2";
|
|
82
|
+
provider.languageModel = createLanguageModel;
|
|
83
|
+
provider.chat = createLanguageModel;
|
|
84
|
+
provider.textEmbeddingModel = (modelId) => {
|
|
85
|
+
throw new NoSuchModelError({ modelId, modelType: "textEmbeddingModel" });
|
|
86
|
+
};
|
|
87
|
+
provider.imageModel = (modelId) => {
|
|
88
|
+
throw new NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
89
|
+
};
|
|
90
|
+
return provider;
|
|
91
|
+
}
|
|
92
|
+
var gmicloud = createGmicloud();
|
|
93
|
+
export {
|
|
94
|
+
VERSION,
|
|
95
|
+
createGmicloud,
|
|
96
|
+
gmicloud
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gmicloud-provider.ts","../src/gmicloud-chat-language-model.ts","../src/gmicloud-error.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type LanguageModelV2,\n type ProviderV2,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { GmicloudChatLanguageModel } from './gmicloud-chat-language-model';\nimport type { GmicloudChatModelId } from './gmicloud-chat-options';\nimport { gmicloudErrorStructure } from './gmicloud-error';\nimport { VERSION } from './version';\n\nexport interface GmicloudProviderSettings {\n /**\n * GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment\n * variable (matching GMI's own SDK package).\n */\n apiKey?: string;\n /**\n * Base URL for the API calls. Defaults to\n * `https://api.gmi-serving.com/v1`.\n */\n baseURL?: string;\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface GmicloudProvider extends ProviderV2 {\n /**\n * Creates a GMI Cloud model for text generation.\n */\n (modelId: GmicloudChatModelId): LanguageModelV2;\n\n /**\n * Creates a GMI Cloud model for text generation.\n */\n languageModel(modelId: GmicloudChatModelId): LanguageModelV2;\n\n /**\n * Creates a GMI Cloud chat model for text generation.\n */\n chat(modelId: GmicloudChatModelId): LanguageModelV2;\n}\n\nexport function createGmicloud(\n options: GmicloudProviderSettings = {},\n): GmicloudProvider {\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? 'https://api.gmi-serving.com/v1',\n );\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'GMI_CLOUD_APIKEY',\n description: 'GMI Cloud API key',\n })}`,\n ...options.headers,\n },\n `ai-sdk/gmicloud/${VERSION}`,\n );\n\n const createLanguageModel = (modelId: GmicloudChatModelId) => {\n return new GmicloudChatLanguageModel(modelId, {\n provider: `gmicloud.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n errorStructure: gmicloudErrorStructure,\n includeUsage: true,\n });\n };\n\n const provider = (modelId: GmicloudChatModelId) =>\n createLanguageModel(modelId);\n\n provider.specificationVersion = 'v2' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.textEmbeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n\n return provider;\n}\n\nexport const gmicloud = createGmicloud();\n","import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';\n\n/**\n * GMI Cloud chat completions over the OpenAI-compatible protocol. The only\n * customization is the error structure (see ./gmicloud-error.ts): GMI's edge\n * nests the backend engine's diagnostic in `error.details`, which the default\n * OpenAI-compatible error handling drops.\n */\nexport class GmicloudChatLanguageModel extends OpenAICompatibleChatLanguageModel {}\n","import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';\nimport { z } from 'zod/v4';\n\nexport const gmicloudErrorDataSchema = z.object({\n error: z.object({\n message: z.string(),\n type: z.string().nullish(),\n param: z.any().nullish(),\n code: z.union([z.string(), z.number()]).nullish(),\n details: z.string().nullish(),\n }),\n});\n\nexport type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;\n\n// The parsed value is only read, never merged, so a guarded parse\n// (secureJsonParse) is not required here; the v5 provider-utils package does\n// not re-export it.\nfunction tryParseDetails(details: string): unknown {\n try {\n return JSON.parse(details);\n } catch {\n return undefined;\n }\n}\n\nfunction unwrapDetailsMessage(details: string | null | undefined) {\n if (details == null || details === '') {\n return undefined;\n }\n const message = (\n tryParseDetails(details) as { error?: { message?: unknown } } | undefined\n )?.error?.message;\n return typeof message === 'string' && message.trim() !== ''\n ? message\n : undefined;\n}\n\nexport const gmicloudErrorStructure: ProviderErrorStructure<GmicloudErrorData> =\n {\n errorSchema: gmicloudErrorDataSchema,\n errorToMessage: data =>\n unwrapDetailsMessage(data.error.details) ?? data.error.message,\n };\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":";AAAA;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;;;ACVP,SAAS,yCAAyC;AAQ3C,IAAM,4BAAN,cAAwC,kCAAkC;AAAC;;;ACPlF,SAAS,SAAS;AAEX,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,OAAO,EAAE,OAAO;AAAA,IACd,SAAS,EAAE,OAAO;AAAA,IAClB,MAAM,EAAE,OAAO,EAAE,QAAQ;AAAA,IACzB,OAAO,EAAE,IAAI,EAAE,QAAQ;AAAA,IACvB,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQ;AAAA,IAChD,SAAS,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC9B,CAAC;AACH,CAAC;AAOD,SAAS,gBAAgB,SAA0B;AACjD,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,SAAoC;AA1BlE;AA2BE,MAAI,WAAW,QAAQ,YAAY,IAAI;AACrC,WAAO;AAAA,EACT;AACA,QAAM,WACJ,2BAAgB,OAAO,MAAvB,mBACC,UADD,mBACQ;AACV,SAAO,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,KACrD,UACA;AACN;AAEO,IAAM,yBACX;AAAA,EACE,aAAa;AAAA,EACb,gBAAgB,UAAK;AAzCzB;AA0CM,sCAAqB,KAAK,MAAM,OAAO,MAAvC,YAA4C,KAAK,MAAM;AAAA;AAC3D;;;ACzCK,IAAM,UACX,OACI,UACA;;;AHkDC,SAAS,eACd,UAAoC,CAAC,GACnB;AAzDpB;AA0DE,QAAM,UAAU;AAAA,KACd,aAAQ,YAAR,YAAmB;AAAA,EACrB;AACA,QAAM,aAAa,MACjB;AAAA,IACE;AAAA,MACE,eAAe,UAAU,WAAW;AAAA,QAClC,QAAQ,QAAQ;AAAA,QAChB,yBAAyB;AAAA,QACzB,aAAa;AAAA,MACf,CAAC,CAAC;AAAA,MACF,GAAG,QAAQ;AAAA,IACb;AAAA,IACA,mBAAmB,OAAO;AAAA,EAC5B;AAEF,QAAM,sBAAsB,CAAC,YAAiC;AAC5D,WAAO,IAAI,0BAA0B,SAAS;AAAA,MAC5C,UAAU;AAAA,MACV,KAAK,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,GAAG,IAAI;AAAA,MACpC,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,MACf,gBAAgB;AAAA,MAChB,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,CAAC,YAChB,oBAAoB,OAAO;AAE7B,WAAS,uBAAuB;AAChC,WAAS,gBAAgB;AACzB,WAAS,OAAO;AAEhB,WAAS,qBAAqB,CAAC,YAAoB;AACjD,UAAM,IAAI,iBAAiB,EAAE,SAAS,WAAW,qBAAqB,CAAC;AAAA,EACzE;AACA,WAAS,aAAa,CAAC,YAAoB;AACzC,UAAM,IAAI,iBAAiB,EAAE,SAAS,WAAW,aAAa,CAAC;AAAA,EACjE;AAEA,SAAO;AACT;AAEO,IAAM,WAAW,eAAe;","names":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GMI Cloud
|
|
3
|
+
description: Learn how to use GMI Cloud's models with the AI SDK.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GMI Cloud Provider
|
|
7
|
+
|
|
8
|
+
The [GMI Cloud](https://www.gmicloud.ai) provider offers access to open-weight language models through GMI Cloud's GPU inference platform, over an OpenAI-compatible API.
|
|
9
|
+
|
|
10
|
+
API keys can be obtained from the [GMI Cloud console](https://console.gmicloud.ai).
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
The GMI Cloud provider is available via the `@ai-sdk/gmicloud` module. You can install it with:
|
|
15
|
+
|
|
16
|
+
<InstallPackages packages="@ai-sdk/gmicloud" />
|
|
17
|
+
|
|
18
|
+
## Provider Instance
|
|
19
|
+
|
|
20
|
+
You can import the default provider instance `gmicloud` from `@ai-sdk/gmicloud`:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For custom configuration, you can import `createGmicloud` and create a provider instance with your settings:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { createGmicloud } from '@ai-sdk/gmicloud';
|
|
30
|
+
|
|
31
|
+
const gmicloud = createGmicloud({
|
|
32
|
+
apiKey: process.env.GMI_CLOUD_APIKEY ?? '',
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You can use the following optional settings to customize the GMI Cloud provider instance:
|
|
37
|
+
|
|
38
|
+
- **baseURL** _string_
|
|
39
|
+
|
|
40
|
+
Use a different URL prefix for API calls.
|
|
41
|
+
The default prefix is `https://api.gmi-serving.com/v1`.
|
|
42
|
+
|
|
43
|
+
- **apiKey** _string_
|
|
44
|
+
|
|
45
|
+
API key that is being sent using the `Authorization` header. It defaults to
|
|
46
|
+
the `GMI_CLOUD_APIKEY` environment variable.
|
|
47
|
+
|
|
48
|
+
- **headers** _Record<string,string>_
|
|
49
|
+
|
|
50
|
+
Custom headers to include in the requests.
|
|
51
|
+
|
|
52
|
+
- **fetch** _FetchFunction_
|
|
53
|
+
|
|
54
|
+
Custom fetch implementation.
|
|
55
|
+
|
|
56
|
+
## Language Models
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { gmicloud } from '@ai-sdk/gmicloud';
|
|
60
|
+
import { generateText } from 'ai';
|
|
61
|
+
|
|
62
|
+
const { text } = await generateText({
|
|
63
|
+
model: gmicloud('deepseek-ai/DeepSeek-V4-Flash-0731'),
|
|
64
|
+
prompt: 'What is the capital of France?',
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
GMI Cloud serves an evolving catalog of open-weight models, so model ids are typed as `string`. Embedding and image models are not supported.
|
|
69
|
+
|
|
70
|
+
## Error diagnostics
|
|
71
|
+
|
|
72
|
+
GMI Cloud's edge reports a generic banner in `error.message` on rejections and nests the backend engine's diagnostic in `error.details`. This provider unwraps the nested diagnostic, so `AI_APICallError.message` carries the engine's reason (e.g. `The request is invalid: Invalid max_tokens value, the valid range of max_tokens is [1, 393216].`) instead of `Backend request failed with status 400`.
|
package/package.json
CHANGED
|
@@ -1,18 +1,78 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/gmicloud",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"
|
|
7
|
-
"main": "./index.js",
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
},
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
11
10
|
"files": [
|
|
12
|
-
"
|
|
11
|
+
"dist/**/*",
|
|
12
|
+
"docs/**/*",
|
|
13
|
+
"src",
|
|
14
|
+
"!src/**/*.test.ts",
|
|
15
|
+
"!src/**/*.test-d.ts",
|
|
16
|
+
"!src/**/__snapshots__",
|
|
17
|
+
"!src/**/__fixtures__",
|
|
18
|
+
"CHANGELOG.md",
|
|
13
19
|
"README.md"
|
|
14
20
|
],
|
|
21
|
+
"directories": {
|
|
22
|
+
"doc": "./docs"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
"./package.json": "./package.json",
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.mjs",
|
|
29
|
+
"require": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@ai-sdk/openai-compatible": "1.0.48",
|
|
34
|
+
"@ai-sdk/provider": "2.0.3",
|
|
35
|
+
"@ai-sdk/provider-utils": "3.0.32"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "20.17.24",
|
|
39
|
+
"tsup": "^8",
|
|
40
|
+
"typescript": "5.8.3",
|
|
41
|
+
"zod": "3.25.76",
|
|
42
|
+
"@vercel/ai-tsconfig": "0.0.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"zod": "^3.25.76 || ^4.1.8"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
},
|
|
15
50
|
"publishConfig": {
|
|
16
|
-
"access": "public"
|
|
51
|
+
"access": "public",
|
|
52
|
+
"provenance": true
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://ai-sdk.dev/docs",
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "https://github.com/vercel/ai",
|
|
58
|
+
"directory": "packages/gmicloud"
|
|
59
|
+
},
|
|
60
|
+
"bugs": {
|
|
61
|
+
"url": "https://github.com/vercel/ai/issues"
|
|
62
|
+
},
|
|
63
|
+
"keywords": [
|
|
64
|
+
"ai"
|
|
65
|
+
],
|
|
66
|
+
"description": "The **GMI Cloud provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for [GMI Cloud](https://www.gmicloud.ai), offering GPU inference for open-weight models over an OpenAI-compatible API.",
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
|
|
69
|
+
"build:watch": "pnpm clean && tsup --watch",
|
|
70
|
+
"clean": "del-cli dist docs *.tsbuildinfo",
|
|
71
|
+
"type-check": "tsc --build",
|
|
72
|
+
"test": "pnpm test:node && pnpm test:edge",
|
|
73
|
+
"test:update": "pnpm test:node -u",
|
|
74
|
+
"test:watch": "vitest --config vitest.node.config.js",
|
|
75
|
+
"test:edge": "vitest --config vitest.edge.config.js --run",
|
|
76
|
+
"test:node": "vitest --config vitest.node.config.js --run"
|
|
17
77
|
}
|
|
18
|
-
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OpenAICompatibleChatLanguageModel } from '@ai-sdk/openai-compatible';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GMI Cloud chat completions over the OpenAI-compatible protocol. The only
|
|
5
|
+
* customization is the error structure (see ./gmicloud-error.ts): GMI's edge
|
|
6
|
+
* nests the backend engine's diagnostic in `error.details`, which the default
|
|
7
|
+
* OpenAI-compatible error handling drops.
|
|
8
|
+
*/
|
|
9
|
+
export class GmicloudChatLanguageModel extends OpenAICompatibleChatLanguageModel {}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ProviderErrorStructure } from '@ai-sdk/openai-compatible';
|
|
2
|
+
import { z } from 'zod/v4';
|
|
3
|
+
|
|
4
|
+
export const gmicloudErrorDataSchema = z.object({
|
|
5
|
+
error: z.object({
|
|
6
|
+
message: z.string(),
|
|
7
|
+
type: z.string().nullish(),
|
|
8
|
+
param: z.any().nullish(),
|
|
9
|
+
code: z.union([z.string(), z.number()]).nullish(),
|
|
10
|
+
details: z.string().nullish(),
|
|
11
|
+
}),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export type GmicloudErrorData = z.infer<typeof gmicloudErrorDataSchema>;
|
|
15
|
+
|
|
16
|
+
// The parsed value is only read, never merged, so a guarded parse
|
|
17
|
+
// (secureJsonParse) is not required here; the v5 provider-utils package does
|
|
18
|
+
// not re-export it.
|
|
19
|
+
function tryParseDetails(details: string): unknown {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(details);
|
|
22
|
+
} catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function unwrapDetailsMessage(details: string | null | undefined) {
|
|
28
|
+
if (details == null || details === '') {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const message = (
|
|
32
|
+
tryParseDetails(details) as { error?: { message?: unknown } } | undefined
|
|
33
|
+
)?.error?.message;
|
|
34
|
+
return typeof message === 'string' && message.trim() !== ''
|
|
35
|
+
? message
|
|
36
|
+
: undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const gmicloudErrorStructure: ProviderErrorStructure<GmicloudErrorData> =
|
|
40
|
+
{
|
|
41
|
+
errorSchema: gmicloudErrorDataSchema,
|
|
42
|
+
errorToMessage: data =>
|
|
43
|
+
unwrapDetailsMessage(data.error.details) ?? data.error.message,
|
|
44
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NoSuchModelError,
|
|
3
|
+
type LanguageModelV2,
|
|
4
|
+
type ProviderV2,
|
|
5
|
+
} from '@ai-sdk/provider';
|
|
6
|
+
import {
|
|
7
|
+
loadApiKey,
|
|
8
|
+
withoutTrailingSlash,
|
|
9
|
+
withUserAgentSuffix,
|
|
10
|
+
type FetchFunction,
|
|
11
|
+
} from '@ai-sdk/provider-utils';
|
|
12
|
+
import { GmicloudChatLanguageModel } from './gmicloud-chat-language-model';
|
|
13
|
+
import type { GmicloudChatModelId } from './gmicloud-chat-options';
|
|
14
|
+
import { gmicloudErrorStructure } from './gmicloud-error';
|
|
15
|
+
import { VERSION } from './version';
|
|
16
|
+
|
|
17
|
+
export interface GmicloudProviderSettings {
|
|
18
|
+
/**
|
|
19
|
+
* GMI Cloud API key. Defaults to the `GMI_CLOUD_APIKEY` environment
|
|
20
|
+
* variable (matching GMI's own SDK package).
|
|
21
|
+
*/
|
|
22
|
+
apiKey?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Base URL for the API calls. Defaults to
|
|
25
|
+
* `https://api.gmi-serving.com/v1`.
|
|
26
|
+
*/
|
|
27
|
+
baseURL?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Custom headers to include in the requests.
|
|
30
|
+
*/
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Custom fetch implementation. You can use it as a middleware to intercept
|
|
34
|
+
* requests, or to provide a custom fetch implementation for e.g. testing.
|
|
35
|
+
*/
|
|
36
|
+
fetch?: FetchFunction;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface GmicloudProvider extends ProviderV2 {
|
|
40
|
+
/**
|
|
41
|
+
* Creates a GMI Cloud model for text generation.
|
|
42
|
+
*/
|
|
43
|
+
(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a GMI Cloud model for text generation.
|
|
47
|
+
*/
|
|
48
|
+
languageModel(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Creates a GMI Cloud chat model for text generation.
|
|
52
|
+
*/
|
|
53
|
+
chat(modelId: GmicloudChatModelId): LanguageModelV2;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createGmicloud(
|
|
57
|
+
options: GmicloudProviderSettings = {},
|
|
58
|
+
): GmicloudProvider {
|
|
59
|
+
const baseURL = withoutTrailingSlash(
|
|
60
|
+
options.baseURL ?? 'https://api.gmi-serving.com/v1',
|
|
61
|
+
);
|
|
62
|
+
const getHeaders = () =>
|
|
63
|
+
withUserAgentSuffix(
|
|
64
|
+
{
|
|
65
|
+
Authorization: `Bearer ${loadApiKey({
|
|
66
|
+
apiKey: options.apiKey,
|
|
67
|
+
environmentVariableName: 'GMI_CLOUD_APIKEY',
|
|
68
|
+
description: 'GMI Cloud API key',
|
|
69
|
+
})}`,
|
|
70
|
+
...options.headers,
|
|
71
|
+
},
|
|
72
|
+
`ai-sdk/gmicloud/${VERSION}`,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const createLanguageModel = (modelId: GmicloudChatModelId) => {
|
|
76
|
+
return new GmicloudChatLanguageModel(modelId, {
|
|
77
|
+
provider: `gmicloud.chat`,
|
|
78
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
79
|
+
headers: getHeaders,
|
|
80
|
+
fetch: options.fetch,
|
|
81
|
+
errorStructure: gmicloudErrorStructure,
|
|
82
|
+
includeUsage: true,
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const provider = (modelId: GmicloudChatModelId) =>
|
|
87
|
+
createLanguageModel(modelId);
|
|
88
|
+
|
|
89
|
+
provider.specificationVersion = 'v2' as const;
|
|
90
|
+
provider.languageModel = createLanguageModel;
|
|
91
|
+
provider.chat = createLanguageModel;
|
|
92
|
+
|
|
93
|
+
provider.textEmbeddingModel = (modelId: string) => {
|
|
94
|
+
throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });
|
|
95
|
+
};
|
|
96
|
+
provider.imageModel = (modelId: string) => {
|
|
97
|
+
throw new NoSuchModelError({ modelId, modelType: 'imageModel' });
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return provider;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export const gmicloud = createGmicloud();
|
package/src/index.ts
ADDED
package/src/version.ts
ADDED
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|