4} from "npm:@mendable/firecrawl-js";
56const app = new FirecrawlApp({ apiKey: Deno.env.get("FIRECRAWL_API_KEY") });
78// Scrape a website
Towniesend-message.ts12 matches
48project,
49branchId,
50anthropicApiKey,
51selectedFiles,
52images,
5455// do we want to allow user-provided tokens still
56const apiKey = anthropicApiKey || Deno.env.get("ANTHROPIC_API_KEY");
57const our_api_token = apiKey === Deno.env.get("ANTHROPIC_API_KEY");
5859if (our_api_token) {
60if (await hasInsufficientCredits({ bearerToken })) {
61return Response.json({
7374const rowid = await startTrackingUsage({
75our_api_token,
76bearerToken, // will look up the userId from this
77branch_id: branchId,
8283// Initialize PostHog client
84const projectApiKey = Deno.env.get("POSTHOG_PROJECT_API_KEY");
8586let tracedModel;
8788if (projectApiKey) {
89const phClient = new PostHog(projectApiKey, {
90host: "https://us.i.posthog.com",
91});
98const traceId = `townie_${rowid}_${Date.now()}`;
99100const anthropic = createAnthropic({ apiKey });
101102// Wrap the Anthropic model with PostHog tracing
108townie_branch_id: branchId,
109townie_usage_id: rowid,
110townie_our_api_token: our_api_token,
111townie_num_images: images?.length || 0,
112townie_selected_files_count: selectedFiles?.length || 0,
121} else {
122// Fallback to regular Anthropic call if PostHog is not configured
123const anthropic = createAnthropic({ apiKey });
124tracedModel = anthropic(model);
125}
271});
272273if (our_api_token) {
274const stillHasCredits =
275!(await hasInsufficientCredits({ bearerToken })); // Check for at least 1 cent
Townie2PurchaseCreditsRoute.tsx2 matches
15const fetchBalance = async () => {
16try {
17const response = await fetch("/api/credit-balance");
18if (response.ok) {
19const data = await response.json();
3536try {
37const response = await fetch("/api/purchase-credits", {
38method: "POST",
39headers: { "Content-Type": "application/json" },
41);
4243// token middleware for API requests
44app.all("/api/*", async (c, next) => {
45if (c.req.path === "/api/stripe-webhook") {
46return next();
47}
55});
5657app.route("/api", backend);
5859app.get("/frontend/*", (c) => {
Townie2val-summary.ts3 matches
18SUM(num_images) as total_images
19FROM ${USAGE_TABLE}
20WHERE val_id = ? AND our_api_token = 1
21GROUP BY val_id
22`, [valId]);
34FROM ${INFERENCE_CALLS_TABLE} i
35JOIN ${USAGE_TABLE} u ON i.usage_id = u.id
36WHERE u.val_id = ? AND u.our_api_token = 1
37GROUP BY u.val_id
38`, [valId]);
41const requestsResult = await sqlite.execute(`
42SELECT * FROM ${USAGE_TABLE}
43WHERE val_id = ? AND our_api_token = 1
44ORDER BY timestamp DESC
45`, [valId]);
Townie2val-detail.ts1 match
18finish_reason?: string;
19num_images?: number;
20our_api_token: boolean;
21}
22
Townie2useUser.tsx1 match
1import { useState, useEffect } from "react";
23const USER_ENDPOINT = "/api/user";
45export function useUser() {
Townie2user-summary.ts2 matches
20SUM(num_images) as total_images
21FROM ${USAGE_TABLE}
22WHERE our_api_token = 1
23`;
24
41FROM ${INFERENCE_CALLS_TABLE} i
42JOIN ${USAGE_TABLE} u ON i.usage_id = u.id
43WHERE u.our_api_token = 1
44`;
45
Townie2user-detail.ts2 matches
1import { renderLayout } from "./layout.ts";
2import { formatNumber, formatPrice, formatDate, formatBoolean } from "../utils/formatters.ts";
3import { CreditAddition } from "../api/credit-additions.ts";
45interface UserSummaryRow {
33finish_reason?: string;
34num_images?: number;
35our_api_token: boolean;
36}
37
Townie2useProject.tsx2 matches
1import { useState, useEffect } from "react";
23const PROJECT_ENDPOINT = "/api/project";
4const FILES_ENDPOINT = "/api/project-files";
56export function useProject(projectId: string, branchId?: string) {