firefly-compiler 0.5.39 → 0.5.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/.hintrc +4 -4
  2. package/.vscode/settings.json +4 -4
  3. package/bin/Release.ff +158 -157
  4. package/bin/firefly.mjs +1 -1
  5. package/compiler/Builder.ff +275 -275
  6. package/compiler/Compiler.ff +234 -234
  7. package/compiler/Dependencies.ff +186 -186
  8. package/compiler/DependencyLock.ff +17 -17
  9. package/compiler/JsEmitter.ff +1437 -1437
  10. package/compiler/LspHook.ff +202 -202
  11. package/compiler/ModuleCache.ff +178 -178
  12. package/compiler/Workspace.ff +88 -88
  13. package/core/.firefly/include/package.json +5 -5
  14. package/core/.firefly/package.ff +2 -2
  15. package/core/Any.ff +25 -25
  16. package/core/Array.ff +298 -298
  17. package/core/Atomic.ff +63 -63
  18. package/core/Box.ff +7 -7
  19. package/core/BrowserSystem.ff +40 -40
  20. package/core/BuildSystem.ff +156 -156
  21. package/core/Crypto.ff +94 -94
  22. package/core/Equal.ff +41 -41
  23. package/core/Error.ff +25 -25
  24. package/core/HttpClient.ff +142 -142
  25. package/core/Instant.ff +24 -24
  26. package/core/Js.ff +305 -305
  27. package/core/JsSystem.ff +135 -135
  28. package/core/Json.ff +423 -423
  29. package/core/List.ff +482 -482
  30. package/core/Lock.ff +108 -108
  31. package/core/NodeSystem.ff +198 -198
  32. package/core/Ordering.ff +160 -160
  33. package/core/Path.ff +377 -378
  34. package/core/Queue.ff +90 -90
  35. package/core/Random.ff +140 -140
  36. package/core/RbMap.ff +216 -216
  37. package/core/Show.ff +44 -44
  38. package/core/SourceLocation.ff +68 -68
  39. package/core/Task.ff +165 -165
  40. package/experimental/benchmarks/ListGrab.ff +23 -23
  41. package/experimental/benchmarks/ListGrab.java +55 -55
  42. package/experimental/benchmarks/Pyrotek45.ff +30 -30
  43. package/experimental/benchmarks/Pyrotek45.java +64 -64
  44. package/experimental/bidirectional/Bidi.ff +88 -88
  45. package/experimental/lines/Main.ff +40 -40
  46. package/experimental/random/Index.ff +53 -53
  47. package/experimental/random/Process.ff +120 -120
  48. package/experimental/random/RunLength.ff +65 -65
  49. package/experimental/random/Scrape.ff +51 -51
  50. package/experimental/random/Symbols.ff +73 -73
  51. package/experimental/random/Tensor.ff +52 -52
  52. package/experimental/random/Units.ff +36 -36
  53. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
  54. package/experimental/s3/S3TestPut.ff +16 -16
  55. package/experimental/tests/TestJson.ff +26 -26
  56. package/firefly.sh +0 -0
  57. package/fireflysite/.firefly/package.ff +4 -4
  58. package/fireflysite/CommunityOverview.ff +20 -20
  59. package/fireflysite/CountingButtonDemo.ff +58 -58
  60. package/fireflysite/DocumentParser.ff +325 -325
  61. package/fireflysite/ExamplesOverview.ff +40 -40
  62. package/fireflysite/FrontPage.ff +344 -344
  63. package/fireflysite/GettingStarted.ff +45 -45
  64. package/fireflysite/Guide.ff +456 -456
  65. package/fireflysite/Main.ff +163 -163
  66. package/fireflysite/MatchingPasswordsDemo.ff +82 -82
  67. package/fireflysite/PackagesOverview.ff +49 -49
  68. package/fireflysite/PostgresqlDemo.ff +34 -34
  69. package/fireflysite/ReferenceAll.ff +18 -18
  70. package/fireflysite/ReferenceIntroduction.ff +11 -11
  71. package/fireflysite/Styles.ff +567 -567
  72. package/fireflysite/Test.ff +121 -121
  73. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -209
  74. package/fireflysite/assets/markdown/reference/EmittedJavascript.md +65 -65
  75. package/fireflysite/assets/markdown/reference/Exceptions.md +101 -101
  76. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +364 -364
  77. package/fireflysite/assets/markdown/reference/JavascriptInterop.md +235 -235
  78. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -162
  79. package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -48
  80. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -224
  81. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -86
  82. package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -99
  83. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -100
  84. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -184
  85. package/fireflysite/assets/markdown/scratch/ControlFlow.md +136 -136
  86. package/fireflysite/assets/markdown/scratch/Toc.md +40 -40
  87. package/lsp/.firefly/package.ff +1 -1
  88. package/lsp/CompletionHandler.ff +827 -827
  89. package/lsp/Handler.ff +714 -714
  90. package/lsp/HoverHandler.ff +79 -79
  91. package/lsp/LanguageServer.ff +272 -272
  92. package/lsp/SignatureHelpHandler.ff +55 -55
  93. package/lsp/SymbolHandler.ff +181 -181
  94. package/lsp/TestReferences.ff +17 -17
  95. package/lsp/TestReferencesCase.ff +7 -7
  96. package/lsp/stderr.txt +1 -1
  97. package/lsp/stdout.txt +34 -34
  98. package/lux/.firefly/package.ff +1 -1
  99. package/lux/Css.ff +648 -648
  100. package/lux/CssTest.ff +48 -48
  101. package/lux/Lux.ff +608 -608
  102. package/lux/LuxEvent.ff +79 -79
  103. package/lux/Main.ff +123 -123
  104. package/lux/Main2.ff +143 -143
  105. package/lux/TestDry.ff +28 -28
  106. package/output/js/ff/compiler/Builder.mjs +36 -36
  107. package/output/js/ff/core/Path.mjs +0 -2
  108. package/package.json +1 -1
  109. package/rpc/.firefly/package.ff +1 -1
  110. package/rpc/Rpc.ff +70 -70
  111. package/s3/.firefly/package.ff +1 -1
  112. package/s3/S3.ff +92 -92
  113. package/vscode/LICENSE.txt +21 -21
  114. package/vscode/Prepublish.ff +15 -15
  115. package/vscode/README.md +16 -16
  116. package/vscode/client/package-lock.json +544 -544
  117. package/vscode/client/package.json +22 -22
  118. package/vscode/client/src/extension.ts +104 -104
  119. package/vscode/icons/firefly-icon.svg +10 -10
  120. package/vscode/language-configuration.json +61 -61
  121. package/vscode/package-lock.json +3623 -3623
  122. package/vscode/package.json +1 -1
  123. package/vscode/snippets.json +241 -241
  124. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  125. package/webserver/.firefly/include/package.json +5 -5
  126. package/webserver/.firefly/package.ff +2 -2
  127. package/webserver/WebServer.ff +647 -647
  128. package/websocket/.firefly/package.ff +1 -1
  129. package/websocket/WebSocket.ff +100 -100
