const std = @import("std"); const CEREBRAS_URL = "https://a...
Prompt
const std = @import("std"); const CEREBRAS_URL = "https://api.cerebras.ai/v1/chat/completions"; const EXA_URL = "https://api.exa.ai/search"; const PORT = 5000; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); // Check environment variables const cerebras_key = std.process.getEnvVarOwned(allocator, "CEREBRAS_API_KEY") catch { std.log.err("CEREBRAS_API_KEY environment variable is required", .{}); return; }; defer allocator.free(cerebras_key); const exa_key = std.process.getEnvVarOwned(allocator, "EXA_API_KEY") catch { std.log.err("EXA_API_KEY environment variable is required", .{}); return; }; defer allocator.free(exa_key); // Create HTTP client var http_client = std.http.Client{ .allocator = allocator }; defer http_client.deinit(); // Create server const address = std.net.Address.parseIp4("0.0.0.0", PORT) catch unreachable; var server = address.listen(.{ .reuse_address = true, }) catch |err| { std.log.err("Failed to start server: {}", .{err}); return; }; defer server.deinit(); std.log.info("Server listening on http://0.0.0.0:{d}", .{PORT}); while (true) { const connection = server.accept() catch |err| { std.log.err("Failed to accept connection: {}", .{err}); continue; }; handleRequest(allocator, connection, &http_client, cerebras_key, exa_key) catch |err| { std.log.err("Error handling request: {}", .{err}); }; connection.stream.close(); } } fn handleRequest( allocator: std.mem.Allocator, connection: std.net.Server.Connection, http_client: *std.http.Client, cerebras_key: []const u8, exa_key: []const u8, ) !void { var buffer: [8192]u8 = undefined; const bytes_read = try connection.stream.reader().read(&buffer); if (bytes_read == 0) return; const request = buffer[0..bytes_read]; // Parse first line to get method and path var lines = std.mem.split(u8, request, "\r\n"); const first_line = lines.next() orelse return; var parts = std.mem.split(u8, first_line, " "); const method = parts.next() orelse return; const path = parts.next() orelse return; if (std.mem.eql(u8, method, "GET") and std.mem.eql(u8, path, "/")) { try serveFile(connection.stream.writer(), allocator, "index.html"); } else if (std.mem.eql(u8, method, "POST") and std.mem.eql(u8, path, "/api/chat")) { try handleChat(connection.stream.writer(), allocator, request, http_client, cerebras_key); } else if (std.mem.eql(u8, method, "POST") and std.mem.eql(u8, path, "/api/deepsearch")) { try handleDeepSearch(connection.stream.writer(), allocator, request, http_client, cerebras_key, exa_key); } else { try send404(connection.stream.writer()); } } fn serveFile(writer: anytype, allocator: std.mem.Allocator, path: []const u8) !void { const file = std.fs.cwd().openFile(path, .{}) catch { try send404(writer); return; }; defer file.close(); const content = try file.readToEndAlloc(allocator, 1024 * 1024); defer allocator.free(content); const response = try std.fmt.allocPrint(allocator, "HTTP/1.1 200 OK\r\n" ++ "Content-Type: text/html; charset=utf-8\r\n" ++ "Content-Length: {d}\r\n" ++ "\r\n" ++ "{s}", .{ content.len, content } ); defer allocator.free(response); try writer.writeAll(response); } fn send404(writer: anytype) !void { const response = "HTTP/1.1 404 Not Found\r\n" ++ "Content-Type: text/plain\r\n" ++ "Content-Length: 9\r\n" ++ "\r\n" ++ "Not Found"; try writer.writeAll(response); } fn sendError(writer: anytype, allocator: std.mem.Allocator, status: []const u8, message: []const u8) !void { const response = try std.fmt.allocPrint(allocator, "HTTP/1.1 {s}\r\n" ++ "Content-Type: text/plain\r\n" ++ "Content-Length: {d}\r\n" ++ "\r\n" ++ "{s}", .{ status, message.len, message } ); defer allocator.free(response); try writer.writeAll(response); } fn findRequestBody(request: []const u8) []const u8 { const body_separator = "\r\n\r\n"; if (std.mem.indexOf(u8, request, body_separator)) |pos| { return request[pos + body_separator.len..]; } return ""; } fn extractJsonString(allocator: std.mem.Allocator, json_str: []const u8, field: []const u8) ![]u8 { var parsed = std.json.parseFromSlice(std.json.Value, allocator, json_str, .{}) catch { return error.InvalidJson; }; defer parsed.deinit(); const obj = parsed.value.object; const field_value = obj.get(field) orelse return error.FieldNotFound; return try allocator.dupe(u8, field_value.string); } fn escapeJsonString(allocator: std.mem.Allocator, input: []const u8) ![]u8 { var result = std.ArrayList(u8).init(allocator); defer result.deinit(); for (input) |char| { switch (char) { '"' => try result.appendSlice("\\\""), '\\' => try result.appendSlice("\\\\"), '\n' => try result.appendSlice("\\n"), '\r' => try result.appendSlice("\\r"), '\t' => try result.appendSlice("\\t"), else => try result.append(char), } } return result.toOwnedSlice(); } fn handleChat(writer: anytype, allocator: std.mem.Allocator, request: []const u8, http_client: *std.http.Client, cerebras_key: []const u8) !void { const body = findRequestBody(request); if (body.len == 0) { try sendError(writer, allocator, "400 Bad Request", "Missing request body"); return; } const message = extractJsonString(allocator, body, "message") catch { try sendError(writer, allocator, "400 Bad Request", "Invalid JSON or missing message field"); return; }; defer allocator.free(message); // Send SSE headers const headers = "HTTP/1.1 200 OK\r\n" ++ "Content-Type: text/event-stream\r\n" ++ "Cache-Control: no-cache\r\n" ++ "Connection: keep-alive\r\n" ++ "Access-Control-Allow-Origin: *\r\n" ++ "\r\n"; try writer.writeAll(headers); // Call Cerebras API try streamCerebrasChat(writer, allocator, http_client, cerebras_key, message); } fn handleDeepSearch(writer: anytype, allocator: std.mem.Allocator, request: []const u8, http_client: *std.http.Client, cerebras_key: []const u8, exa_key: []const u8) !void { const body = findRequestBody(request); if (body.len == 0) { try sendError(writer, allocator, "400 Bad Request", "Missing request body"); return; } const query = extractJsonString(allocator, body, "query") catch { try sendError(writer, allocator, "400 Bad Request", "Invalid JSON or missing query field"); return; }; defer allocator.free(query); // Send SSE headers const headers = "HTTP/1.1 200 OK\r\n" ++ "Content-Type: text/event-stream\r\n" ++ "Cache-Control: no-cache\r\n" ++ "Connection: keep-alive\r\n" ++ "Access-Control-Allow-Origin: *\r\n" ++ "\r\n"; try writer.writeAll(headers); // First search with Exa const search_results = searchWithExa(allocator, http_client, exa_key, query) catch |err| { std.log.err("Exa search failed: {}", .{err}); const error_data = "data: {\"choices\":[{\"delta\":{\"content\":\"Hiba történt a keresés során.\"}}]}\n\n"; try writer.writeAll(error_data); const done_data = "data: [DONE]\n\n"; try writer.writeAll(done_data); return; }; defer allocator.free(search_results); // Stream response with search results try streamCerebrasDeepSearch(writer, allocator, http_client, cerebras_key, query, search_results); } fn searchWithExa(allocator: std.mem.Allocator, http_client: *std.http.Client, exa_key: []const u8, query: []const u8) ![]u8 { const escaped_query = try escapeJsonString(allocator, query); defer allocator.free(escaped_query); const payload = try std.fmt.allocPrint(allocator, "{{\"query\":\"{s}\",\"type\":\"fast\",\"numResults\":30,\"livecrawl\":\"never\"}}", .{escaped_query} ); defer allocator.free(payload); const uri = try std.Uri.parse(EXA_URL); const auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{exa_key}); defer allocator.free(auth_header); var headers = std.http.Headers{ .allocator = allocator }; defer headers.deinit(); try headers.append("Authorization", auth_header); try headers.append("Content-Type", "application/json"); var req = try http_client.open(.POST, uri, .{ .headers = headers, .extra_headers = &.{}, }); defer req.deinit(); req.transfer_encoding = .{ .content_length = payload.len }; try req.send(); try req.writeAll(payload); try req.finish(); try req.wait(); if (req.response.status != .ok) { std.log.err("Exa API returned status: {}", .{req.response.status}); return error.ApiError; } const response_body = try req.reader().readAllAlloc(allocator, 5 * 1024 * 1024); return response_body; } fn streamCerebrasChat(writer: anytype, allocator: std.mem.Allocator, http_client: *std.http.Client, cerebras_key: []const u8, message: []const u8) !void { const escaped_message = try escapeJsonString(allocator, message); defer allocator.free(escaped_message); const payload = try std.fmt.allocPrint(allocator, "{{\"model\":\"gpt-oss-120b\",\"stream\":true,\"max_completion_tokens\":2048,\"messages\":[{{\"role\":\"system\",\"content\":\"Magyarul, tömören válaszolj.\"}},{{\"role\":\"user\",\"content\":\"{s}\"}}]}}", .{escaped_message} ); defer allocator.free(payload); try streamToCerebras(writer, allocator, http_client, cerebras_key, payload); } fn streamCerebrasDeepSearch(writer: anytype, allocator: std.mem.Allocator, http_client: *std.http.Client, cerebras_key: []const u8, query: []const u8, search_results: []const u8) !void { const escaped_query = try escapeJsonString(allocator, query); defer allocator.free(escaped_query); const escaped_results = try escapeJsonString(allocator, search_results); defer allocator.free(escaped_results); const payload = try std.fmt.allocPrint(allocator, "{{\"model\":\"gpt-oss-120b\",\"stream\":true,\"max_completion_tokens\":65536,\"messages\":[{{\"role\":\"system\",\"content\":\"Magyar ügynök vagy. Adj hosszú, tagolt, hivatkozott jelentést a megadott találatok alapján.\"}},{{\"role\":\"user\",\"content\":\"Kérdés: {s}\"}},{{\"role\":\"user\",\"content\":\"Találatok (JSON): {s}\"}}]}}", .{ escaped_query, escaped_results } ); defer allocator.free(payload); try streamToCerebras(writer, allocator, http_client, cerebras_key, payload); } fn streamToCerebras(writer: anytype, allocator: std.mem.Allocator, http_client: *std.http.Client, cerebras_key: []const u8, payload: []const u8) !void { const uri = try std.Uri.parse(CEREBRAS_URL); const auth_header = try std.fmt.allocPrint(allocator, "Bearer {s}", .{cerebras_key}); defer allocator.free(auth_header); var headers = std.http.Headers{ .allocator = allocator }; defer headers.deinit(); try headers.append("Authorization", auth_header); try headers.append("Content-Type", "application/json"); try headers.append("Accept", "text/event-stream"); var req = try http_client.open(.POST, uri, .{ .headers = headers, .extra_headers = &.{}, }); defer req.deinit(); req.transfer_encoding = .{ .content_length = payload.len }; try req.send(); try req.writeAll(payload); try req.finish(); try req.wait(); if (req.response.status != .ok) { std.log.err("Cerebras API returned status: {}", .{req.response.status}); const error_data = "data: {\"choices\":[{\"delta\":{\"content\":\"Hiba történt az AI válasz generálása során.\"}}]}\n\n"; try writer.writeAll(error_data); const done_data = "data: [DONE]\n\n"; try writer.writeAll(done_data); return; } var reader = req.reader(); var line_buffer: [2048]u8 = undefined; while (true) { if (reader.readUntilDelimiterOrEof(line_buffer[0..], '\n')) |maybe_line| { if (maybe_line) |line| { const trimmed = std.mem.trim(u8, line, "\r\n "); if (std.mem.startsWith(u8, trimmed, "data: ")) { try writer.print("{s}\n\n", .{trimmed}); // Check for [DONE] to exit if (std.mem.indexOf(u8, trimmed, "[DONE]") != null) { break; } } } else break; } else |_| break; } } Send back the complete code with all the fixes. Fix each of the listed errors one by one, making sure to actually correct them so that there are 0 errors remaining. Keep the original imports, since the files exist. Write out every single character; do not abbreviate anything. Fix every error. There must be exactly one file. Do not write anything else; just output the complete code, and it must not contain any comments. Never, under any circumstances, use simplified, substitute, dummy, simulated, or fake code. Write the entire file as complete, unabridged, production-ready code in a single code block. It must be 100% error-free, a complete, error-free file, and must be submitted as a downloadable file. These requirements are mandatory and must be strictly adhered to. If no list of errors is provided, you must find all the errors and fix them. If there were comments in the original code, delete them. And most importantly: YOU MUST NEVER SIMPLIFY!
Response not available
Response not available