diff --git a/src/backend/src/modules/puterai/DeepSeekService.js b/src/backend/src/modules/puterai/DeepSeekService.js
new file mode 100644
index 000000000..697f42412
--- /dev/null
+++ b/src/backend/src/modules/puterai/DeepSeekService.js
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2024-present Puter Technologies Inc.
+ *
+ * This file is part of Puter.
+ *
+ * Puter is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+// METADATA // {"ai-commented":{"service":"claude"}}
+const BaseService = require("../../services/BaseService");
+const { whatis, nou } = require("../../util/langutil");
+const { PassThrough } = require("stream");
+const { TypedValue } = require("../../services/drivers/meta/Runtime");
+const { TeePromise } = require('@heyputer/putility').libs.promise;
+
+const PUTER_PROMPT = `
+ You are running on an open-source platform called Puter,
+ as the DeepSeek implementation for a driver interface
+ called puter-chat-completion.
+
+ The following JSON contains system messages from the
+ user of the driver interface (typically an app on Puter):
+`.replace('\n', ' ').trim();
+
+
+/**
+* DeepSeekService class - Provides integration with X.AI's API for chat completions
+* Extends BaseService to implement the puter-chat-completion interface.
+* Handles model management, message adaptation, streaming responses,
+* and usage tracking for X.AI's language models like Grok.
+* @extends BaseService
+*/
+class DeepSeekService extends BaseService {
+ static MODULES = {
+ openai: require('openai'),
+ }
+
+
+ /**
+ * Gets the system prompt used for AI interactions
+ * @returns {string} The base system prompt that identifies the AI as running on Puter
+ */
+ get_system_prompt () {
+ return PUTER_PROMPT;
+ }
+
+ adapt_model (model) {
+ return model;
+ }
+
+
+ /**
+ * Initializes the XAI service by setting up the OpenAI client and registering with the AI chat provider
+ * @private
+ * @returns {Promise} Resolves when initialization is complete
+ */
+ async _init () {
+ this.openai = new this.modules.openai.OpenAI({
+ apiKey: this.global_config.services.deepseek.apiKey,
+ baseURL: 'https://api.deepseek.com',
+ });
+
+ const svc_aiChat = this.services.get('ai-chat');
+ svc_aiChat.register_provider({
+ service_name: this.service_name,
+ alias: true,
+ });
+ }
+
+
+ /**
+ * Returns the default model identifier for the XAI service
+ * @returns {string} The default model ID 'grok-beta'
+ */
+ get_default_model () {
+ return 'grok-beta';
+ }
+
+ static IMPLEMENTS = {
+ ['puter-chat-completion']: {
+ /**
+ * Returns a list of available models and their details.
+ * See AIChatService for more information.
+ *
+ * @returns Promise> Array of model details
+ */
+ async models () {
+ return await this.models_();
+ },
+ /**
+ * Returns a list of available model names including their aliases
+ * @returns {Promise} Array of model identifiers and their aliases
+ * @description Retrieves all available model IDs and their aliases,
+ * flattening them into a single array of strings that can be used for model selection
+ */
+ async list () {
+ const models = await this.models_();
+ const model_names = [];
+ for ( const model of models ) {
+ model_names.push(model.id);
+ if ( model.aliases ) {
+ model_names.push(...model.aliases);
+ }
+ }
+ return model_names;
+ },
+
+ /**
+ * AI Chat completion method.
+ * See AIChatService for more details.
+ */
+ async complete ({ messages, stream, model }) {
+ model = this.adapt_model(model);
+ const adapted_messages = [];
+
+ const system_prompts = [];
+ let previous_was_user = false;
+ for ( const message of messages ) {
+ if ( typeof message.content === 'string' ) {
+ message.content = {
+ type: 'text',
+ text: message.content,
+ };
+ }
+ if ( whatis(message.content) !== 'array' ) {
+ message.content = [message.content];
+ }
+ if ( ! message.role ) message.role = 'user';
+ if ( message.role === 'user' && previous_was_user ) {
+ const last_msg = adapted_messages[adapted_messages.length-1];
+ last_msg.content.push(
+ ...(Array.isArray ? message.content : [message.content])
+ );
+ continue;
+ }
+ if ( message.role === 'system' ) {
+ system_prompts.push(...message.content);
+ continue;
+ }
+ adapted_messages.push(message);
+ if ( message.role === 'user' ) {
+ previous_was_user = true;
+ }
+ }
+
+ adapted_messages.unshift({
+ role: 'system',
+ content: this.get_system_prompt() +
+ JSON.stringify(system_prompts),
+ })
+
+ const completion = await this.openai.chat.completions.create({
+ messages: adapted_messages,
+ model: model ?? this.get_default_model(),
+ max_tokens: 1000,
+ stream,
+ ...(stream ? {
+ stream_options: { include_usage: true },
+ } : {}),
+ });
+
+ if ( stream ) {
+ let usage_promise = new TeePromise();
+
+ const stream = new PassThrough();
+ const retval = new TypedValue({
+ $: 'stream',
+ content_type: 'application/x-ndjson',
+ chunked: true,
+ }, stream);
+ (async () => {
+ let last_usage = null;
+ for await ( const chunk of completion ) {
+ if ( chunk.usage ) last_usage = chunk.usage;
+ // if (
+ // event.type !== 'content_block_delta' ||
+ // event.delta.type !== 'text_delta'
+ // ) continue;
+ // const str = JSON.stringify({
+ // text: event.delta.text,
+ // });
+ // stream.write(str + '\n');
+ if ( chunk.choices.length < 1 ) continue;
+ if ( nou(chunk.choices[0].delta.content) ) continue;
+ const str = JSON.stringify({
+ text: chunk.choices[0].delta.content
+ });
+ stream.write(str + '\n');
+ }
+ usage_promise.resolve({
+ input_tokens: last_usage.prompt_tokens,
+ output_tokens: last_usage.completion_tokens,
+ });
+ stream.end();
+ })();
+
+ return new TypedValue({ $: 'ai-chat-intermediate' }, {
+ stream: true,
+ response: retval,
+ usage_promise: usage_promise,
+ });
+ }
+
+ const ret = completion.choices[0];
+ ret.usage = {
+ input_tokens: completion.usage.prompt_tokens,
+ output_tokens: completion.usage.completion_tokens,
+ };
+ return ret;
+ }
+ }
+ }
+
+
+ /**
+ * Retrieves available AI models and their specifications
+ * @returns {Promise} Array of model objects containing:
+ * - id: Model identifier string
+ * - name: Human readable model name
+ * - context: Maximum context window size
+ * - cost: Pricing information object with currency and rates
+ * @private
+ */
+ async models_ () {
+ return [
+ {
+ id: 'deepseek-chat',
+ name: 'DeepSeek Chat',
+ context: 64000,
+ cost: {
+ currency: 'usd-cents',
+ tokens: 1_000_000,
+ input: 14,
+ output: 28,
+ },
+ },
+ {
+ id: 'deepseek-reasoner',
+ name: 'DeepSeek Reasoner',
+ context: 64000,
+ cost: {
+ currency: 'usd-cents',
+ tokens: 1_000_000,
+ input: 55,
+ output: 219,
+ },
+ }
+ ];
+ }
+}
+
+module.exports = {
+ DeepSeekService,
+};
+
diff --git a/src/backend/src/modules/puterai/PuterAIModule.js b/src/backend/src/modules/puterai/PuterAIModule.js
index 04247342b..b3ec8d48f 100644
--- a/src/backend/src/modules/puterai/PuterAIModule.js
+++ b/src/backend/src/modules/puterai/PuterAIModule.js
@@ -92,6 +92,14 @@ class PuterAIModule extends AdvancedBase {
// services.registerService('claude', ClaudeEnoughService);
}
+ if ( !! config?.services?.['deepseek'] ) {
+ const { DeepSeekService } = require('./DeepSeekService');
+ services.registerService('deepseek', DeepSeekService);
+
+ // const { ClaudeEnoughService } = require('./ClaudeEnoughService');
+ // services.registerService('claude', ClaudeEnoughService);
+ }
+
const { AIChatService } = require('./AIChatService');
services.registerService('ai-chat', AIChatService);