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
/** @jsxImportSource https://esm.sh/react */
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@4";
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();
const systemPrompt = `The conversation below is your recent interaction with the user.
Your entire response should only be TypeScript.
Your response should start with \`\`\`ts and end with \`\`\`.
Make an HTTP val (other vals are currently not supported to run, even though we have examples for them).
Start your response with a comment explaining how your approach will work, what libraries or
API calls you will use, and any tradeoffs you're making. Then write the code in a concise way,
the simplest way to achieve the goal, though you can add some inline comments to explain your
reasoning (not for every line, but for major groups of lines). Don't use any environment variables
unless strictly necessary, for example, use APIs that don't require a key, prefer internal function
imports (using esm.town), and prefer putting API keys as inline variables. Use built-in Deno
functions where possible. Unless specified, don't add error handling,
make sure that errors bubble up to the caller.
There should be no comments like "more content here", it should be complete and directly runnable.
The val should create a "export default async function main" which is the main function that gets
executed on every HTTP request.`.replace("\n", " ");
const assistantMessageHeader = (maxHeight: number) => {
return `I wrote some new code for your Val: <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)"> `;
};
const bubbleHeader = (emoji: string, id?: string, spin?: boolean) => {
const idStr = id ? ` id="${id}"` : "";
const spinStr = spin ? " animate-spin" : "";
return `
<div class="flex mb-4" ${idStr}>
<div class="${spinStr}" 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 bubbleFooter = () => `
</div>
</div>
`;
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 = "";
new Promise(async () => {
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";
tabPanelCode.style.visibility = "hidden";
janpaul123-valle_tmp_92279722423458817448513814852015.web.val.run
July 15, 2024