Jika Anda ingin menyembunyikan API Token di server-side, buat Cloudflare Worker gratis dan tempelkan kode berikut ke dalamnya:
const ALLOWED_MODELS = [
"@cf/meta/llama-3.1-8b-instruct-fp8",
"@cf/meta/llama-3.2-1b-instruct",
"@cf/meta/llama-3.2-3b-instruct",
"@cf/zai-org/glm-4.7-flash",
"@cf/google/gemma-4-26b-a4b-it",
];
const DEFAULT_MODEL = "@cf/meta/llama-3.1-8b-instruct-fp8";
const CORS = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
"Content-Type": "application/json; charset=utf-8",
};
function json(data, status = 200) {
return new Response(JSON.stringify(data), { status, headers: CORS });
}
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (request.method === "OPTIONS") return new Response(null, { status: 204, headers: CORS });
if (request.method === "GET" && url.pathname === "/") {
return json({ success: true, message: "AI Worker aktif", endpoint: "/chat", models: ALLOWED_MODELS });
}
if (url.pathname !== "/chat") return json({ success: false, error: "Endpoint tidak ditemukan" }, 404);
if (request.method !== "POST") return json({ success: false, error: "Gunakan POST" }, 405);
if (!env.AI) return json({ success: false, error: "Binding Workers AI bernama AI belum dikonfigurasi." }, 500);
try {
const body = await request.json();
const requestedModel = typeof body.model === "string" ? body.model : DEFAULT_MODEL;
if (!ALLOWED_MODELS.includes(requestedModel)) {
return json({ success: false, error: "Model tidak diizinkan. Pilih model dari daftar di aplikasi." }, 400);
}
let messages;
if (Array.isArray(body.messages) && body.messages.length) {
const validMessages = body.messages
.filter(m => m && ["system", "user", "assistant"].includes(m.role) && typeof m.content === "string")
.map(m => ({ role: m.role, content: m.content.slice(0, 12000) }));
// Pertahankan system prompt dan maksimal 20 pesan percakapan terbaru.
const systemMessage = validMessages.find(m => m.role === "system");
const conversation = validMessages.filter(m => m.role !== "system").slice(-20);
messages = [...(systemMessage ? [systemMessage] : []), ...conversation];
} else {
const message = typeof body.message === "string" ? body.message.trim() : "";
if (!message) return json({ success: false, error: "Pesan masih kosong." }, 400);
messages = [
{ role: "system", content: "Kamu adalah asisten AI yang ramah, membantu, jujur, dan menjawab sesuai bahasa pengguna." },
{ role: "user", content: message.slice(0, 4000) },
];
}
if (!messages.some(m => m.role === "user")) {
return json({ success: false, error: "Pesan pengguna tidak ditemukan." }, 400);
}
const result = await env.AI.run(requestedModel, {
messages,
max_tokens: 900,
});
const answer = result && typeof result.response === "string" ? result.response : "";
if (!answer) return json({ success: false, error: "Model tidak mengembalikan jawaban teks." }, 502);
return json({ success: true, answer, model: requestedModel });
} catch (error) {
console.error("Workers AI error:", error);
return json({ success: false, error: error instanceof Error ? error.message : String(error) }, 500);
}
},
};