14
14
white-space : pre-line ;
15
15
padding : 0.25em ;
16
16
min-height : 5em ;
17
- height : 5em ;
18
17
flex-grow : 1 ;
19
18
flex-shrink : 1 ;
19
+ }
20
+
21
+ textarea {
20
22
resize : vertical ;
23
+ height : 8em ;
21
24
}
22
25
23
- input [ type = " password " ] {
26
+ input {
24
27
border : 1px solid var (--fg-color );
25
28
padding : 0.25em ;
26
29
}
41
44
justify-content : flex-end ;
42
45
align-items : center ;
43
46
gap : 1em ;
44
- margin-top : -0.75em ;
45
47
}
46
48
</style >
47
49
53
55
// May appear unused, but actually used during evals
54
56
import { llmToolFunctions , llmModels } from " ./llm.svelte.js" ;
55
57
import { functions as formulaFunctions } from " ./formula-functions.svelte" ;
58
+ import CodeEditor from " ./CodeEditor.svelte" ;
56
59
57
60
let { globals } = $props ();
58
61
let response = $state ();
@@ -86,7 +89,6 @@ Available spreadsheets:
86
89
).join('\\ n')
87
90
}
88
91
` );
89
- let llmCode = $state (" " );
90
92
91
93
// Need to call eval in a separate function from derived.by to ensure globals,
92
94
// functions, and prompt are in-scope
@@ -103,14 +105,24 @@ Available spreadsheets:
103
105
});
104
106
105
107
async function submit() {
106
- response = llmModels[modelName].request(prompt, systemPrompt, {
107
- apiKey: llmModels[modelName].apiKey,
108
- });
109
- // TODO: Fix race condition if the button is pushed multiple times
110
- llmCode = await response;
108
+ response = llmModels[modelName]
109
+ .request(prompt, systemPrompt)
110
+ .then((parts) =>
111
+ parts.map((part) => {
112
+ if (part.startsWith("` ` ` " ) && part.endsWith(" ` ` ` ")) {
113
+ return {
114
+ code: part
115
+ .replaceAll(/(^` ` ` ` *( *javascript *)?\n )|(\n ` ` ` ` *$)/g, "")
116
+ .trim(),
117
+ };
118
+ } else {
119
+ return part;
120
+ }
121
+ }),
122
+ );
111
123
}
112
124
113
- function execute() {
125
+ function execute(llmCode ) {
114
126
llmToolFunctions.globals = globals;
115
127
eval(
116
128
llmCode +
@@ -143,6 +155,10 @@ Available spreadsheets:
143
155
<!-- <Button>Save</Button> -->
144
156
</div>
145
157
</label>
158
+ <label>
159
+ Model
160
+ <input type="text" bind:value={llmModels[modelName].model} />
161
+ </label>
146
162
</Details>
147
163
148
164
<Details>
@@ -165,18 +181,35 @@ Available spreadsheets:
165
181
placeholder="Make a simple budget spreadsheet template"
166
182
bind:value={prompt}
167
183
></textarea>
184
+ <div class="buttons" style="margin-top: 0.5em;">
185
+ <Button onclick={submit}>Submit</Button>
186
+ </div>
168
187
</div>
169
188
170
- <div class="buttons"><Button onclick={submit}>Submit</Button></div>
171
-
172
189
{#if response}
173
190
<h1>LLM Response</h1>
174
191
{#await response}
175
192
<p>Loading...</p>
176
- {:then}
177
- <textarea bind:value={llmCode} style:min-height="10em" style:flex-grow="2"
178
- ></textarea>
179
- <div class="buttons"><Button onclick={execute}>Execute</Button></div>
193
+ {:then r}
194
+ <div style="gap: 0.25em;">
195
+ {#each r as part, i}
196
+ {#if part.code}
197
+ <Details open>
198
+ {#snippet summary()}Code{/snippet}
199
+ <CodeEditor bind:code={r[i].code} style="min-height: 10em"
200
+ ></CodeEditor>
201
+ <div class="buttons">
202
+ <Button onclick={() => execute(r[i].code)}>Execute</Button>
203
+ </div>
204
+ </Details>
205
+ {:else}
206
+ <Details open>
207
+ {#snippet summary()}Text{/snippet}
208
+ <pre class="message">{part}</pre>
209
+ </Details>
210
+ {/if}
211
+ {/each}
212
+ </div>
180
213
<!-- TODO: Add error display if evaluated code throws -->
181
214
{:catch e}
182
215
<p>Error: {e?.message ?? e}</p>
0 commit comments