147 lines
3.9 KiB
JavaScript
147 lines
3.9 KiB
JavaScript
|
|
#!/usr/local/bin/wren
|
||
|
|
|
||
|
|
import "pathlib" for Path
|
||
|
|
import "http" for Http
|
||
|
|
import "json" for Json
|
||
|
|
import "env" for Environment
|
||
|
|
import "argparse" for ArgumentParser
|
||
|
|
import "os" for Process
|
||
|
|
|
||
|
|
class SourceCodeGenerator {
|
||
|
|
static VERSION { "1.0" }
|
||
|
|
static DEFAULT_MODEL { "anthropic/claude-haiku-4.5" }
|
||
|
|
static API_ENDPOINT { "https://openrouter.ai/api/v1/chat/completions" }
|
||
|
|
static TUTORIAL_PATH { "apps/minitut.md" }
|
||
|
|
|
||
|
|
static DEFAULT_PROMPT {
|
||
|
|
"A small but useful application that combines several modules / libraries that is plug and play to use! Small description on top commenten what the application is and what it does and where it can be used for."
|
||
|
|
}
|
||
|
|
|
||
|
|
static run() {
|
||
|
|
System.print("// wren source code generator v%(this.VERSION)")
|
||
|
|
|
||
|
|
var startTime = System.clock
|
||
|
|
var args = parseArguments()
|
||
|
|
var apiKey = getApiKey()
|
||
|
|
var tutorial = loadTutorial()
|
||
|
|
var messages = buildMessages(tutorial, args["prompt"])
|
||
|
|
var sourceCode = generateCode(apiKey, messages)
|
||
|
|
|
||
|
|
printResults(startTime, sourceCode)
|
||
|
|
saveOutput(args["output"], sourceCode)
|
||
|
|
}
|
||
|
|
|
||
|
|
static parseArguments() {
|
||
|
|
var parser = ArgumentParser.new()
|
||
|
|
parser.addArgument("prompt", {"default": this.DEFAULT_PROMPT})
|
||
|
|
parser.addArgument("-o", {"long": "--output", "default": ""})
|
||
|
|
return parser.parseArgs()
|
||
|
|
}
|
||
|
|
|
||
|
|
static getApiKey() {
|
||
|
|
var apiKey = Environment.get("OPENROUTER_API_KEY")
|
||
|
|
if (apiKey == null || apiKey.count == 0) {
|
||
|
|
System.print("Error: OPENROUTER_API_KEY environment variable not set")
|
||
|
|
Fiber.abort("Missing API key")
|
||
|
|
}
|
||
|
|
return apiKey
|
||
|
|
}
|
||
|
|
|
||
|
|
static loadTutorial() {
|
||
|
|
return Path.new(this.TUTORIAL_PATH).readText()
|
||
|
|
}
|
||
|
|
|
||
|
|
static buildMessages(tutorial, userPrompt) {
|
||
|
|
var messages = []
|
||
|
|
messages.add({
|
||
|
|
"role": "system",
|
||
|
|
"content": "You are an application generator that will produce wren source code exclusively as described below:\n" + tutorial
|
||
|
|
})
|
||
|
|
messages.add({
|
||
|
|
"role": "user",
|
||
|
|
"content": "Please generate source code based on everything what i say from now on."
|
||
|
|
})
|
||
|
|
messages.add({
|
||
|
|
"role": "assistant",
|
||
|
|
"content": "I will respond in literally valid JSON only in this format: {\"source_code\":\"<the source code>\"} without any markup or markdown formatting."
|
||
|
|
})
|
||
|
|
messages.add({
|
||
|
|
"role": "user",
|
||
|
|
"content": userPrompt
|
||
|
|
})
|
||
|
|
return messages
|
||
|
|
}
|
||
|
|
|
||
|
|
static generateCode(apiKey, messages) {
|
||
|
|
var requestBody = {
|
||
|
|
"model": "%(this.DEFAULT_MODEL)",
|
||
|
|
"messages": messages
|
||
|
|
}
|
||
|
|
|
||
|
|
var headers = {
|
||
|
|
"Authorization": "Bearer " + apiKey,
|
||
|
|
"Content-Type": "application/json"
|
||
|
|
}
|
||
|
|
|
||
|
|
var response = Http.post(this.API_ENDPOINT, requestBody, headers)
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
System.print("Error: %(response.body)")
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
return extractSourceCode(response.body)
|
||
|
|
}
|
||
|
|
|
||
|
|
static extractSourceCode(responseBody) {
|
||
|
|
var data = Json.parse(responseBody)
|
||
|
|
|
||
|
|
if (data == null || data["choices"] == null || data["choices"].count == 0) {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
var message = data["choices"][0]["message"]
|
||
|
|
if (message == null || message["content"] == null) {
|
||
|
|
return ""
|
||
|
|
}
|
||
|
|
|
||
|
|
var text = message["content"]
|
||
|
|
text = stripMarkdownWrapper(text)
|
||
|
|
text = extractFromJson(text)
|
||
|
|
|
||
|
|
return text
|
||
|
|
}
|
||
|
|
|
||
|
|
static stripMarkdownWrapper(text) {
|
||
|
|
if (text.startsWith("```")) {
|
||
|
|
return text[7..-4].trim()
|
||
|
|
}
|
||
|
|
return text
|
||
|
|
}
|
||
|
|
|
||
|
|
static extractFromJson(text) {
|
||
|
|
if (text.startsWith("{")) {
|
||
|
|
return Json.parse(text)["source_code"]
|
||
|
|
}
|
||
|
|
return text
|
||
|
|
}
|
||
|
|
|
||
|
|
static printResults(startTime, output) {
|
||
|
|
var elapsedTime = System.clock - startTime
|
||
|
|
System.print("// Generation time: %(elapsedTime)")
|
||
|
|
System.print("")
|
||
|
|
System.print(output)
|
||
|
|
}
|
||
|
|
|
||
|
|
static saveOutput(outputPath, content) {
|
||
|
|
if (!outputPath.isEmpty) {
|
||
|
|
Path.new(outputPath).writeText(content)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
System.print(SourceCodeGenerator.DEFAULT_MODEL)
|
||
|
|
|
||
|
|
SourceCodeGenerator.run()
|
||
|
|
|