Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Improvements Made:
// - Re-organized and cleaned the code for better readability and maintainability.
// - Added some comments to explain major parts of the implementation.
// - Updated form elements to handle common form submission patterns more gracefully.
// - Improved existing functions and refactored to maintain a clean structure while keeping it consistent with the existing code.
import valleGetValsContextWindow from "https://esm.town/v/janpaul123/valleGetValsContextWindow";
import { passwordAuth } from "https://esm.town/v/pomdtr/password_auth?v=84";
import { verifyToken } from "https://esm.town/v/pomdtr/verifyToken";
import ValTown from "npm:@valtown/sdk";
import { Hono } from "npm:hono";
import _ from "npm:lodash";
import OpenAI from "npm:openai";
import { renderToString } from "npm:react-dom/server";
const vt = new ValTown({ bearerToken: Deno.env.get("valtown") });
const username = "janpaul123";
const app = new Hono();
// Helper Function: Render JSX to HTML Response
const jsxResponse = (jsx) => {
return new Response(renderToString(jsx), { headers: { "Content-Type": "text/html" } });
};
// Prompt Templates to Guide the Language Model
const systemprompt = `Your entire response should only be TypeScript. Make an HTTP val (other vals are currently not supported to run).`
+ ` Start your response with a comment explaining what you're going to do, and `
+ `write the code with explanations. Don't use any environment variables unless strictly necessary.`;
// Rendering Utilities to Construct Conversation UI
const makeBubbleHeader = (emoji, id="", spin=false) => `
<div class="flex mb-4" id="${id}">
<div class="${spin ? "animate-spin" : ""}" style="width:32px; height:32px; line-height:32px; font-size:28px; overflow:hidden; text-align:center; display:inline-block; background:#ddd; border-radius:100%; flex-shrink:0">${emoji}</div>
<div class="flex-1 ml-4" style="margin-top:3px; min-width:0">
`;
const makeBubbleFooter = () => `</div></div>`;
const makeAssistantMessageHeader = (maxHeight) => `
<div class="js-scroll-container-assistant font-mono whitespace-pre-wrap text-xs overflow-auto p-2 mt-2 rounded" style="max-height:${maxHeight}px; background:rgb(249 250 251)">
I wrote some new code for your Val:
`;
// Main Handler that Manages Conversation and Updates Code
const mainHandler = async (c) => {
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
const textEncoder = new TextEncoder();
const write = (text) => writer.write(textEncoder.encode(text));
let valCode = "";
let iframeSrc = "";
const body = await c.req.parseBody();
const userprompt = body.userprompt;
const prevConversation = body.prevConversation ? JSON.parse(body.prevConversation) : [];
const currentCode = body.code || "";
const model = body.model || "gpt-3.5-turbo";
// Start building HTML response
write(`<!DOCTYPE html>
<html>
<head>
<style>
html, body { margin: 0; padding: 0; height: 100%; }
.cm-focused { outline: none !important; }
.cm-editor, .for-codemirror-container > div { height: 100%; }
</style>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
</head>
<body>
<form method="POST" action="/" style="height: 100%">
<div style="float:right; width:60%; height:100%; padding-left: 16px; display:flex; flex-direction:column">
<div class="flex p-4 pl-0">
<button id="tab-button-code" onclick='event.preventDefault(); openTab("code")' class="rounded mr-2 px-2 hover:bg-gray-100">Code</button>
<button id="tab-button-preview" onclick='event.preventDefault(); openTab("preview")' class="rounded mr-2 px-2 hover:bg-gray-100">Preview</button>
</div>
<div style="width: 100%; flex: 1; display: flex; position: relative">
<div class="for-codemirror-container" style="position:absolute; left:0; right:0; top:0; bottom:0; display:flex; flex-direction:column; padding-right: 16px; padding-bottom: 16px; width: 100%" id="tab-panel-code">
<textarea name="code" id="code-textarea" style="width: 100%; height: 100%; resize: none; background: rgb(249 250 251); padding: 8px" class="for-codemirror text-xs font-mono rounded">${_.escape(valCode)}</textarea>
</div>
<div style="position:absolute; left:0; right:0; top:0; bottom:0; flex:1; display:flex; flex-direction:column; padding-right: 16px; padding-bottom: 16px; width: 100%" id="tab-panel-preview">
<iframe id="preview-iframe" style="width: 100%; height: 100%" src="${iframeSrc}"></iframe>
</div>
</div>
<script>
function openTab(tab) {
const tabButtonCode = document.getElementById("tab-button-code");
const tabButtonPreview = document.getElementById("tab-button-preview");
const tabPanelCode = document.getElementById("tab-panel-code");
const tabPanelPreview = document.getElementById("tab-panel-preview");
if (tab == "code") {
tabButtonCode.style.backgroundColor = "#ddd";
tabButtonPreview.style.backgroundColor = "";
tabPanelCode.style.visibility = "visible";
tabPanelPreview.style.visibility = "hidden";
} else if (tab == "preview") {
tabButtonCode.style.backgroundColor = "";
tabButtonPreview.style.backgroundColor = "#ddd";
janpaul123-valle_tmp_50677281064121176482256801591227.web.val.run
July 15, 2024