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);
5455const rowid = await startTrackingUsage({
56our_api_token,
57bearerToken, // will look up the userId from this
58branch_id: branchId,
6364// Initialize PostHog client
65const projectApiKey = Deno.env.get("POSTHOG_PROJECT_API_KEY");
66
67let tracedModel;
68
69if (projectApiKey) {
70const phClient = new PostHog(projectApiKey, {
71host: "https://us.i.posthog.com"
72});
79const traceId = `townie_${rowid}_${Date.now()}`;
8081const anthropic = createAnthropic({ apiKey });
82
83// Wrap the Anthropic model with PostHog tracing
89townie_branch_id: branchId,
90townie_usage_id: rowid,
91townie_our_api_token: our_api_token,
92townie_num_images: images?.length || 0,
93townie_selected_files_count: selectedFiles?.length || 0,
102} else {
103// Fallback to regular Anthropic call if PostHog is not configured
104const anthropic = createAnthropic({ apiKey });
105tracedModel = anthropic(model);
106}
makemeavalindex.ts8 matches
69app.get("/shared/*", c => serveFile(c.req.path, import.meta.url));
7071// API Routes
72app.get("/api/quote", (c) => {
73const randomQuote = quotes[Math.floor(Math.random() * quotes.length)];
74return c.json(randomQuote);
75});
7677app.get("/api/weather", async (c) => {
78const lat = c.req.query("lat");
79const lon = c.req.query("lon");
8485try {
86// Use Open-Meteo API (no API key required)
87const response = await fetch(
88`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true&timezone=auto`
89);
90
91if (!response.ok) {
92throw new Error("Weather API request failed");
93}
94
136});
137138app.post("/api/gratitude", async (c) => {
139try {
140const { text } = await c.req.json();
167});
168169app.get("/api/gratitude", async (c) => {
170try {
171const entries = await blob.getJSON("gratitude_entries") || [];
11};
1213// API helper functions
14const api = {
15async createProject(name: string) {
16const response = await fetch('/api/projects', {
17method: 'POST',
18headers: { 'Content-Type': 'application/json' },
23
24async getProject(id: string) {
25const response = await fetch(`/api/projects/${id}`);
26return response.json();
27},
28
29async updateProject(id: string, data: any) {
30const response = await fetch(`/api/projects/${id}`, {
31method: 'PUT',
32headers: { 'Content-Type': 'application/json' },
37
38async addClip(projectId: string, clipData: any) {
39const response = await fetch(`/api/projects/${projectId}/clips`, {
40method: 'POST',
41headers: { 'Content-Type': 'application/json' },
46
47async updateClip(clipId: string, data: any) {
48const response = await fetch(`/api/clips/${clipId}`, {
49method: 'PUT',
50headers: { 'Content-Type': 'application/json' },
55
56async deleteClip(clipId: string) {
57const response = await fetch(`/api/clips/${clipId}`, {
58method: 'DELETE'
59});
90setIsLoading(true);
91try {
92const result = await api.createProject('New Project');
93const newProject: Project = {
94id: result.id,
121};
122123// Handle file upload with API integration
124const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
125const files = event.target.files;
145};
146147const result = await api.addClip(project.id, clipData);
148
149const newClip: VideoClip = {
229if (selectedClipData) {
230try {
231await api.updateClip(selectedClip, {
232effects: selectedClipData.effects,
233trimStart: selectedClipData.trimStart,
243};
244245// Remove clip with API integration
246const removeClip = async (clipId: string) => {
247if (!project) return;
248249try {
250await api.deleteClip(clipId);
251} catch (error) {
252console.error('Failed to delete clip:', error);
297try {
298for (const clip of updatedClips) {
299await api.updateClip(clip.id, {
300position: clip.position,
301effects: clip.effects,
338const clipData = updatedClips.find(c => c.id === clipId);
339if (clipData) {
340await api.updateClip(clipId, {
341trimStart,
342trimEnd,
yt-transcriptREADME.md1 match
48## Technical Details
4950- Uses YouTube's transcript API via corsproxy.io
51- Built with Hono backend and React frontend
52- TypeScript for type safety
yt-transcriptindex.tsx1 match
9495try {
96const response = await fetch('/api/transcript', {
97method: 'POST',
98headers: {
yt-transcriptindex.ts2 matches
50}
5152// API endpoint to extract transcript
53app.post("/api/transcript", async c => {
54try {
55const { url } = await c.req.json();
124});
125126// API Routes for video processing
127128// Get all projects
129app.get("/api/projects", async c => {
130try {
131const result = await sqlite.execute(
139140// Create new project
141app.post("/api/projects", async c => {
142try {
143const body = await c.req.json();
164165// Get project with clips
166app.get("/api/projects/:id", async c => {
167try {
168const projectId = c.req.param("id");
198199// Update project
200app.put("/api/projects/:id", async c => {
201try {
202const projectId = c.req.param("id");
218219// Delete project
220app.delete("/api/projects/:id", async c => {
221try {
222const projectId = c.req.param("id");
235236// Add clip to project
237app.post("/api/projects/:id/clips", async c => {
238try {
239const projectId = c.req.param("id");
274275// Update clip
276app.put("/api/clips/:id", async c => {
277try {
278const clipId = c.req.param("id");
292293// Delete clip
294app.delete("/api/clips/:id", async c => {
295try {
296const clipId = c.req.param("id");
304});
305306app.post("/api/export", async c => {
307// In a real app, this would handle video processing with FFmpeg
308const { projectId, settings } = await c.req.json();
313return c.json({
314success: true,
315downloadUrl: "/api/download/sample-video.mp4",
316message: "Video exported successfully"
317});
318});
319320app.get("/api/effects", c => {
321// Return trending effects data
322const effects: TrendingEffect[] = [
17```
18โโโ backend/
19โ โโโ index.ts # API server with Hono
20โโโ frontend/
21โ โโโ index.html # Main app interface
3031- **Frontend**: React 18, TypeScript, TailwindCSS
32- **Backend**: Hono API framework
33- **Video Processing**: Web APIs (MediaRecorder, Canvas, WebGL)
34- **Storage**: Browser localStorage for projects
35- **PWA**: Service worker for offline capability
personalShopperREADME.md21 matches
3## Description
45This is an AI-powered Grocery Shopping assistant that turns an imprecise list of items like "milk, bread, eggs" into a Kroger cart full of groceries. It relies on the Kroger API to search each item, then uses an LLM to decide which specific UPC to add to the cart (again, using the Kroger API). Once an item is selected, we store the UPC in the database so we can avoid consulting the LLM for that item again.
67Households have preferences for which items to buy, and what priorities they have for each item. For example, we prefer to buy free range eggs and poultry, but don't particularly care whether they are organic or not. These details are stored in a database, which should also be consulted to add context to the LLM's decisions.
15Set these in your Val Town environment:
1617- `KROGER_CLIENT_ID` - Your Kroger API client ID
18- `KROGER_CLIENT_SECRET` - Your Kroger API client secret
19- `KROGER_REDIRECT_URI` - Your registered redirect URI (e.g., `https://your-val.web.val.run/auth/callback`)
2064- Unique constraint on (userId, itemName)
6566## API Endpoints
6768### Authentication
70- `GET /auth/callback` - OAuth callback handler
71- `POST /auth/logout` - Logout user
72- `GET /api/user` - Get current user info
73- `PUT /api/user/location` - Update preferred store location
7475### Guidance Management
76- `GET /api/guidance` - Get all guidance for current user
77- `GET /api/guidance/search?q=item` - Search guidance by item name
78- `POST /api/guidance` - Create new guidance
79- `PUT /api/guidance/:id` - Update guidance
80- `DELETE /api/guidance/:id` - Delete guidance
8182### Selection Management
83- `GET /api/selections` - Get all selections for current user
84- `GET /api/selections/item/:itemName` - Get selection for specific item
85- `POST /api/selections` - Create/update selection
86- `PUT /api/selections/:id` - Update selection
87- `DELETE /api/selections/:id` - Delete selection
8889## Shopping Process
90911. The user supplies a list of items they want to buy.
922. We search the Kroger API, getting a list of products that match the free text name.
933. For each item, we:
941. Try to find it in selections. If we can't find it there,
952. Use full-text search to find the most relevant guidance. Then ask the LLM to decide which specific UPC to add to the cart. Store this in the selections table for next time.
964. We use the Kroger API to add the item to the cart.
975. Repeat for each item.
98110- TypeScript
111- Val.Town with SQLite integration
112- Hono for the API
113- TailwindCSS for styling
114- Kroger API for product data and cart management
115116## File Structure
128โโโ shared/
129โ โโโ types.ts # Shared TypeScript interfaces
130โโโ docs/ # Kroger API documentation
131```
132
personalShopperoauth-setup.md13 matches
53When a user clicks "Connect with Kroger", they're redirected to:
54```
55https://api.kroger.com/v1/connect/oauth2/authorize?
56client_id=YOUR_CLIENT_ID&
57redirect_uri=YOUR_REDIRECT_URI&
68### 3. Token Exchange
69Your app exchanges the authorization code for:
70- `access_token`: Used to make API calls on behalf of the user
71- `refresh_token`: Used to get new access tokens when they expire
72- `expires_in`: How long the access token is valid (in seconds)
75Your app uses the access token to get the user's Kroger profile ID from:
76```
77GET https://api.kroger.com/v1/identity/profile
78Authorization: Bearer ACCESS_TOKEN
79```
115- If refresh fails, users will need to re-authenticate
116117## API Endpoints
118119Once OAuth is configured, these endpoints become available:
125126### User Management
127- `GET /api/user` - Get current user info
128- `PUT /api/user/location` - Update preferred store location
129130### Data Management
131- `GET /api/guidance` - Get user's shopping preferences
132- `POST /api/guidance` - Add new preference
133- `GET /api/selections` - Get user's saved product selections
134- `POST /api/selections` - Save new product selection
135136## Next Steps
1391401. **Test the full flow** with a real Kroger account
1412. **Implement product search** using the Kroger Products API
1423. **Add cart management** using the Kroger Cart API
1434. **Integrate AI/LLM** for intelligent product selection
1445. **Build the shopping list interface**
146## Support
147148For Kroger API issues:
149- [Kroger Developer Documentation](https://developer.kroger.com/documentation)
150- [Kroger Developer Support](https://developer.kroger.com/support)