@node-llm/core 1.12.0 → 1.13.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 +1 -1
- package/dist/aliases.d.ts +119 -63
- package/dist/aliases.d.ts.map +1 -1
- package/dist/aliases.js +177 -121
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/llm.d.ts.map +1 -1
- package/dist/llm.js +3 -2
- package/dist/models/models.json +1362 -416
- package/dist/providers/registry.d.ts +2 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +2 -1
- package/dist/providers/xai/Capabilities.d.ts +12 -0
- package/dist/providers/xai/Capabilities.d.ts.map +1 -0
- package/dist/providers/xai/Capabilities.js +79 -0
- package/dist/providers/xai/Chat.d.ts +8 -0
- package/dist/providers/xai/Chat.d.ts.map +1 -0
- package/dist/providers/xai/Chat.js +69 -0
- package/dist/providers/xai/Errors.d.ts +2 -0
- package/dist/providers/xai/Errors.d.ts.map +1 -0
- package/dist/providers/xai/Errors.js +33 -0
- package/dist/providers/xai/Image.d.ts +8 -0
- package/dist/providers/xai/Image.d.ts.map +1 -0
- package/dist/providers/xai/Image.js +47 -0
- package/dist/providers/xai/Models.d.ts +8 -0
- package/dist/providers/xai/Models.d.ts.map +1 -0
- package/dist/providers/xai/Models.js +47 -0
- package/dist/providers/xai/Streaming.d.ts +8 -0
- package/dist/providers/xai/Streaming.d.ts.map +1 -0
- package/dist/providers/xai/Streaming.js +167 -0
- package/dist/providers/xai/XAIProvider.d.ts +37 -0
- package/dist/providers/xai/XAIProvider.d.ts.map +1 -0
- package/dist/providers/xai/XAIProvider.js +66 -0
- package/dist/providers/xai/index.d.ts +7 -0
- package/dist/providers/xai/index.d.ts.map +1 -0
- package/dist/providers/xai/index.js +19 -0
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { registerDeepSeekProvider } from "./deepseek/index.js";
|
|
|
6
6
|
import { registerOllamaProvider } from "./ollama/index.js";
|
|
7
7
|
import { registerOpenRouterProvider } from "./openrouter/index.js";
|
|
8
8
|
import { registerBedrockProvider } from "./bedrock/index.js";
|
|
9
|
+
import { registerXAIProvider } from "./xai/index.js";
|
|
9
10
|
import { NodeLLMConfig } from "../config.js";
|
|
10
11
|
type ProviderFactory = (config?: NodeLLMConfig) => Provider;
|
|
11
12
|
export type ProviderInterceptor = (provider: Provider) => Provider;
|
|
@@ -46,5 +47,5 @@ declare class ProviderRegistry {
|
|
|
46
47
|
* ```
|
|
47
48
|
*/
|
|
48
49
|
export declare const providerRegistry: ProviderRegistry;
|
|
49
|
-
export { registerOpenAIProvider as ensureOpenAIRegistered, registerOpenAIProvider, registerAnthropicProvider, registerGeminiProvider, registerDeepSeekProvider, registerOllamaProvider, registerOpenRouterProvider, registerBedrockProvider };
|
|
50
|
+
export { registerOpenAIProvider as ensureOpenAIRegistered, registerOpenAIProvider, registerAnthropicProvider, registerGeminiProvider, registerDeepSeekProvider, registerOllamaProvider, registerOpenRouterProvider, registerBedrockProvider, registerXAIProvider };
|
|
50
51
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,KAAK,eAAe,GAAG,CAAC,MAAM,CAAC,EAAE,aAAa,KAAK,QAAQ,CAAC;AAC5D,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC;AAEnE,cAAM,gBAAgB;IACpB,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAEzC,cAAc,CAAC,WAAW,EAAE,mBAAmB,GAAG,SAAS;IAIlE;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe;IAO/C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,QAAQ;IAgBvD;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACH,IAAI,IAAI,MAAM,EAAE;CAGjB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,kBAAyB,CAAC;AAGvD,OAAO,EACL,sBAAsB,IAAI,sBAAsB,EAChD,sBAAsB,EACtB,yBAAyB,EACzB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,mBAAmB,EACpB,CAAC"}
|
|
@@ -5,6 +5,7 @@ import { registerDeepSeekProvider } from "./deepseek/index.js";
|
|
|
5
5
|
import { registerOllamaProvider } from "./ollama/index.js";
|
|
6
6
|
import { registerOpenRouterProvider } from "./openrouter/index.js";
|
|
7
7
|
import { registerBedrockProvider } from "./bedrock/index.js";
|
|
8
|
+
import { registerXAIProvider } from "./xai/index.js";
|
|
8
9
|
class ProviderRegistry {
|
|
9
10
|
providers = new Map();
|
|
10
11
|
globalInterceptor;
|
|
@@ -64,4 +65,4 @@ class ProviderRegistry {
|
|
|
64
65
|
*/
|
|
65
66
|
export const providerRegistry = new ProviderRegistry();
|
|
66
67
|
// Exported registration functions (delegates to provider-specific index files)
|
|
67
|
-
export { registerOpenAIProvider as ensureOpenAIRegistered, registerOpenAIProvider, registerAnthropicProvider, registerGeminiProvider, registerDeepSeekProvider, registerOllamaProvider, registerOpenRouterProvider, registerBedrockProvider };
|
|
68
|
+
export { registerOpenAIProvider as ensureOpenAIRegistered, registerOpenAIProvider, registerAnthropicProvider, registerGeminiProvider, registerDeepSeekProvider, registerOllamaProvider, registerOpenRouterProvider, registerBedrockProvider, registerXAIProvider };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class Capabilities {
|
|
2
|
+
static supportsVision(model: string): boolean;
|
|
3
|
+
static supportsTools(model: string): boolean;
|
|
4
|
+
static supportsStructuredOutput(model: string): boolean;
|
|
5
|
+
static supportsEmbeddings(model: string): boolean;
|
|
6
|
+
static supportsImageGeneration(model: string): boolean;
|
|
7
|
+
static supportsTranscription(model: string): boolean;
|
|
8
|
+
static supportsModeration(model: string): boolean;
|
|
9
|
+
static supportsReasoning(model: string): boolean;
|
|
10
|
+
static getContextWindow(model: string): number;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=Capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/Capabilities.ts"],"names":[],"mappings":"AAsBA,qBAAa,YAAY;IACvB,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAO7C,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAS5C,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IASvD,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOjD,MAAM,CAAC,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOtD,MAAM,CAAC,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOpD,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOjD,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOhD,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAM/C"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ModelRegistry } from "../../models/ModelRegistry.js";
|
|
2
|
+
const VISION_MODELS = [
|
|
3
|
+
"grok-2-vision-1212",
|
|
4
|
+
"grok-4-0709",
|
|
5
|
+
"grok-4-fast-non-reasoning",
|
|
6
|
+
"grok-4-fast-reasoning",
|
|
7
|
+
"grok-4.1-fast-non-reasoning",
|
|
8
|
+
"grok-4.1-fast-reasoning",
|
|
9
|
+
"grok-4-1-fast-non-reasoning",
|
|
10
|
+
"grok-4-1-fast-reasoning"
|
|
11
|
+
];
|
|
12
|
+
const REASONING_MODELS = [
|
|
13
|
+
"grok-3-mini",
|
|
14
|
+
"grok-4-0709",
|
|
15
|
+
"grok-4-fast-reasoning",
|
|
16
|
+
"grok-4.1-fast-reasoning",
|
|
17
|
+
"grok-4-1-fast-reasoning",
|
|
18
|
+
"grok-code-fast-1"
|
|
19
|
+
];
|
|
20
|
+
export class Capabilities {
|
|
21
|
+
static supportsVision(model) {
|
|
22
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
23
|
+
if (registryModel?.capabilities.includes("vision"))
|
|
24
|
+
return true;
|
|
25
|
+
return model.includes("vision") || VISION_MODELS.includes(model);
|
|
26
|
+
}
|
|
27
|
+
static supportsTools(model) {
|
|
28
|
+
if (this.supportsImageGeneration(model))
|
|
29
|
+
return false;
|
|
30
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
31
|
+
if (registryModel?.capabilities.includes("tools"))
|
|
32
|
+
return true;
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
static supportsStructuredOutput(model) {
|
|
36
|
+
if (this.supportsImageGeneration(model))
|
|
37
|
+
return false;
|
|
38
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
39
|
+
if (registryModel?.capabilities.includes("structured_output"))
|
|
40
|
+
return true;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
static supportsEmbeddings(model) {
|
|
44
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
45
|
+
if (registryModel?.capabilities.includes("embeddings"))
|
|
46
|
+
return true;
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
static supportsImageGeneration(model) {
|
|
50
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
51
|
+
if (registryModel?.capabilities.includes("image_generation"))
|
|
52
|
+
return true;
|
|
53
|
+
return model.includes("image") || model.includes("imagine");
|
|
54
|
+
}
|
|
55
|
+
static supportsTranscription(model) {
|
|
56
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
57
|
+
if (registryModel?.capabilities.includes("transcription"))
|
|
58
|
+
return true;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
static supportsModeration(model) {
|
|
62
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
63
|
+
if (registryModel?.capabilities.includes("moderation"))
|
|
64
|
+
return true;
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
static supportsReasoning(model) {
|
|
68
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
69
|
+
if (registryModel?.capabilities.includes("reasoning"))
|
|
70
|
+
return true;
|
|
71
|
+
return model.includes("reasoning") || REASONING_MODELS.includes(model);
|
|
72
|
+
}
|
|
73
|
+
static getContextWindow(model) {
|
|
74
|
+
const registryModel = ModelRegistry.find(model, "xai");
|
|
75
|
+
if (registryModel?.context_window)
|
|
76
|
+
return registryModel.context_window;
|
|
77
|
+
return 128000;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChatRequest, ChatResponse } from "../Provider.js";
|
|
2
|
+
export declare class XAIChat {
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
private readonly apiKey;
|
|
5
|
+
constructor(baseUrl: string, apiKey: string);
|
|
6
|
+
execute(request: ChatRequest): Promise<ChatResponse>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=Chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/Chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAS,MAAM,gBAAgB,CAAC;AAiClE,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAgF3D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ModelRegistry } from "../../models/ModelRegistry.js";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
import { handleXAIError } from "./Errors.js";
|
|
4
|
+
import { mapSystemMessages } from "../utils.js";
|
|
5
|
+
import { fetchWithTimeout } from "../../utils/fetch.js";
|
|
6
|
+
export class XAIChat {
|
|
7
|
+
baseUrl;
|
|
8
|
+
apiKey;
|
|
9
|
+
constructor(baseUrl, apiKey) {
|
|
10
|
+
this.baseUrl = baseUrl;
|
|
11
|
+
this.apiKey = apiKey;
|
|
12
|
+
}
|
|
13
|
+
async execute(request) {
|
|
14
|
+
const { model, messages, tools, max_tokens, response_format, thinking: _thinking, headers: _headers, requestTimeout, ...rest } = request;
|
|
15
|
+
const mappedMessages = mapSystemMessages(messages, false);
|
|
16
|
+
const body = {
|
|
17
|
+
model,
|
|
18
|
+
messages: mappedMessages,
|
|
19
|
+
...rest
|
|
20
|
+
};
|
|
21
|
+
if (max_tokens)
|
|
22
|
+
body.max_tokens = max_tokens;
|
|
23
|
+
if (tools && tools.length > 0)
|
|
24
|
+
body.tools = tools;
|
|
25
|
+
if (response_format)
|
|
26
|
+
body.response_format = response_format;
|
|
27
|
+
const url = `${this.baseUrl}/chat/completions`;
|
|
28
|
+
logger.logRequest("xAI", "POST", url, body);
|
|
29
|
+
const response = await fetchWithTimeout(url, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: {
|
|
32
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
33
|
+
"Content-Type": "application/json",
|
|
34
|
+
...request.headers
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify(body)
|
|
37
|
+
}, requestTimeout);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
await handleXAIError(response, model);
|
|
40
|
+
}
|
|
41
|
+
const json = (await response.json());
|
|
42
|
+
logger.logResponse("xAI", response.status, response.statusText, json);
|
|
43
|
+
const message = json.choices[0]?.message;
|
|
44
|
+
const content = message?.content ?? null;
|
|
45
|
+
const usage = {
|
|
46
|
+
input_tokens: json.usage.prompt_tokens,
|
|
47
|
+
output_tokens: json.usage.completion_tokens,
|
|
48
|
+
total_tokens: json.usage.total_tokens
|
|
49
|
+
};
|
|
50
|
+
const toolCalls = message?.tool_calls?.map((tc) => ({
|
|
51
|
+
id: tc.id,
|
|
52
|
+
type: "function",
|
|
53
|
+
function: {
|
|
54
|
+
name: tc.function.name,
|
|
55
|
+
arguments: tc.function.arguments
|
|
56
|
+
}
|
|
57
|
+
}));
|
|
58
|
+
if (!content && (!toolCalls || toolCalls.length === 0)) {
|
|
59
|
+
throw new Error("xAI returned empty response");
|
|
60
|
+
}
|
|
61
|
+
// Cost calculation if registered in ModelRegistry
|
|
62
|
+
const calculatedUsage = ModelRegistry.calculateCost(usage, model, "xai");
|
|
63
|
+
return {
|
|
64
|
+
content,
|
|
65
|
+
usage: calculatedUsage,
|
|
66
|
+
tool_calls: toolCalls
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/Errors.ts"],"names":[],"mappings":"AASA,wBAAsB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAiCvF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { APIError, AuthenticationError, BadRequestError, RateLimitError, ServerError, NotFoundError } from "../../errors/index.js";
|
|
2
|
+
export async function handleXAIError(response, model) {
|
|
3
|
+
const status = response.status;
|
|
4
|
+
let errorMessage = `xAI API identification failed with status ${status}`;
|
|
5
|
+
let errorData = {};
|
|
6
|
+
try {
|
|
7
|
+
const text = await response.text();
|
|
8
|
+
console.error("XAI ERROR RESPONSE:", text);
|
|
9
|
+
errorData = JSON.parse(text);
|
|
10
|
+
errorMessage = errorData.error?.message || errorMessage;
|
|
11
|
+
}
|
|
12
|
+
catch (_e) {
|
|
13
|
+
// Ignore JSON parsing errors
|
|
14
|
+
}
|
|
15
|
+
const provider = "xai";
|
|
16
|
+
switch (status) {
|
|
17
|
+
case 401:
|
|
18
|
+
throw new AuthenticationError(errorMessage, status, errorData, provider);
|
|
19
|
+
case 400:
|
|
20
|
+
throw new BadRequestError(errorMessage, errorData, provider, model);
|
|
21
|
+
case 404:
|
|
22
|
+
throw new NotFoundError(errorMessage, status, errorData, provider, model);
|
|
23
|
+
case 429:
|
|
24
|
+
throw new RateLimitError(errorMessage, errorData, provider, model);
|
|
25
|
+
case 500:
|
|
26
|
+
case 502:
|
|
27
|
+
case 503:
|
|
28
|
+
case 504:
|
|
29
|
+
throw new ServerError(errorMessage, status, errorData, provider, model);
|
|
30
|
+
default:
|
|
31
|
+
throw new APIError(errorMessage, status, errorData, provider, model);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ImageRequest, ImageResponse } from "../Provider.js";
|
|
2
|
+
export declare class XAIImage {
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
private readonly apiKey;
|
|
5
|
+
constructor(baseUrl: string, apiKey: string);
|
|
6
|
+
execute(request: ImageRequest): Promise<ImageResponse>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=Image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/Image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAY7D,qBAAa,QAAQ;IAEjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;CA6C7D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { handleXAIError } from "./Errors.js";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
import { fetchWithTimeout } from "../../utils/fetch.js";
|
|
4
|
+
export class XAIImage {
|
|
5
|
+
baseUrl;
|
|
6
|
+
apiKey;
|
|
7
|
+
constructor(baseUrl, apiKey) {
|
|
8
|
+
this.baseUrl = baseUrl;
|
|
9
|
+
this.apiKey = apiKey;
|
|
10
|
+
}
|
|
11
|
+
async execute(request) {
|
|
12
|
+
const body = {
|
|
13
|
+
model: request.model || "grok-imagine-image",
|
|
14
|
+
prompt: request.prompt
|
|
15
|
+
};
|
|
16
|
+
if (request.size)
|
|
17
|
+
body.size = request.size;
|
|
18
|
+
if (request.n)
|
|
19
|
+
body.n = request.n;
|
|
20
|
+
if (request.quality)
|
|
21
|
+
body.quality = request.quality;
|
|
22
|
+
const url = `${this.baseUrl}/images/generations`;
|
|
23
|
+
logger.logRequest("xAI", "POST", url, body);
|
|
24
|
+
const response = await fetchWithTimeout(url, {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: {
|
|
27
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
28
|
+
"Content-Type": "application/json"
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify(body)
|
|
31
|
+
}, request.requestTimeout);
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
await handleXAIError(response, request.model);
|
|
34
|
+
}
|
|
35
|
+
const json = (await response.json());
|
|
36
|
+
logger.logResponse("xAI", response.status, response.statusText, json);
|
|
37
|
+
const data = json.data?.[0];
|
|
38
|
+
if (!data) {
|
|
39
|
+
throw new Error("xAI returned empty image response");
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
url: data.url,
|
|
43
|
+
revised_prompt: data.revised_prompt,
|
|
44
|
+
mime_type: "image/png"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAa3C,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CAoCtC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { fetchWithTimeout } from "../../utils/fetch.js";
|
|
2
|
+
import { handleXAIError } from "./Errors.js";
|
|
3
|
+
import { Capabilities } from "./Capabilities.js";
|
|
4
|
+
export class XAIModels {
|
|
5
|
+
baseUrl;
|
|
6
|
+
apiKey;
|
|
7
|
+
constructor(baseUrl, apiKey) {
|
|
8
|
+
this.baseUrl = baseUrl;
|
|
9
|
+
this.apiKey = apiKey;
|
|
10
|
+
}
|
|
11
|
+
async execute() {
|
|
12
|
+
const url = `${this.baseUrl}/models`;
|
|
13
|
+
const response = await fetchWithTimeout(url, {
|
|
14
|
+
method: "GET",
|
|
15
|
+
headers: {
|
|
16
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
17
|
+
"Content-Type": "application/json"
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
await handleXAIError(response);
|
|
22
|
+
}
|
|
23
|
+
const json = (await response.json());
|
|
24
|
+
return json.data.map((m) => {
|
|
25
|
+
const caps = [];
|
|
26
|
+
if (Capabilities.supportsVision(m.id))
|
|
27
|
+
caps.push("vision");
|
|
28
|
+
if (Capabilities.supportsTools(m.id))
|
|
29
|
+
caps.push("tools");
|
|
30
|
+
if (Capabilities.supportsStructuredOutput(m.id))
|
|
31
|
+
caps.push("structured_output");
|
|
32
|
+
if (Capabilities.supportsReasoning(m.id))
|
|
33
|
+
caps.push("reasoning");
|
|
34
|
+
return {
|
|
35
|
+
id: m.id,
|
|
36
|
+
name: m.id,
|
|
37
|
+
provider: "xai",
|
|
38
|
+
family: "grok",
|
|
39
|
+
context_window: Capabilities.getContextWindow(m.id),
|
|
40
|
+
max_output_tokens: null,
|
|
41
|
+
modalities: { input: ["text", "image"], output: ["text"] },
|
|
42
|
+
capabilities: caps,
|
|
43
|
+
pricing: {}
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChatRequest, ChatChunk } from "../Provider.js";
|
|
2
|
+
export declare class XAIStreaming {
|
|
3
|
+
private readonly baseUrl;
|
|
4
|
+
private readonly apiKey;
|
|
5
|
+
constructor(baseUrl: string, apiKey: string);
|
|
6
|
+
execute(request: ChatRequest, controller?: AbortController): AsyncGenerator<ChatChunk>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=Streaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAOxD,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CA2L9F"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { APIError } from "../../errors/index.js";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
import { handleXAIError } from "./Errors.js";
|
|
4
|
+
import { mapSystemMessages } from "../utils.js";
|
|
5
|
+
import { fetchWithTimeout } from "../../utils/fetch.js";
|
|
6
|
+
export class XAIStreaming {
|
|
7
|
+
baseUrl;
|
|
8
|
+
apiKey;
|
|
9
|
+
constructor(baseUrl, apiKey) {
|
|
10
|
+
this.baseUrl = baseUrl;
|
|
11
|
+
this.apiKey = apiKey;
|
|
12
|
+
}
|
|
13
|
+
async *execute(request, controller) {
|
|
14
|
+
const abortController = controller || new AbortController();
|
|
15
|
+
const { model, messages, tools, max_tokens, response_format, thinking: _thinking, headers: _headers, requestTimeout, ...rest } = request;
|
|
16
|
+
const mappedMessages = mapSystemMessages(messages, false);
|
|
17
|
+
const body = {
|
|
18
|
+
model,
|
|
19
|
+
messages: mappedMessages,
|
|
20
|
+
stream: true,
|
|
21
|
+
...rest
|
|
22
|
+
};
|
|
23
|
+
if (max_tokens)
|
|
24
|
+
body.max_tokens = max_tokens;
|
|
25
|
+
if (tools && tools.length > 0)
|
|
26
|
+
body.tools = tools;
|
|
27
|
+
if (response_format)
|
|
28
|
+
body.response_format = response_format;
|
|
29
|
+
// xAI supports include_usage
|
|
30
|
+
body.stream_options = { include_usage: true };
|
|
31
|
+
let done = false;
|
|
32
|
+
// Track tool calls being built across chunks
|
|
33
|
+
const toolCallsMap = new Map();
|
|
34
|
+
try {
|
|
35
|
+
const url = `${this.baseUrl}/chat/completions`;
|
|
36
|
+
logger.logRequest("xAI", "POST", url, body);
|
|
37
|
+
const response = await fetchWithTimeout(url, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: {
|
|
40
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
41
|
+
"Content-Type": "application/json",
|
|
42
|
+
...request.headers
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(body),
|
|
45
|
+
signal: abortController.signal
|
|
46
|
+
}, requestTimeout);
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
await handleXAIError(response, model);
|
|
49
|
+
}
|
|
50
|
+
logger.debug("xAI streaming started", {
|
|
51
|
+
status: response.status,
|
|
52
|
+
statusText: response.statusText
|
|
53
|
+
});
|
|
54
|
+
if (!response.body) {
|
|
55
|
+
throw new Error("No response body for streaming");
|
|
56
|
+
}
|
|
57
|
+
const reader = response.body.getReader();
|
|
58
|
+
const decoder = new TextDecoder();
|
|
59
|
+
let buffer = "";
|
|
60
|
+
while (true) {
|
|
61
|
+
const { value, done: readerDone } = await reader.read();
|
|
62
|
+
if (readerDone)
|
|
63
|
+
break;
|
|
64
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
65
|
+
buffer += chunk;
|
|
66
|
+
const lines = buffer.split("\n\n");
|
|
67
|
+
buffer = lines.pop() || "";
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
let trimmed = line.trim();
|
|
70
|
+
// Handle carriage returns
|
|
71
|
+
if (trimmed.endsWith("\r")) {
|
|
72
|
+
trimmed = trimmed.substring(0, trimmed.length - 1);
|
|
73
|
+
}
|
|
74
|
+
if (!trimmed.startsWith("data: "))
|
|
75
|
+
continue;
|
|
76
|
+
const data = trimmed.replace("data: ", "").trim();
|
|
77
|
+
if (data === "[DONE]") {
|
|
78
|
+
done = true;
|
|
79
|
+
// Yield final tool calls if any were accumulated
|
|
80
|
+
if (toolCallsMap.size > 0) {
|
|
81
|
+
const toolCalls = Array.from(toolCallsMap.values()).map((tc) => ({
|
|
82
|
+
id: tc.id,
|
|
83
|
+
type: "function",
|
|
84
|
+
function: {
|
|
85
|
+
name: tc.function.name,
|
|
86
|
+
arguments: tc.function.arguments
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
yield { content: "", tool_calls: toolCalls, done: true };
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const json = JSON.parse(data);
|
|
95
|
+
// Check for errors in the data
|
|
96
|
+
if (json.error) {
|
|
97
|
+
throw new APIError("xAI", response.status, json.error.message || "Stream error");
|
|
98
|
+
}
|
|
99
|
+
const delta = json.choices?.[0]?.delta;
|
|
100
|
+
const deltaContent = delta?.content;
|
|
101
|
+
if (deltaContent) {
|
|
102
|
+
yield {
|
|
103
|
+
content: deltaContent || ""
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// Handle tool calls delta
|
|
107
|
+
if (delta?.tool_calls) {
|
|
108
|
+
for (const toolCallDelta of delta.tool_calls) {
|
|
109
|
+
const index = toolCallDelta.index;
|
|
110
|
+
if (!toolCallsMap.has(index)) {
|
|
111
|
+
toolCallsMap.set(index, {
|
|
112
|
+
id: toolCallDelta.id || "",
|
|
113
|
+
type: "function",
|
|
114
|
+
function: {
|
|
115
|
+
name: toolCallDelta.function?.name || "",
|
|
116
|
+
arguments: toolCallDelta.function?.arguments || ""
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const existing = toolCallsMap.get(index);
|
|
122
|
+
if (toolCallDelta.id)
|
|
123
|
+
existing.id = toolCallDelta.id;
|
|
124
|
+
if (toolCallDelta.function?.name) {
|
|
125
|
+
existing.function.name += toolCallDelta.function.name;
|
|
126
|
+
}
|
|
127
|
+
if (toolCallDelta.function?.arguments) {
|
|
128
|
+
existing.function.arguments += toolCallDelta.function.arguments;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Handle usage
|
|
134
|
+
if (json.usage) {
|
|
135
|
+
const usage = {
|
|
136
|
+
input_tokens: json.usage.prompt_tokens,
|
|
137
|
+
output_tokens: json.usage.completion_tokens,
|
|
138
|
+
total_tokens: json.usage.total_tokens
|
|
139
|
+
};
|
|
140
|
+
yield { content: "", usage };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
// Re-throw APIError
|
|
145
|
+
if (e instanceof APIError)
|
|
146
|
+
throw e;
|
|
147
|
+
// Ignore other parse errors
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
done = true;
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
// Graceful exit on abort
|
|
155
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
throw e;
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
// Cleanup: abort if user breaks early
|
|
162
|
+
if (!done) {
|
|
163
|
+
abortController.abort();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Provider, ChatRequest, ChatResponse, ModelInfo, ChatChunk, ImageRequest, ImageResponse } from "../Provider.js";
|
|
2
|
+
import { BaseProvider } from "../BaseProvider.js";
|
|
3
|
+
export interface XAIProviderOptions {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class XAIProvider extends BaseProvider implements Provider {
|
|
8
|
+
private readonly options;
|
|
9
|
+
private readonly baseUrl;
|
|
10
|
+
private readonly chatHandler;
|
|
11
|
+
private readonly streamingHandler;
|
|
12
|
+
private readonly modelsHandler;
|
|
13
|
+
private readonly imageHandler;
|
|
14
|
+
capabilities: {
|
|
15
|
+
supportsVision: (model: string) => boolean;
|
|
16
|
+
supportsTools: (model: string) => boolean;
|
|
17
|
+
supportsStructuredOutput: (model: string) => boolean;
|
|
18
|
+
supportsEmbeddings: (model: string) => boolean;
|
|
19
|
+
supportsImageGeneration: (model: string) => boolean;
|
|
20
|
+
supportsTranscription: (model: string) => boolean;
|
|
21
|
+
supportsModeration: (model: string) => boolean;
|
|
22
|
+
supportsReasoning: (model: string) => boolean;
|
|
23
|
+
supportsDeveloperRole: (_model: string) => boolean;
|
|
24
|
+
getContextWindow: (model: string) => number;
|
|
25
|
+
};
|
|
26
|
+
constructor(options: XAIProviderOptions);
|
|
27
|
+
get id(): string;
|
|
28
|
+
apiBase(): string;
|
|
29
|
+
headers(): Record<string, string>;
|
|
30
|
+
protected providerName(): string;
|
|
31
|
+
defaultModel(_feature?: string): string;
|
|
32
|
+
chat(request: ChatRequest): Promise<ChatResponse>;
|
|
33
|
+
stream(request: ChatRequest): AsyncGenerator<ChatChunk>;
|
|
34
|
+
listModels(): Promise<ModelInfo[]>;
|
|
35
|
+
paint(request: ImageRequest): Promise<ImageResponse>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=XAIProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"XAIProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/xai/XAIProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,EACZ,aAAa,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAY,SAAQ,YAAa,YAAW,QAAQ;IAoBnD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAnBpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAe;IAChD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAW;IAEjC,YAAY;gCACO,MAAM;+BACP,MAAM;0CACK,MAAM;oCACZ,MAAM;yCACD,MAAM;uCACR,MAAM;oCACT,MAAM;mCACP,MAAM;wCACD,MAAM;kCACZ,MAAM;MAChC;gBAE2B,OAAO,EAAE,kBAAkB;IASxD,IAAW,EAAE,IAAI,MAAM,CAEtB;IAEM,OAAO,IAAI,MAAM;IAIjB,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAOxC,SAAS,CAAC,YAAY,IAAI,MAAM;IAIhB,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAIjD,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAIhD,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC;IAIxD,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAIlC,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;CAG3D"}
|