39 profile_image_url: user.profileImageUrl,
40 url: user.url,
41 updated_at: new Date().toISOString(), // Using current time as the API doesn't provide updated_at
42 });
43
1043 <link rel="icon" href="https://fav.farm/👀" />
1044 <meta name="viewport" content="width=device-width, initial-scale=1" />
1045 <link rel="preconnect" href="https://fonts.googleapis.com" />
1046 <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
1047 <link
1048 href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100..700;1,100..700&display=swap"
1049 rel="stylesheet"
1050 />
1061 <a href="https://val.town" className="valtown-link" style={{ marginLeft: "auto" }}>Return to Val Town</a>
1062 </h1>
1063 <div className="api-info">
1064 <details>
1065 <summary>API Access</summary>
1066 <div className="api-docs">
1067 <p>
1068 You can access search results via JSON API by adding <code>format=json</code> to your query:
1069 </p>
1070 {searchTerm
1222 <div className="search-examples">
1223 <a href="?q=fetch" className="example-link">fetch</a>
1224 <a href="?q=api" className="example-link">api</a>
1225 <a href="?q=database" className="example-link">database</a>
1226 <a href="?q=image" className="example-link">image</a>
1376 <div className="search-examples">
1377 <a href="?q=fetch" className="example-link">fetch</a>
1378 <a href="?q=api" className="example-link">api</a>
1379 <a href="?q=database" className="example-link">database</a>
1380 <a href="?q=image" className="example-link">image</a>
14import { searchDocs, searchDocsCount } from "./docsearch.ts";
15
16// Handle typeahead API requests
17export function handleTypeahead(req: Request): Response {
18 const url = new URL(req.url);
173 searchTerm
174 ? (needFullDocsData
175 ? searchDocs(searchTerm, page, pageSize, true) // Get full data for docs tab or JSON API
176 : searchDocsCount(searchTerm).then(count => ({ results: [], totalResults: count }))) // Just get count for other tabs in HTML view
177 : { results: [], totalResults: 0 }
82
831. **Create a Slack App**:
84 - Go to [Slack API Apps](https://api.slack.com/apps) → Create New App → From scratch
85 - Name your app and select your workspace
86 - Click "Create App"
17Townie is fully open-source and itself runs on Val Town. Pull requests welcome!
18
19To 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.
20
21Authentication 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:
8import { OpenAI } from "https://esm.town/v/std/openai";
9import { Octokit } from "https://esm.sh/@octokit/rest@20.0.2";
10import { WebClient } from "https://esm.sh/@slack/web-api@7.0.2";
11
12// Dedupe events
13// https://api.slack.com/apis/events-api#responding-to-events
14const processedEvents = new Set<string>();
15
129async function isBugReportLLM(text: string): Promise<boolean> {
130 try {
131 // Check if OpenAI API key is available
132 if (!Deno.env.get("OPENAI_API_KEY")) {
133 console.warn("OpenAI API key not found - bug detection disabled");
134 return false;
135 }
225 });
226
227 // Filter out pull requests (GitHub API includes PRs in issues endpoint)
228 const actualIssues = response.data.filter(issue => !issue.html_url.includes("/pull/"));
229
249async function findRelatedIssues(slackMessage: string, issues: any[]): Promise<any[]> {
250 try {
251 // Check if OpenAI API key is available
252 if (!Deno.env.get("OPENAI_API_KEY")) {
253 return [];
254 }
12app.get("/frontend/**/*", c => serveFile(c.req.path, import.meta.url));
13
14// Add your API routes here
15// app.get("/api/data", c => c.json({ hello: "world" }));
16
17// Unwrap and rethrow Hono errors as the original error
32 // Chat Completions (POST /v1/chat/completions)
33 try {
34 const response: any = await fetch("https://api.sarvam.ai/v1/chat/completions", {
35 method: "POST",
36 headers: {
21 setLoading(true);
22 const [destinationsRes, userRes] = await Promise.all([
23 fetch('/api/goals/travel-destinations'),
24 fetch('/api/user/profile')
25 ]);
26
64
65 try {
66 const response = await fetch('/api/goals', {
67 method: 'POST',
68 headers: {
26 try {
27 setLoading(true);
28 const response = await fetch('/api/goals');
29 const data = await response.json();
30 if (data.success) {
68
69 try {
70 const response = await fetch('/api/goals', {
71 method: 'POST',
72 headers: {
123
124 try {
125 const response = await fetch(`/api/goals/${goalId}/progress`, {
126 method: 'POST',
127 headers: {
165
166 try {
167 const response = await fetch(`/api/goals/${goalId}`, {
168 method: 'DELETE',
169 });