a574a4824db_README.md2 matches
45* `migrations.ts` - code to set up the database tables the app needs
6* `queries.ts` - functions to run queries against those tables, which are imported and used in the main Hono server in `/backend/index.ts`
78## Migrations
18The queries file is where running the migrations happen in this app. It'd also be reasonable for that to happen in index.ts, or as is said above, for that line to be commented out, and only run when actual changes are made to your database schema.
1920The queries file exports functions to get and write data. It relies on shared types and data imported from the `/shared` directory.
a574a4824db_App.tsx2 matches
62};
6364export function App() {
65const [memories, setMemories] = useState<Memory[]>([]);
66const [loading, setLoading] = useState(true);
139const data = await response.json();
140141// Change the sorting function to show memories in chronological order
142const sortedMemories = [...data].sort((a, b) => {
143const dateA = a.createdDate || 0;
a574a4824db_NotebookView.tsx1 match
54}
5556export function NotebookView({ onClose, avatarUrl }: NotebookViewProps) {
57const [memories, setMemories] = useState<Memory[]>([]);
58const [loading, setLoading] = useState(true);
a9dcc8717e8_getCalendarEvents.ts6 matches
6const LOCAL_TIMEZONE = "America/New_York";
78async function deleteExistingCalendarEvents() {
9await sqlite.execute(
10`
15}
1617// Helper function to extract time from ISO string without timezone conversion
18function extractTimeFromISO(isoString) {
19// Match the time portion of the ISO string
20const timeMatch = isoString.match(/T(\d{2}):(\d{2}):/);
31}
3233function formatEventToNaturalLanguage(event) {
34const summary = event.summary || "Untitled event";
3583}
8485async function insertCalendarEvent(date, eventText) {
86const { nanoid } = await import("https://esm.sh/nanoid@5.0.5");
8797}
9899export default async function getCalendarEvents() {
100try {
101const events = await getEvents(
a9dcc8717e8_generateFunFacts.ts8 matches
11* @returns Array of previous fun facts
12*/
13async function getPreviousFunFacts() {
14try {
15const result = await sqlite.execute(
32* @param dates Array of date strings in ISO format
33*/
34async function deleteExistingFunFacts(dates) {
35try {
36for (const date of dates) {
51* @param factText The fun fact text
52*/
53async function insertFunFact(date, factText) {
54try {
55await sqlite.execute(
75* @returns Array of generated fun facts
76*/
77async function generateFunFacts(previousFacts) {
78try {
79// Get API key from environment
197* @returns Array of parsed facts
198*/
199function parseFallbackFacts(responseText, expectedDates) {
200// Try to extract facts using regex
201const factPattern = /(\d{4}-\d{2}-\d{2})["']?[,:]?\s*["']?(.*?)["']?[,}]/gs;
260261/**
262* Main function to generate and store fun facts for the next 7 days
263*/
264export async function generateAndStoreFunFacts() {
265try {
266// Get previous fun facts
301* Intended to be used as a Val Town cron job
302*/
303export default async function() {
304console.log("Running fun facts generation cron job...");
305return await generateAndStoreFunFacts();
a9dcc8717e8_getWeather.ts5 matches
8const TABLE_NAME = `memories`;
910function summarizeWeather(weather: WeatherResponse) {
11const summarizeDay = (day: WeatherResponse["weather"][number]) => ({
12date: day.date,
25}
2627async function generateConciseWeatherSummary(weatherDay) {
28try {
29// Get API key from environment
83}
8485async function deleteExistingForecast(date: string) {
86await sqlite.execute(
87`
93}
9495async function insertForecast(date: string, forecast: string) {
96const { nanoid } = await import("https://esm.sh/nanoid@5.0.5");
97112}
113114export default async function getWeatherForecast(interval: number) {
115const weather = await getWeather("Washington, DC");
116console.log({ weather });
a9dcc8717e8_handleUSPSEmail.ts3 matches
4const RECIPIENTS = ["Geoffrey", "Maggie"] as const;
56function parseDateFromSubject(subject: string): string | null {
7const match = subject.match(/(\w{3}), (\d{1,2}\/\d{1,2})/);
8if (match) {
19};
2021async function analyzeHtmlContent(
22anthropic: Anthropic,
23htmlContent: string,
80}
8182export default async function (e: Email) {
83console.log("email content");
84console.log(e.html);
a9dcc8717e8_handleTelegramMessage.ts5 matches
36* Store a chat message in the database
37*/
38export async function storeChatMessage(
39chatId,
40senderId,
69* Retrieve chat history for a specific chat
70*/
71export async function getChatHistory(chatId, limit = 50) {
72try {
73const { sqlite } = await import("https://esm.town/v/stevekrouse/sqlite");
94* Format chat history for Anthropic API
95*/
96function formatChatHistoryForAI(history) {
97const messages = [];
98118* Analyze a Telegram message and extract memories from it
119*/
120async function analyzeMessageContent(
121anthropic,
122username,
499500// Handle webhook requests
501export default async function (req: Request): Promise<Response> {
502// Set webhook if it is not set yet
503if (!isEndpointSet) {
a9dcc8717e8_memoryUtils.ts3 matches
7* @returns Array of memory objects
8*/
9export async function getAllMemories(includeDate = true, startDate = null) {
10try {
11const { sqlite } = await import("https://esm.town/v/stevekrouse/sqlite");
41* @returns Array of memory objects
42*/
43export async function getRelevantMemories() {
44try {
45// Get today's date in US Eastern Time
59* @returns Formatted string of memories
60*/
61export function formatMemoriesForPrompt(memories) {
62if (!memories || memories.length === 0) {
63return "No stored memories are available.";
a9dcc8717e8_.cursorrules15 matches
8### 1. Script Vals
910- Basic JavaScript/TypeScript functions
11- Can be imported by other vals
12- Example structure:
1314```typescript
15export function myFunction() {
16// Your code here
17}
2526```typescript
27export default async function (req: Request) {
28return new Response("Hello World");
29}
3738```typescript
39export default async function () {
40// Scheduled task code
41}
4950```typescript
51export default async function (email: Email) {
52// Process email
53}
5758- Ask clarifying questions when requirements are ambiguous
59- Provide complete, functional solutions rather than skeleton implementations
60- Test your logic against edge cases before presenting the final solution
61- Ensure all code follows Val Town's specific platform requirements
70- **Never bake in secrets into the code** - always use environment variables
71- Include comments explaining complex logic (avoid commenting obvious operations)
72- Follow modern ES6+ conventions and functional programming practices if possible
7374## Val Town Standard Libraries
7576Val Town provides several hosted services and utility functions.
7778### Blob Storage
124```
125126## Val Town Utility Functions
127128Val Town provides several utility functions to help with common project tasks.
129130### Importing Utilities
176{
177name: "should add numbers correctly",
178function: () => {
179expect(1 + 1).toBe(2);
180},
210โ โโโ database/
211โ โ โโโ migrations.ts # Schema definitions
212โ โ โโโ queries.ts # DB query functions
213โ โ โโโ README.md
214โ โโโ index.ts # Main entry point
226โโโ shared/
227โโโ README.md
228โโโ utils.ts # Shared types and functions
229```
230232- Hono is the recommended API framework (similar to Express, Flask, or Sinatra)
233- Main entry point should be `backend/index.ts`
234- **Static asset serving:** Use the utility functions to read and serve project files:
235```ts
236// Use the serveFile utility to handle content types automatically
273- Run migrations on startup or comment out for performance
274- Change table names when modifying schemas rather than altering
275- Export clear query functions with proper TypeScript typing
276- Follow the queries and migrations pattern from the example
277