Skip to content

Commit 28adcf5

Browse files
committed
feat(ai): add xAI grok-beta
1 parent d613c5f commit 28adcf5

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

src/backend/src/modules/puterai/PuterAIModule.js

+5
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ class PuterAIModule extends AdvancedBase {
4848
const { GroqAIService } = require('./GroqAIService');
4949
services.registerService('groq', GroqAIService);
5050
}
51+
52+
if ( !! config?.services?.['xai'] ) {
53+
const { XAIService } = require('./XAIService');
54+
services.registerService('xai', XAIService);
55+
}
5156
}
5257
}
5358

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
const { default: Anthropic } = require("@anthropic-ai/sdk");
2+
const BaseService = require("../../services/BaseService");
3+
const { whatis } = require("../../util/langutil");
4+
const { PassThrough } = require("stream");
5+
const { TypedValue } = require("../../services/drivers/meta/Runtime");
6+
7+
const PUTER_PROMPT = `
8+
You are running on an open-source platform called Puter,
9+
as the xAI implementation for a driver interface
10+
called puter-chat-completion.
11+
12+
The following JSON contains system messages from the
13+
user of the driver interface (typically an app on Puter):
14+
`.replace('\n', ' ').trim();
15+
16+
class XAIService extends BaseService {
17+
static MODULES = {
18+
Anthropic: require('@anthropic-ai/sdk'),
19+
}
20+
21+
async _init () {
22+
this.anthropic = new Anthropic({
23+
apiKey: this.config.apiKey,
24+
baseURL: 'https://api.x.ai'
25+
});
26+
}
27+
28+
static IMPLEMENTS = {
29+
['puter-chat-completion']: {
30+
async list () {
31+
return [
32+
'grok-beta',
33+
];
34+
},
35+
async complete ({ messages, stream, model }) {
36+
const adapted_messages = [];
37+
38+
const system_prompts = [];
39+
let previous_was_user = false;
40+
for ( const message of messages ) {
41+
if ( typeof message.content === 'string' ) {
42+
message.content = {
43+
type: 'text',
44+
text: message.content,
45+
};
46+
}
47+
if ( whatis(message.content) !== 'array' ) {
48+
message.content = [message.content];
49+
}
50+
if ( ! message.role ) message.role = 'user';
51+
if ( message.role === 'user' && previous_was_user ) {
52+
const last_msg = adapted_messages[adapted_messages.length-1];
53+
last_msg.content.push(
54+
...(Array.isArray ? message.content : [message.content])
55+
);
56+
continue;
57+
}
58+
if ( message.role === 'system' ) {
59+
system_prompts.push(...message.content);
60+
continue;
61+
}
62+
adapted_messages.push(message);
63+
if ( message.role === 'user' ) {
64+
previous_was_user = true;
65+
}
66+
}
67+
68+
if ( stream ) {
69+
const stream = new PassThrough();
70+
const retval = new TypedValue({
71+
$: 'stream',
72+
content_type: 'application/x-ndjson',
73+
chunked: true,
74+
}, stream);
75+
(async () => {
76+
const completion = await this.anthropic.messages.stream({
77+
model: model ?? 'grok-beta',
78+
max_tokens: 1000,
79+
temperature: 0,
80+
system: PUTER_PROMPT + JSON.stringify(system_prompts),
81+
messages: adapted_messages,
82+
});
83+
for await ( const event of completion ) {
84+
if (
85+
event.type !== 'content_block_delta' ||
86+
event.delta.type !== 'text_delta'
87+
) continue;
88+
const str = JSON.stringify({
89+
text: event.delta.text,
90+
});
91+
stream.write(str + '\n');
92+
}
93+
stream.end();
94+
})();
95+
96+
return retval;
97+
}
98+
99+
const msg = await this.anthropic.messages.create({
100+
model: model ?? 'grok-beta',
101+
max_tokens: 1000,
102+
temperature: 0,
103+
system: PUTER_PROMPT + JSON.stringify(system_prompts),
104+
messages: adapted_messages,
105+
});
106+
return {
107+
message: msg,
108+
finish_reason: 'stop'
109+
};
110+
}
111+
}
112+
}
113+
}
114+
115+
module.exports = {
116+
XAIService,
117+
};

src/puter-js/src/modules/AI.js

+2
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ class AI{
267267
"whisper-large-v3"
268268
].includes(options.model)) {
269269
driver = 'groq';
270+
}else if(options.model === 'grok-beta') {
271+
driver = 'xai';
270272
}
271273

272274
// stream flag from settings

0 commit comments

Comments
 (0)