pixelass commited on
Commit
9d1931d
•
1 Parent(s): e5ae926

feat: stricter prompt

Browse files

adds reloading and several performance tweaks
fixes several bugs with rendering issues

public/js/utils.js CHANGED
@@ -50,17 +50,20 @@ function answer(window_, channel, targetOrigin = "*") {
50
  }
51
 
52
  function handleTemplate(template) {
53
- for (let i = 1; i < 100_000_000; i++) {
54
  window.clearInterval(i);
55
  window.cancelAnimationFrame(i);
56
  window.clearTimeout(i);
57
  }
58
 
59
- Function("Template", `${template};`)();
 
 
 
 
60
  }
61
 
62
  subscribe("fail4", event => {
63
- console.log("GUEST", event);
64
  const { action } = event.data;
65
  switch (action.type) {
66
  case "call":
@@ -70,7 +73,6 @@ subscribe("fail4", event => {
70
  handleTemplate(action.payload.template);
71
  break;
72
  case "broadcast":
73
- console.log("broadcast", action.payload.template);
74
  ctx.clearRect(0, 0, canvas.width, canvas.height);
75
  handleTemplate(action.payload.template);
76
  break;
 
50
  }
51
 
52
  function handleTemplate(template) {
53
+ for (let i = 1; i < 1_000; i++) {
54
  window.clearInterval(i);
55
  window.cancelAnimationFrame(i);
56
  window.clearTimeout(i);
57
  }
58
 
59
+ try {
60
+ Function("Template", `${template};`)();
61
+ } catch (error) {
62
+ console.log(error);
63
+ }
64
  }
65
 
66
  subscribe("fail4", event => {
 
67
  const { action } = event.data;
68
  switch (action.type) {
69
  case "call":
 
73
  handleTemplate(action.payload.template);
74
  break;
75
  case "broadcast":
 
76
  ctx.clearRect(0, 0, canvas.width, canvas.height);
77
  handleTemplate(action.payload.template);
78
  break;
src/pages/_app.tsx CHANGED
@@ -1,7 +1,6 @@
1
  import Head from "next/head";
2
  import { AppProps } from "next/app";
3
  import { ThemeProvider } from "@mui/material/styles";
4
- import CssBaseline from "@mui/material/CssBaseline";
5
  import { CacheProvider, EmotionCache } from "@emotion/react";
6
  import theme from "@/lib/theme";
7
  import createEmotionCache from "@/lib/createEmotionCache";
@@ -22,7 +21,6 @@ export default function MyApp(props: MyAppProps) {
22
  </Head>
23
  <ThemeProvider theme={theme}>
24
  {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
25
- <CssBaseline />
26
  <Component {...pageProps} />
27
  </ThemeProvider>
28
  </CacheProvider>
 
1
  import Head from "next/head";
2
  import { AppProps } from "next/app";
3
  import { ThemeProvider } from "@mui/material/styles";
 
4
  import { CacheProvider, EmotionCache } from "@emotion/react";
5
  import theme from "@/lib/theme";
6
  import createEmotionCache from "@/lib/createEmotionCache";
 
21
  </Head>
22
  <ThemeProvider theme={theme}>
23
  {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
 
24
  <Component {...pageProps} />
25
  </ThemeProvider>
26
  </CacheProvider>
src/pages/index.tsx CHANGED
@@ -1,6 +1,5 @@
1
  import { useEffect, useRef, useState } from "react";
2
 
3
- import Head from "next/head";
4
  import axios from "axios";
5
  import CheckIcon from "@mui/icons-material/Check";
6
  import ClearIcon from "@mui/icons-material/Clear";
@@ -31,12 +30,20 @@ import ListItemIcon from "@mui/material/ListItemIcon";
31
  import ListItemButton from "@mui/material/ListItemButton";
32
  import ListItemText from "@mui/material/ListItemText";
33
  import { useHost } from "esdeka/react";
 
 
 
34
 
35
  const base = {
36
- default: `/** 1.Base Script */
37
- const canvas=document.querySelector('canvas');
38
- const ctx=canvas.getContext('2d');
39
- `,
 
 
 
 
 
40
  };
41
 
42
  const fontMono = Fira_Code({
@@ -56,6 +63,7 @@ export default function Home() {
56
  },
57
  ]);
58
  const [loading, setLoading] = useState(false);
 
59
 
60
  const { broadcast, call, subscribe } = useHost(ref, "fail4");
61
 
@@ -64,6 +72,7 @@ export default function Home() {
64
 
65
  // Send a connection request
66
  useEffect(() => {
 
67
  if (connection.current || tries <= 0) {
68
  return () => {
69
  /* Consistency */
@@ -71,24 +80,29 @@ export default function Home() {
71
  }
72
 
73
  const timeout = setTimeout(() => {
74
- call({ template: "console.log('it works')" });
75
- setTries(tries - 1);
76
- }, 200);
77
 
78
- call({ template: "console.log('it works')" });
 
79
 
80
  return () => {
81
  clearTimeout(timeout);
82
  };
83
- }, [call, tries]);
84
 
85
  useEffect(() => {
86
- if (!connection.current) {
87
  const unsubscribe = subscribe(event => {
88
  const { action } = event.data;
89
  switch (action.type) {
90
  case "answer":
91
  connection.current = true;
 
 
 
 
92
  break;
93
  default:
94
  break;
@@ -101,7 +115,7 @@ export default function Home() {
101
  return () => {
102
  /* Consistency */
103
  };
104
- }, [subscribe]);
105
 
106
  // Broadcast store to guest
107
  useEffect(() => {
@@ -125,211 +139,244 @@ export default function Home() {
125
 
126
  const current = answers.find(({ id }) => id === activeId);
127
 
 
 
 
 
 
 
 
 
 
128
  return (
129
- <Stack
130
- sx={{
131
- ...fontMono.style,
132
- flexDirection: "row",
133
- height: "100%",
134
- }}
135
- >
136
- <Head>
137
- <style>{`html,body,#__next{margin:0;height:100%;overflow:hidden}`}</style>
138
- </Head>
139
- <Stack sx={{ width: "50%", flex: 1, gap: 2 }}>
140
- <Box
141
- component="form"
142
- onSubmit={async event => {
143
- event.preventDefault();
144
- const formData = new FormData(event.target as HTMLFormElement);
145
- const formObject = Object.fromEntries(formData);
146
- try {
147
- setLoading(true);
148
- const { data } = await axios.post("/api/gpt", formObject);
149
- const answer = data;
150
- setAnswers([answer, ...answers]);
151
- setRunningId(answer.id);
152
- } catch (error) {
153
- console.error(error);
154
- } finally {
155
- setLoading(false);
156
- }
157
- }}
158
- >
159
- <AppBar position="static" elevation={0}>
160
- <Toolbar>
161
- <IconButton
162
- type="submit"
163
- edge="start"
164
- color="inherit"
165
- aria-label={loading ? "Loading" : "Run"}
166
- disabled={loading}
167
- >
168
- {loading ? <HourglassTopIcon /> : <PlayArrowIcon />}
169
- </IconButton>
170
- <Typography sx={{ flex: 1 }}>
171
- {current?.task} - {current?.id ?? ""}
172
- </Typography>
173
- <IconButton
174
- edge="end"
175
- color="inherit"
176
- aria-label="Clear Prompt"
177
- onClick={async () => {
178
- broadcast({ template: base.default });
179
 
180
- //await axios.post("/api/run", {
181
- // content:
182
- // base.default,
183
- //});
184
- setActiveId("1");
185
- setTemplate(base.default);
186
- }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  >
188
- <ClearIcon />
189
- </IconButton>
190
- </Toolbar>
191
- </AppBar>
192
- <Paper variant="outlined" sx={{ p: 0 }}>
193
- <Stack sx={{ p: 2, gap: 2 }}>
194
- <Typography>Based on: {current?.task ?? "Base Script"}</Typography>
195
- <TextField
196
- multiline
197
- fullWidth
198
- id="prompt"
199
- name="prompt"
200
- label="Prompt"
201
- placeholder="add a red box"
202
- maxRows={6}
203
- InputProps={{
204
- style: fontMono.style,
205
- }}
206
- />
207
- <TextField
208
- multiline
209
- fullWidth
210
- id="negativePrompt"
211
- name="negativePrompt"
212
- label="Negative Prompt"
213
- placeholder="images, audio files"
214
- maxRows={6}
215
- InputProps={{
216
- style: fontMono.style,
217
- }}
218
- />
219
- </Stack>
220
- </Paper>
221
- <Accordion>
222
- <AccordionSummary
223
- expandIcon={<ExpandMoreIcon />}
224
- aria-controls="panel1a-content"
225
- id="panel1a-header"
226
- >
227
- <Typography>Options</Typography>
228
- </AccordionSummary>
229
- <AccordionDetails>
230
- <TextField
231
- multiline
232
- fullWidth
233
- id="template"
234
- name="template"
235
- label="Template"
236
- placeholder={base.default}
237
- maxRows={6}
238
- value={template}
239
- InputProps={{
240
- style: { ...fontMono.style },
241
- }}
242
- onChange={event => {
243
- setTemplate(event.target.value);
244
- }}
245
- />
246
- </AccordionDetails>
247
- </Accordion>
248
- </Box>
249
 
250
- <List sx={{ flex: 1, overflow: "auto" }}>
251
- {answers.map(answer => {
252
- return (
253
- <ListItem
254
- key={answer.id}
255
- secondaryAction={
256
- <Stack sx={{ flexDirection: "row", gap: 1 }}>
257
- {answer.id === "1" ? undefined : (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  <IconButton
259
  edge="end"
260
- aria-label="Delete"
261
  onClick={() => {
262
- setAnswers(
263
- answers.filter(({ id }) => id !== answer.id)
264
- );
265
  }}
266
  >
267
- <DeleteForeverIcon />
 
 
 
 
268
  </IconButton>
269
- )}
270
- <IconButton
271
- edge="end"
272
- aria-label="Show"
273
- onClick={() => {
274
- setRunningId(answer.id);
275
- }}
276
- >
277
- {runningId === answer.id ? (
278
- <VisibilityIcon />
 
 
 
 
 
 
279
  ) : (
280
- <VisibilityOffIcon />
281
  )}
282
- </IconButton>
283
- </Stack>
284
- }
285
- disablePadding
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  >
287
- <ListItemButton
288
- dense
289
- selected={activeId === answer.id}
290
- role={undefined}
291
- onClick={() => {
292
- setActiveId(answer.id);
293
- setTemplate(answer.content);
294
- }}
295
- >
296
- <ListItemIcon>
297
- {activeId === answer.id ? (
298
- <CheckIcon />
299
- ) : (
300
- <ContentCopyIcon />
301
- )}
302
- </ListItemIcon>
303
- <ListItemText primary={`${answer.task} - ${answer.id}`} />
304
- </ListItemButton>
305
- </ListItem>
306
- );
307
- })}
308
- </List>
309
- </Stack>
310
- <Stack sx={{ flex: 1, width: "50%" }}>
311
- <AppBar position="static" elevation={0}>
312
- <Toolbar>
313
- <IconButton
314
- color="inherit"
315
- aria-label="Reload"
316
- onClick={() => {
317
- if (ref.current) {
318
- ref.current.src = `//localhost:8080?${nanoid()}`;
319
- }
320
  }}
321
  >
322
- <ReplayIcon />
323
- </IconButton>
324
- </Toolbar>
325
- </AppBar>
326
- <Box
327
- ref={ref}
328
- component="iframe"
329
- sx={{ width: "100%", flex: 1, m: 0, border: 0 }}
330
- src="/live"
331
- />
 
 
 
 
 
 
 
332
  </Stack>
333
- </Stack>
334
  );
335
  }
 
1
  import { useEffect, useRef, useState } from "react";
2
 
 
3
  import axios from "axios";
4
  import CheckIcon from "@mui/icons-material/Check";
5
  import ClearIcon from "@mui/icons-material/Clear";
 
30
  import ListItemButton from "@mui/material/ListItemButton";
31
  import ListItemText from "@mui/material/ListItemText";
32
  import { useHost } from "esdeka/react";
33
+ import CircularProgress from "@mui/material/CircularProgress";
34
+ import { miniPrompt } from "@/services/api";
35
+ import CssBaseline from "@mui/material/CssBaseline";
36
 
37
  const base = {
38
+ default: miniPrompt`const canvas = document.querySelector('canvas');
39
+ const ctx = canvas.getContext('2d');
40
+ /*60FPS draw cycle*/
41
+ function draw(){
42
+ const FPS = 60;
43
+ setTimeout(requestAnimationFrame(draw),1000/FPS)
44
+ }
45
+ draw();
46
+ `,
47
  };
48
 
49
  const fontMono = Fira_Code({
 
63
  },
64
  ]);
65
  const [loading, setLoading] = useState(false);
66
+ const [loadingLive, setLoadingLive] = useState(true);
67
 
68
  const { broadcast, call, subscribe } = useHost(ref, "fail4");
69
 
 
72
 
73
  // Send a connection request
74
  useEffect(() => {
75
+ const current = answers.find(({ id }) => id === runningId);
76
  if (connection.current || tries <= 0) {
77
  return () => {
78
  /* Consistency */
 
80
  }
81
 
82
  const timeout = setTimeout(() => {
83
+ if (current) {
84
+ call({ template: current.content });
85
+ }
86
 
87
+ setTries(tries - 1);
88
+ }, 1_000);
89
 
90
  return () => {
91
  clearTimeout(timeout);
92
  };
93
+ }, [call, tries, answers, runningId]);
94
 
95
  useEffect(() => {
96
+ if (!connection.current && loadingLive) {
97
  const unsubscribe = subscribe(event => {
98
  const { action } = event.data;
99
  switch (action.type) {
100
  case "answer":
101
  connection.current = true;
102
+ setTimeout(() => {
103
+ setLoadingLive(false);
104
+ }, 1_500);
105
+ console.log("connected");
106
  break;
107
  default:
108
  break;
 
115
  return () => {
116
  /* Consistency */
117
  };
118
+ }, [subscribe, loadingLive]);
119
 
120
  // Broadcast store to guest
121
  useEffect(() => {
 
139
 
140
  const current = answers.find(({ id }) => id === activeId);
141
 
142
+ function reload() {
143
+ connection.current = false;
144
+ if (ref.current) {
145
+ ref.current.src = `/live?${nanoid()}`;
146
+ setLoadingLive(true);
147
+ setTries(3);
148
+ }
149
+ }
150
+
151
  return (
152
+ <>
153
+ <CssBaseline />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
+ <Stack
156
+ sx={{
157
+ ...fontMono.style,
158
+ position: "absolute",
159
+ inset: 0,
160
+ overflow: "hidden",
161
+ flexDirection: "row",
162
+ height: "100%",
163
+ }}
164
+ >
165
+ <Stack sx={{ width: "50%", flex: 1, gap: 2 }}>
166
+ <Box
167
+ component="form"
168
+ onSubmit={async event => {
169
+ event.preventDefault();
170
+ const formData = new FormData(event.target as HTMLFormElement);
171
+ const formObject = Object.fromEntries(formData);
172
+ try {
173
+ setLoading(true);
174
+ const { data } = await axios.post("/api/gpt", formObject);
175
+ const answer = data;
176
+ setAnswers([answer, ...answers]);
177
+ setRunningId(answer.id);
178
+ reload();
179
+ } catch (error) {
180
+ console.error(error);
181
+ } finally {
182
+ setLoading(false);
183
+ }
184
+ }}
185
+ >
186
+ <AppBar position="static" elevation={0}>
187
+ <Toolbar>
188
+ <IconButton
189
+ type="submit"
190
+ edge="start"
191
+ color="inherit"
192
+ aria-label={loading ? "Loading" : "Run"}
193
+ disabled={loading}
194
+ >
195
+ {loading ? <HourglassTopIcon /> : <PlayArrowIcon />}
196
+ </IconButton>
197
+ <Typography sx={{ flex: 1 }}>
198
+ {current?.task} - {current?.id ?? ""}
199
+ </Typography>
200
+ <IconButton
201
+ edge="end"
202
+ color="inherit"
203
+ aria-label="Clear Prompt"
204
+ onClick={async () => {
205
+ broadcast({ template: base.default });
206
+ setActiveId("1");
207
+ setTemplate(base.default);
208
+ reload();
209
+ }}
210
+ >
211
+ <ClearIcon />
212
+ </IconButton>
213
+ </Toolbar>
214
+ </AppBar>
215
+ <Paper variant="outlined" sx={{ p: 0 }}>
216
+ <Stack sx={{ p: 2, gap: 2 }}>
217
+ <Typography>
218
+ Based on: {current?.task ?? "Base Script"} - {activeId}
219
+ </Typography>
220
+ <TextField
221
+ multiline
222
+ fullWidth
223
+ id="prompt"
224
+ name="prompt"
225
+ label="Prompt"
226
+ placeholder="add a red box"
227
+ maxRows={6}
228
+ InputProps={{
229
+ style: fontMono.style,
230
+ }}
231
+ />
232
+ <TextField
233
+ multiline
234
+ fullWidth
235
+ id="negativePrompt"
236
+ name="negativePrompt"
237
+ label="Negative Prompt"
238
+ placeholder="images, audio files"
239
+ maxRows={6}
240
+ InputProps={{
241
+ style: fontMono.style,
242
+ }}
243
+ />
244
+ </Stack>
245
+ </Paper>
246
+ <Accordion>
247
+ <AccordionSummary
248
+ expandIcon={<ExpandMoreIcon />}
249
+ aria-controls="panel1a-content"
250
+ id="panel1a-header"
251
  >
252
+ <Typography>Options</Typography>
253
+ </AccordionSummary>
254
+ <AccordionDetails>
255
+ <TextField
256
+ multiline
257
+ fullWidth
258
+ id="template"
259
+ name="template"
260
+ label="Template"
261
+ placeholder={base.default}
262
+ maxRows={6}
263
+ value={template}
264
+ InputProps={{
265
+ style: { ...fontMono.style },
266
+ }}
267
+ onChange={event => {
268
+ setTemplate(event.target.value);
269
+ }}
270
+ />
271
+ </AccordionDetails>
272
+ </Accordion>
273
+ </Box>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
+ <List sx={{ flex: 1, overflow: "auto" }}>
276
+ {answers.map(answer => {
277
+ return (
278
+ <ListItem
279
+ key={answer.id}
280
+ secondaryAction={
281
+ <Stack sx={{ flexDirection: "row", gap: 1 }}>
282
+ {answer.id === "1" ? undefined : (
283
+ <IconButton
284
+ edge="end"
285
+ aria-label="Delete"
286
+ onClick={() => {
287
+ setAnswers(
288
+ answers.filter(
289
+ ({ id }) => id !== answer.id
290
+ )
291
+ );
292
+ }}
293
+ >
294
+ <DeleteForeverIcon />
295
+ </IconButton>
296
+ )}
297
  <IconButton
298
  edge="end"
299
+ aria-label="Show"
300
  onClick={() => {
301
+ setRunningId(answer.id);
302
+ reload();
 
303
  }}
304
  >
305
+ {runningId === answer.id ? (
306
+ <VisibilityIcon />
307
+ ) : (
308
+ <VisibilityOffIcon />
309
+ )}
310
  </IconButton>
311
+ </Stack>
312
+ }
313
+ disablePadding
314
+ >
315
+ <ListItemButton
316
+ dense
317
+ selected={activeId === answer.id}
318
+ role={undefined}
319
+ onClick={() => {
320
+ setActiveId(answer.id);
321
+ setTemplate(answer.content);
322
+ }}
323
+ >
324
+ <ListItemIcon>
325
+ {activeId === answer.id ? (
326
+ <CheckIcon />
327
  ) : (
328
+ <ContentCopyIcon />
329
  )}
330
+ </ListItemIcon>
331
+ <ListItemText primary={`${answer.task} - ${answer.id}`} />
332
+ </ListItemButton>
333
+ </ListItem>
334
+ );
335
+ })}
336
+ </List>
337
+ </Stack>
338
+ <Stack sx={{ flex: 1, width: "50%", position: "relative" }}>
339
+ <AppBar position="static" elevation={0}>
340
+ <Toolbar>
341
+ <IconButton
342
+ color="inherit"
343
+ aria-label="Reload"
344
+ onClick={() => {
345
+ reload();
346
+ }}
347
  >
348
+ <ReplayIcon />
349
+ </IconButton>
350
+ </Toolbar>
351
+ </AppBar>
352
+ {loadingLive && (
353
+ <Box
354
+ sx={{
355
+ position: "absolute",
356
+ zIndex: 100,
357
+ top: "50%",
358
+ left: "50%",
359
+ transform: "translate(-50%,-50%)",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }}
361
  >
362
+ <CircularProgress />
363
+ </Box>
364
+ )}
365
+ <Box
366
+ ref={ref}
367
+ component="iframe"
368
+ sx={{
369
+ width: "100%",
370
+ flex: 1,
371
+ m: 0,
372
+ border: 0,
373
+ overflow: "hidden",
374
+ visibility: loadingLive ? "hidden" : undefined,
375
+ }}
376
+ src="/live"
377
+ />
378
+ </Stack>
379
  </Stack>
380
+ </>
381
  );
382
  }
src/pages/live.tsx CHANGED
@@ -1,9 +1,28 @@
1
  import Script from "next/script";
2
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  export default function Page() {
4
  return (
5
  <>
6
- <canvas id="canvas" />
 
7
  <Script src="/js/utils.js" />
8
  </>
9
  );
 
1
  import Script from "next/script";
2
+ const styles = (
3
+ <style>
4
+ {`
5
+ * {
6
+ margin: 0;
7
+ padding: 0;
8
+ box-sizing: border-box;
9
+ }
10
+ html, body {
11
+ height: 100%;
12
+ width: 100%;
13
+ overflow: hidden;
14
+ }
15
+ #__next {
16
+ display: contents;
17
+ }
18
+ `}
19
+ </style>
20
+ );
21
  export default function Page() {
22
  return (
23
  <>
24
+ {styles}
25
+ <canvas id="canvas" style={{}} />
26
  <Script src="/js/utils.js" />
27
  </>
28
  );
src/services/api/index.ts CHANGED
@@ -36,16 +36,13 @@ export async function toOpenAI({
36
  const nextMessage: ChatCompletionRequestMessage = {
37
  role: "user",
38
  content: miniPrompt`
39
- DO: ${prompt_}
40
- ${negativePrompt_ ? `DONT: ${negativePrompt_}` : ""}
41
  INPUT: ${template.trim()}
42
  OUTPUT FORMAT: plain valid JavaScript
43
  `,
44
  };
45
  const task = `${prompt_}${negativePrompt_ ? ` | not(${negativePrompt_})` : ""}`;
46
- console.log(">>> NEXT MESSAGE CONTENT");
47
- console.log(nextMessage.content);
48
- console.log("<<<");
49
 
50
  try {
51
  const response = await openai.createChatCompletion({
@@ -54,7 +51,22 @@ export async function toOpenAI({
54
  messages: [
55
  {
56
  role: "system",
57
- content: `You are a FULLSTACK DEVELOPER. You implement the "DO". You NEVER implement "DONT". You EXCLUSIVELY answer in the requested "OUTPUT FORMAT" and NOTHING ELSE. You ALWAYS follow the "DO", "DONT", "INPUT" and "OUTPUT FORMAT".`,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  },
59
  nextMessage,
60
  ],
 
36
  const nextMessage: ChatCompletionRequestMessage = {
37
  role: "user",
38
  content: miniPrompt`
39
+ ADD: ${prompt_}
40
+ ${negativePrompt_ ? `REMOVE: ${negativePrompt_}` : ""}
41
  INPUT: ${template.trim()}
42
  OUTPUT FORMAT: plain valid JavaScript
43
  `,
44
  };
45
  const task = `${prompt_}${negativePrompt_ ? ` | not(${negativePrompt_})` : ""}`;
 
 
 
46
 
47
  try {
48
  const response = await openai.createChatCompletion({
 
51
  messages: [
52
  {
53
  role: "system",
54
+ content: miniPrompt`
55
+ All UPPERCASE words are IMPORTANT, all "UPPERCASE" words in QUOTES (") indicate KEYWORDS,
56
+ You are an expert JavaScript Developer, with a creative mindset.
57
+ You are a Canvas-2d expert and performance guru.
58
+ You strictly follow all "DOCS".
59
+ You ALWAYS follow the "ADD", "REMOVE", "INPUT" and "OUTPUT FORMAT".
60
+ You NEVER explain anything.
61
+
62
+ DOCS:
63
+ "ADD" is a set of features that You write code for
64
+ "REMOVE" is a set of things that should be removed or changed to something else
65
+ "INPUT" is the code that should be EXTENDED, ADJUSTED or FIXED
66
+ "OUTPUT FORMAT" is always JavaScript. the output should always be just JavaScript and NOTHING ELSE
67
+
68
+ You EXCLUSIVELY answer in the requested "OUTPUT FORMAT" and NOTHING ELSE
69
+ `,
70
  },
71
  nextMessage,
72
  ],