TownieuseProjects.tsx1 match
1import { useState, useEffect } from "react";
23const ENDPOINT = "/api/projects-loader";
45export function useProjects() {
TownieuseCreateProject.tsx1 match
1import { useState, useEffect } from "react";
23const ENDPOINT = "/api/create-project";
45export function useCreateProject() {
TownieuseCreateBranch.tsx1 match
1import { useState, useEffect } from "react";
23const ENDPOINT = "/api/create-branch";
45export function useCreateBranch(projectId: string) {
TownieuseChatLogic.ts2 matches
17project,
18branchId,
19// anthropicApiKey,
20// bearerToken,
21selectedFiles,
39status,
40} = useChat({
41api: "/api/send-message",
42body: {
43project,
TownieuseBranches.tsx1 match
1import { useState, useEffect } from "react";
23const ENDPOINT = "/api/project-branches";
45export function useBranches (projectId: string) {
TowniesoundEffects.ts4 matches
45/**
6* Plays a bell sound notification using the Web Audio API
7* @returns A Promise that resolves when the sound has started playing
8*/
13const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
14if (!AudioContext) {
15console.warn("Web Audio API not supported in this browser");
16resolve();
17return;
6566/**
67* Plays a simple notification sound using the Web Audio API
68* This is a simpler, shorter bell sound
69* @returns A Promise that resolves when the sound has started playing
75const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
76if (!AudioContext) {
77console.warn("Web Audio API not supported in this browser");
78resolve();
79return;
Towniesend-message.ts11 matches
28}
2930const { messages, project, branchId, anthropicApiKey, selectedFiles, images } = await c.req.json();
3132// do we want to allow user-provided tokens still
33const apiKey = anthropicApiKey || Deno.env.get("ANTHROPIC_API_KEY");
34const our_api_token = apiKey === Deno.env.get("ANTHROPIC_API_KEY");
3536if (our_api_token) {
37if (await overLimit(bearerToken)) {
38const user = await getUser(bearerToken);
5960const rowid = await startTrackingUsage({
61our_api_token,
62bearerToken, // will look up the userId from this
63branch_id: branchId,
6869// Initialize PostHog client
70const projectApiKey = Deno.env.get("POSTHOG_PROJECT_API_KEY");
71
72let tracedModel;
73
74if (projectApiKey) {
75const phClient = new PostHog(projectApiKey, {
76host: "https://us.i.posthog.com"
77});
84const traceId = `townie_${rowid}_${Date.now()}`;
8586const anthropic = createAnthropic({ apiKey });
87
88// Wrap the Anthropic model with PostHog tracing
94townie_branch_id: branchId,
95townie_usage_id: rowid,
96townie_our_api_token: our_api_token,
97townie_num_images: images?.length || 0,
98townie_selected_files_count: selectedFiles?.length || 0,
107} else {
108// Fallback to regular Anthropic call if PostHog is not configured
109const anthropic = createAnthropic({ apiKey });
110tracedModel = anthropic(model);
111}
Townieschema.tsx2 matches
19finish_reason?: string;
20num_images?: number;
21our_api_token: boolean;
22}
2344finish_reason TEXT,
45num_images INTEGER,
46our_api_token INTEGER NOT NULL,
47finish_timestamp INTEGER
48)
Townierequests.ts4 matches
17finish_reason: string | null;
18num_images: number | null;
19our_api_token: number;
20}
2157
58// Fetch the inference calls data
59fetch('/api/inference-calls?usage_id=' + usageId)
60.then(response => response.json())
61.then(data => {
192<th>Finish</th>
193<th>Images</th>
194<th>Our API</th>
195</tr>
196</thead>
216<td>${row.finish_reason || '-'}</td>
217<td>${formatNumber(row.num_images)}</td>
218<td>${formatBoolean(row.our_api_token)}</td>
219</tr>
220`).join("")}
17Townie is fully open-source and itself runs on Val Town. Pull requests welcome!
1819To get Townie running in your Val Town account, click the **Remix** button and then add your ANTHROPIC_API_KEY. You can leave all the other environment variables blank.
2021Authentication in Townie is handled via Val Town Oauth. However, we have not yet opened up our OAuth to anyone else, which currently makes it very awkward to use your own Townie. Here is a temporary workaround: