1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5import gleam/option.{type Option, None, Some}
6import gleam/string
7
8/// The system prompt that establishes garble's role as a text transformer.
9const system_prompt = "You are a text transformation tool. Transform the text in <raw> according to the user's directions.
10
11<rules>
12- Follow the user's transformation directions precisely
13- If no directions are provided, return the input unchanged
14- Output ONLY the transformed text—no explanations, commentary, or metadata
15- Never reference the original text or the fact that a transformation occurred
16- Wrap your entire output in a fenced code block (```)
17</rules>"
18
19/// Returns the system prompt.
20pub fn system() -> String {
21 system_prompt
22}
23
24/// Build the user message with raw input sandwiched between direction references.
25pub fn build_user_message(raw_input: String, directions: String) -> String {
26 let directions_block = case string.trim(directions) {
27 "" -> ""
28 trimmed -> "\n\n<directions>\n" <> trimmed <> "\n</directions>"
29 }
30
31 "<raw>\n"
32 <> raw_input
33 <> "\n</raw>"
34 <> directions_block
35 <> "\n\nTransform the text in <raw> according to the directions above."
36}
37
38/// Extract content from within a fenced code block.
39/// Returns the content inside the first code block found, or the full text if none.
40pub fn extract_code_block(text: String) -> String {
41 case find_code_block(text) {
42 Some(content) -> content
43 None -> text
44 }
45}
46
47fn find_code_block(text: String) -> Option(String) {
48 case string.split_once(text, "```") {
49 Error(_) -> None
50 Ok(#(_before, after_open)) -> {
51 // Skip the language tag (everything until first newline)
52 let content_start = case string.split_once(after_open, "\n") {
53 Ok(#(_lang, rest)) -> rest
54 Error(_) -> after_open
55 }
56 case string.split_once(content_start, "```") {
57 Ok(#(content, _after_close)) -> Some(string.trim(content))
58 Error(_) -> None
59 }
60 }
61 }
62}