package/lux/LuxEvent.ff CHANGED
@@ -1,79 +1,79 @@
1
- class LuxEvent(jsValue: JsValue)
2
-
3
- extend self: LuxEvent {
4
-
5
- preventDefault(): Unit {self.jsValue->preventDefault()}
6
-
7
- stopPropagation(): Unit {self.jsValue->stopPropagation()}
8
-
9
- target(): JsValue {self.jsValue->target}
10
-
11
- currentTarget(): JsValue {self.jsValue->currentTarget}
12
-
13
- relatedTarget(): JsValue {self.jsValue->relatedTarget}
14
-
15
- nativeEvent(): JsValue {self.jsValue}
16
-
17
- type(): String {self.jsValue->type?}
18
-
19
- altKey(): Bool {Js.binaryOperator("||", self.jsValue->altKey, False)?}
20
-
21
- ctrlKey(): Bool {Js.binaryOperator("||", self.jsValue->ctrlKey, False)?}
22
-
23
- shiftKey(): Bool {Js.binaryOperator("||", self.jsValue->shiftKey, False)?}
24
-
25
- metaKey(): Bool {Js.binaryOperator("||", self.jsValue->metaKey, False)?}
26
-
27
- button(): Int {Js.binaryOperator("||", self.jsValue->button, 0)?}
28
-
29
- primaryButton(): Bool {Js.unaryOperator("!!", Js.binaryOperator("&", self.jsValue->buttons, 1))?}
30
-
31
- secondaryButton(): Bool {Js.unaryOperator("!!", Js.binaryOperator("&", self.jsValue->buttons, 2))?}
32
-
33
- middleButton(): Bool {Js.unaryOperator("!!", Js.binaryOperator("&", self.jsValue->buttons, 4))?}
34
-
35
- clientX(): Float {Js.binaryOperator("||", self.jsValue->clientX, 0)?}
36
-
37
- clientY(): Float {Js.binaryOperator("||", self.jsValue->clientY, 0)?}
38
-
39
- movementX(): Float {Js.binaryOperator("||", self.jsValue->movementX, 0)?}
40
-
41
- movementY(): Float {Js.binaryOperator("||", self.jsValue->movementY, 0)?}
42
-
43
- offsetX(): Float {Js.binaryOperator("||", self.jsValue->offsetX, 0)?}
44
-
45
- offsetY(): Float {Js.binaryOperator("||", self.jsValue->offsetY, 0)?}
46
-
47
- pageX(): Float {Js.binaryOperator("||", self.jsValue->pageX, 0)?}
48
-
49
- pageY(): Float {Js.binaryOperator("||", self.jsValue->pageY, 0)?}
50
-
51
- screenX(): Float {Js.binaryOperator("||", self.jsValue->screenX, 0)?}
52
-
53
- screenY(): Float {Js.binaryOperator("||", self.jsValue->screenY, 0)?}
54
-
55
- key(): String {Js.binaryOperator("||", self.jsValue->key, "")?}
56
-
57
- code(): String {Js.binaryOperator("||", self.jsValue->code, "")?}
58
-
59
- repeat(): Bool {Js.unaryOperator("!!", self.jsValue->repeat)?}
60
-
61
- leftKeyLocation(): Bool {self.jsValue->location === 1}
62
-
63
- rightKeyLocation(): Bool {self.jsValue->location === 2}
64
-
65
- numpadKeyLocation(): Bool {self.jsValue->location === 3}
66
-
67
- isComposing(): Bool {Js.unaryOperator("!!", self.jsValue->isComposing)?}
68
-
69
- data(): String {Js.binaryOperator("||", self.jsValue->data, "")?}
70
-
71
- text(): String {"" + Js.binaryOperator("||", self.jsValue->target->value, "")?}
72
-
73
- inputType(): String {Js.binaryOperator("||", self.jsValue->inputType, "")?}
74
-
75
- dataTransfer(): JsValue {Js.binaryOperator("||", self.jsValue->dataTransfer, "")?}
76
-
77
- getTargetRanges(): JsValue {self.jsValue->getTargetRanges()}
78
-
79
- }
1
+ class LuxEvent(jsValue: JsValue)
2
+
3
+ extend self: LuxEvent {
4
+
5
+ preventDefault(): Unit {self.jsValue->preventDefault()}
6
+
7
+ stopPropagation(): Unit {self.jsValue->stopPropagation()}
8
+
9
+ target(): JsValue {self.jsValue->target}
10
+
11
+ currentTarget(): JsValue {self.jsValue->currentTarget}
12
+
13
+ relatedTarget(): JsValue {self.jsValue->relatedTarget}
14
+
15
+ nativeEvent(): JsValue {self.jsValue}
16
+
17
+ type(): String {self.jsValue->type?}
18
+
19
+ altKey(): Bool {Js.binaryOperator("||", self.jsValue->altKey, False)?}
20
+
21
+ ctrlKey(): Bool {Js.binaryOperator("||", self.jsValue->ctrlKey, False)?}
22
+
23
+ shiftKey(): Bool {Js.binaryOperator("||", self.jsValue->shiftKey, False)?}
24
+
25
+ metaKey(): Bool {Js.binaryOperator("||", self.jsValue->metaKey, False)?}
26
+
27
+ button(): Int {Js.binaryOperator("||", self.jsValue->button, 0)?}
28
+
29
+ primaryButton(): Bool {Js.unaryOperator("!!", Js.binaryOperator("&", self.jsValue->buttons, 1))?}
30
+
31
+ secondaryButton(): Bool {Js.unaryOperator("!!", Js.binaryOperator("&", self.jsValue->buttons, 2))?}
32
+
33
+ middleButton(): Bool {Js.unaryOperator("!!", Js.binaryOperator("&", self.jsValue->buttons, 4))?}
34
+
35
+ clientX(): Float {Js.binaryOperator("||", self.jsValue->clientX, 0)?}
36
+
37
+ clientY(): Float {Js.binaryOperator("||", self.jsValue->clientY, 0)?}
38
+
39
+ movementX(): Float {Js.binaryOperator("||", self.jsValue->movementX, 0)?}
40
+
41
+ movementY(): Float {Js.binaryOperator("||", self.jsValue->movementY, 0)?}
42
+
43
+ offsetX(): Float {Js.binaryOperator("||", self.jsValue->offsetX, 0)?}
44
+
45
+ offsetY(): Float {Js.binaryOperator("||", self.jsValue->offsetY, 0)?}
46
+
47
+ pageX(): Float {Js.binaryOperator("||", self.jsValue->pageX, 0)?}
48
+
49
+ pageY(): Float {Js.binaryOperator("||", self.jsValue->pageY, 0)?}
50
+
51
+ screenX(): Float {Js.binaryOperator("||", self.jsValue->screenX, 0)?}
52
+
53
+ screenY(): Float {Js.binaryOperator("||", self.jsValue->screenY, 0)?}
54
+
55
+ key(): String {Js.binaryOperator("||", self.jsValue->key, "")?}
56
+
57
+ code(): String {Js.binaryOperator("||", self.jsValue->code, "")?}
58
+
59
+ repeat(): Bool {Js.unaryOperator("!!", self.jsValue->repeat)?}
60
+
61
+ leftKeyLocation(): Bool {self.jsValue->location === 1}
62
+
63
+ rightKeyLocation(): Bool {self.jsValue->location === 2}
64
+
65
+ numpadKeyLocation(): Bool {self.jsValue->location === 3}
66
+
67
+ isComposing(): Bool {Js.unaryOperator("!!", self.jsValue->isComposing)?}
68
+
69
+ data(): String {Js.binaryOperator("||", self.jsValue->data, "")?}
70
+
71
+ text(): String {"" + Js.binaryOperator("||", self.jsValue->target->value, "")?}
72
+
73
+ inputType(): String {Js.binaryOperator("||", self.jsValue->inputType, "")?}
74
+
75
+ dataTransfer(): JsValue {Js.binaryOperator("||", self.jsValue->dataTransfer, "")?}
76
+
77
+ getTargetRanges(): JsValue {self.jsValue->getTargetRanges()}
78
+
79
+ }
package/lux/Main.ff CHANGED
@@ -1,123 +1,123 @@
1
- import HttpServer from ff:httpserver
2
-
3
- import Lux
4
- import LuxEvent
5
- import Css
6
-
7
- data ChatEntry(
8
- question: String
9
- answer: Option[String]
10
- )
11
-
12
- mainComponent(lux: Lux, http: HttpClient) {
13
- lux.useState([]): chat, setChat =>
14
- lux.useState(""): message, setMessage =>
15
- lux.div {
16
- lux.div {
17
- chat.each {questionComponent(lux, http, _)}
18
- }
19
- lux.form {
20
- lux.input {
21
- //.with("autofocus", "true")
22
- lux.setValue(message)
23
- lux.onInput {event => setMessage(event.text())}
24
- }
25
- lux.on("submit") {event =>
26
- event.preventDefault()
27
- setMessage("")
28
- setChat([...chat, message])
29
- }
30
- }
31
- }
32
- }
33
-
34
- questionCss = CssClass([Css.marginBottom("10px")], [], [])
35
-
36
- questionComponent(lux: Lux, http: HttpClient, question: String) {
37
- lux.div {
38
- lux.cssClass(questionCss)
39
- lux.div {lux.text("User: " + question)}
40
- lux.useLazy1(question): _ =>
41
- lux.useSuspense {lux.div {lux.text("Assistant typing...")}}: lux =>
42
- let answer = http.post("/chat", [], question.toBuffer()) {_.readText()}
43
- lux.div {lux.text("Assistant: " + answer)}
44
- }
45
- }
46
-
47
- browserMain(system: BrowserSystem) {
48
- Lux.renderById(system, "main") {lux => mainComponent(lux, system.httpClient())}
49
- }
50
-
51
- nodeMain(system: NodeSystem) {
52
- let openAiKey = system.arguments().first()
53
- HttpServer.listen(system, "localhost", 8080) {request, response =>
54
- if(request.path() == "/") {
55
- response.setHeader("Content-Type", ["text/html; charset=UTF-8"])
56
- response.writeText("<!doctype html>")
57
- response.writeText("<div id='main'></div>")
58
- response.writeText("<script type='module' src='/js/script/script/Main.mjs'></script>")
59
- } elseIf {request.path().startsWith("/js/") && !request.path().contains("..")} {
60
- response.setHeader("Content-Type", ["text/javascript; charset=UTF-8"])
61
- response.writeText(system.assets().readText(request.path()))
62
- } elseIf {request.path() == "/chat"} {
63
- let question = request.readText()
64
- response.setHeader("Content-Type", ["text/plain; charset=UTF-8"])
65
- openAiKey.{
66
- | None =>
67
- system.mainTask().sleep(Duration(question.size().toFloat()))
68
- response.writeText("Hi! You need to give an OpenAI secret key at the command line.")
69
- | Some(key) =>
70
- let chatJson = encodeChat(question)
71
- let answer = fetchAnswer(system.httpClient(), key, chatJson)
72
- response.writeText(answer)
73
- }
74
- } else {
75
- response.writeStatus(404, Some("Not found"))
76
- }
77
- }
78
- }
79
-
80
- fetchAnswer(httpClient: HttpClient, key: String, question: Json): String {
81
- let json = httpClient.post(
82
- url = "https://api.openai.com/v1/chat/completions"
83
- headers = [
84
- Pair("Authorization", "Bearer " + key)
85
- Pair("Content-Type", "application/json")
86
- ]
87
- body = question.write().toBuffer()
88
- ) {_.readJson()}
89
- json.field("choices").index(0).field("message").field("content").grabString()
90
- }
91
-
92
- encodeChat(question: String): Json {
93
- let systemJson = Json.object()
94
- .with("role", "system")
95
- .with("content", "You are a helpful assistant.")
96
- let questionJson = Json.object()
97
- .with("role", "user")
98
- .with("content", question)
99
- Json.object()
100
- .with("model", "gpt-3.5-turbo")
101
- .with("messages", [systemJson, questionJson])
102
- }
103
-
104
-
105
- /*
106
- let
107
- encodeMessage role content =
108
- E.object [ ("role", E.string role), ("content", E.string content) ]
109
- encodeEntry question maybeAnswer = case maybeAnswer of
110
- Nothing -> [ encodeMessage "user" question ]
111
- Just answer -> [ encodeMessage "user" question, encodeMessage "assistant" answer ]
112
- encodedMessages = encodeMessage "system" "You are a helpful assistant."
113
- :: List.concatMap (\entry -> encodeEntry entry.question entry.answer) chat
114
- in E.object
115
- [ ("model", E.string "gpt-3.5-turbo")
116
- , ("messages", E.list (\x -> x) encodedMessages)
117
- ]
118
- */
119
- buildMain(system: BuildSystem) {
120
- let browser = system.compileForBrowser("Main.ff")
121
- let assets = AssetSystem.create().addAssets("/js", browser.assets())
122
- system.setAssets(assets)
123
- }
1
+ import HttpServer from ff:httpserver
2
+
3
+ import Lux
4
+ import LuxEvent
5
+ import Css
6
+
7
+ data ChatEntry(
8
+ question: String
9
+ answer: Option[String]
10
+ )
11
+
12
+ mainComponent(lux: Lux, http: HttpClient) {
13
+ lux.useState([]): chat, setChat =>
14
+ lux.useState(""): message, setMessage =>
15
+ lux.div {
16
+ lux.div {
17
+ chat.each {questionComponent(lux, http, _)}
18
+ }
19
+ lux.form {
20
+ lux.input {
21
+ //.with("autofocus", "true")
22
+ lux.setValue(message)
23
+ lux.onInput {event => setMessage(event.text())}
24
+ }
25
+ lux.on("submit") {event =>
26
+ event.preventDefault()
27
+ setMessage("")
28
+ setChat([...chat, message])
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ questionCss = CssClass([Css.marginBottom("10px")], [], [])
35
+
36
+ questionComponent(lux: Lux, http: HttpClient, question: String) {
37
+ lux.div {
38
+ lux.cssClass(questionCss)
39
+ lux.div {lux.text("User: " + question)}
40
+ lux.useLazy1(question): _ =>
41
+ lux.useSuspense {lux.div {lux.text("Assistant typing...")}}: lux =>
42
+ let answer = http.post("/chat", [], question.toBuffer()) {_.readText()}
43
+ lux.div {lux.text("Assistant: " + answer)}
44
+ }
45
+ }
46
+
47
+ browserMain(system: BrowserSystem) {
48
+ Lux.renderById(system, "main") {lux => mainComponent(lux, system.httpClient())}
49
+ }
50
+
51
+ nodeMain(system: NodeSystem) {
52
+ let openAiKey = system.arguments().first()
53
+ HttpServer.listen(system, "localhost", 8080) {request, response =>
54
+ if(request.path() == "/") {
55
+ response.setHeader("Content-Type", ["text/html; charset=UTF-8"])
56
+ response.writeText("<!doctype html>")
57
+ response.writeText("<div id='main'></div>")
58
+ response.writeText("<script type='module' src='/js/script/script/Main.mjs'></script>")
59
+ } elseIf {request.path().startsWith("/js/") && !request.path().contains("..")} {
60
+ response.setHeader("Content-Type", ["text/javascript; charset=UTF-8"])
61
+ response.writeText(system.assets().readText(request.path()))
62
+ } elseIf {request.path() == "/chat"} {
63
+ let question = request.readText()
64
+ response.setHeader("Content-Type", ["text/plain; charset=UTF-8"])
65
+ openAiKey.{
66
+ | None =>
67
+ system.mainTask().sleep(Duration(question.size().toFloat()))
68
+ response.writeText("Hi! You need to give an OpenAI secret key at the command line.")
69
+ | Some(key) =>
70
+ let chatJson = encodeChat(question)
71
+ let answer = fetchAnswer(system.httpClient(), key, chatJson)
72
+ response.writeText(answer)
73
+ }
74
+ } else {
75
+ response.writeStatus(404, Some("Not found"))
76
+ }
77
+ }
78
+ }
79
+
80
+ fetchAnswer(httpClient: HttpClient, key: String, question: Json): String {
81
+ let json = httpClient.post(
82
+ url = "https://api.openai.com/v1/chat/completions"
83
+ headers = [
84
+ Pair("Authorization", "Bearer " + key)
85
+ Pair("Content-Type", "application/json")
86
+ ]
87
+ body = question.write().toBuffer()
88
+ ) {_.readJson()}
89
+ json.field("choices").index(0).field("message").field("content").grabString()
90
+ }
91
+
92
+ encodeChat(question: String): Json {
93
+ let systemJson = Json.object()
94
+ .with("role", "system")
95
+ .with("content", "You are a helpful assistant.")
96
+ let questionJson = Json.object()
97
+ .with("role", "user")
98
+ .with("content", question)
99
+ Json.object()
100
+ .with("model", "gpt-3.5-turbo")
101
+ .with("messages", [systemJson, questionJson])
102
+ }
103
+
104
+
105
+ /*
106
+ let
107
+ encodeMessage role content =
108
+ E.object [ ("role", E.string role), ("content", E.string content) ]
109
+ encodeEntry question maybeAnswer = case maybeAnswer of
110
+ Nothing -> [ encodeMessage "user" question ]
111
+ Just answer -> [ encodeMessage "user" question, encodeMessage "assistant" answer ]
112
+ encodedMessages = encodeMessage "system" "You are a helpful assistant."
113
+ :: List.concatMap (\entry -> encodeEntry entry.question entry.answer) chat
114
+ in E.object
115
+ [ ("model", E.string "gpt-3.5-turbo")
116
+ , ("messages", E.list (\x -> x) encodedMessages)
117
+ ]
118
+ */
119
+ buildMain(system: BuildSystem) {
120
+ let browser = system.compileForBrowser("Main.ff")
121
+ let assets = AssetSystem.create().addAssets("/js", browser.assets())
122
+ system.setAssets(assets)
123
+ }