rynn-k / gists
llamacoder.js javascript
const axios = require('axios');
const crypto = require('crypto');
const { fromBuffer } = require('file-type');

class LlamaCoder {
    constructor() {
        this.inst = axios.create({
            baseURL: 'https://llamacoder.together.ai/api',
            headers: {
                origin: 'https://llamacoder.together.ai',
                referer: 'https://llamacoder.together.ai/',
                'user-agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36'
            }
        });
        
        this.config = {
            models: {
                'deepseek-v3.1': 'deepseek-ai/DeepSeek-V3.1',
                'qwen3-coder': 'Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8',
                'kimi-k2.1': 'moonshotai/Kimi-K2-Instruct-0905',
                'glm-4.6': 'zai-org/GLM-4.6'
            },
            qualities: ['low', 'high']
        };
    }
    
    _upload = async function (buffer) {
        try {
            if (!buffer || !Buffer.isBuffer(buffer)) throw new Error('Image buffer is required.');
            
            const { mime } = await fromBuffer(buffer);
            if (!/image/.test(mime)) throw new Error('Buffer must be a image.');
            
            const { data } = await this.inst.post('/s3-upload', {
                filename: `${Date.now()}_rynn.jpg`,
                filetype: 'image/jpeg',
                _nextS3: { strategy: 'aws-sdk' }
            });
            
            const { region, bucket, key } = data;
            const { AccessKeyId, SecretAccessKey, SessionToken } = data.token.Credentials;
            
            const now = new Date();
            const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '').slice(0, 15) + 'Z';
            const dateStamp = amzDate.slice(0, 8);
            const payloadHash = crypto.createHash('sha256').update(buffer).digest('hex');
            const host = `${bucket}.s3.${region}.amazonaws.com`;
            
            const canonicalHeaders = `content-type:${mime}\nhost:${host}\nx-amz-content-sha256:${payloadHash}\nx-amz-date:${amzDate}\nx-amz-security-token:${SessionToken}\n`;
            const signedHeaders = 'content-type;host;x-amz-content-sha256;x-amz-date;x-amz-security-token';
            const canonicalRequest = `PUT\n/${key}\n\n${canonicalHeaders}\n${signedHeaders}\n${payloadHash}`;
            
            const credentialScope = `${dateStamp}/${region}/s3/aws4_request`;
            const stringToSign = `AWS4-HMAC-SHA256\n${amzDate}\n${credentialScope}\n${crypto.createHash('sha256').update(canonicalRequest).digest('hex')}`;
            
            const signingKey = ['aws4_request', 's3', region, dateStamp].reduceRight((acc, val) => crypto.createHmac('sha256', acc).update(val).digest(), `AWS4${SecretAccessKey}`);
            const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex');
            const authorization = `AWS4-HMAC-SHA256 Credential=${AccessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
            
            await axios.put(`https://${host}/${key}`, buffer, {
                headers: {
                    authorization: authorization,
                    'content-type': mime,
                    'x-amz-date': amzDate,
                    'x-amz-content-sha256': payloadHash,
                    'x-amz-security-token': SessionToken
                }
            });
    
            return `https://${host}/${key}`;
        } catch (error) {
            throw new Error('Failed to upload image.');
        }
    }
    
    create = async function ({ prompt, model = 'deepseek-v3.1', quality = 'high', image = null } = {}) {
        try {
            if (!prompt) throw new Error('Prompt is required.');
            if (!this.config.models[model]) throw new Error(`Available models: ${Object.keys(this.config.models).join(', ')}.`);
            if (!this.config.qualities.includes(quality)) throw new Error(`Available qualities: ${this.config.qualities.join(', ')}.`);
            
            let img;
            if (image) img = await this._upload(image);
            
            const { data: t } = await this.inst.post('/create-chat', {
                prompt: prompt,
                model: this.config.models[model],
                quality: quality,
                ...(image ? { screenshotUrl: img } : {})
            });
            
            if (!t?.lastMessageId) throw new Error('Failed to create chat.');
            
            const { data } = await this.inst.post('/get-next-completion-stream-promise', {
                messageId: t.lastMessageId,
                model: this.config.models[model]
            });
            
            const result = data.split('\n').filter(d => d).map(m => JSON.parse(m)).map(line => line?.choices?.[0]?.text).join('');
            if (!result) throw new Error('No result found.');
            
            return result;
        } catch (error) {
            throw new Error(error.message);
        }
    }
}

// Usage:
const llama = new LlamaCoder();
llama.create({
    prompt: 'Make a beautiful pomodoro timer where I can adjust the lengths of the focus time and the break and it will beep when done.',
    model: 'qwen3-coder'
}).then(console.log);
5315 bytes ยท Updated Mar 24, 2026