7// but in the meantime, we can cache user info in memory
8const userIdCache: { [key: string]: any } = {};
9export async function getUser(bearerToken: string) {
10 if (userIdCache[bearerToken]) return userIdCache[bearerToken];
11
16}
17
18async function last24Hours(userId: string) {
19 const usage = await sqlite.execute(
20 `SELECT
40 "devto": 100, // hardcoded limit of $100 per day for dev.to, billed later
41};
42export async function overLimit(bearerToken: string) {
43 const user = await getUser(bearerToken);
44 const last24HourUsage = await last24Hours(user.id);
49}
50
51export async function insertInferenceCall({
52 usage_id,
53 input_tokens,
103}
104
105export async function startTrackingUsage({
106 bearerToken,
107 val_id,
145}
146
147export async function finishTrackingUsage({
148 rowid,
149 input_tokens,
21 * Parse pagination parameters from URL
22 */
23export function getPaginationParams(url: URL): { page: number; pageSize: number } {
24 const page = parseInt(url.searchParams.get("page") || "1", 10);
25 const pageSize = parseInt(url.searchParams.get("pageSize") || "50", 10);
35 * Calculate pagination metadata
36 */
37export function calculatePagination(params: PaginationParams): PaginationResult {
38 const totalPages = Math.ceil(params.totalItems / params.pageSize);
39
51 * Generate SQL LIMIT and OFFSET clauses for pagination
52 */
53export function getPaginationSQL(page: number, pageSize: number): string {
54 const offset = (page - 1) * pageSize;
55 return `LIMIT ${pageSize} OFFSET ${offset}`;
59 * Generate HTML for pagination controls
60 */
61export function renderPaginationControls(pagination: PaginationResult, baseUrl: string): string {
62 const url = new URL(baseUrl);
63
64 // Function to generate page URL
65 const getPageUrl = (page: number) => {
66 url.searchParams.set("page", page.toString());
10}
11
12export function renderLayout(content: string, options: LayoutOptions): string {
13 const { title, activeTab = "dashboard", scripts = [], styles = [] } = options;
14
149 // Default scripts
150 const defaultScripts = `
151 document.addEventListener('DOMContentLoaded', function() {
152 // Tab navigation
153 document.querySelectorAll('.tab').forEach(tab => {
154 tab.addEventListener('click', function(e) {
155 if (this.getAttribute('href') === '#') {
156 e.preventDefault();
29}
30
31export function renderInferenceCalls(
32 data: InferenceCallRow[],
33 pagination: PaginationData,
6 * Get paginated inference calls
7 */
8export async function getInferenceCalls(url: URL) {
9 const { page, pageSize } = getPaginationParams(url);
10 const usageId = url.searchParams.get("usage_id");
11 * Main entry point for the usage dashboard
12 */
13export default async function(req: Request) {
14 // Check authentication first
15 const authResponse = await basicAuthMiddleware(req);
6 * Handle API requests
7 */
8export async function handleApiRequest(req: Request): Promise<Response> {
9 const url = new URL(req.url);
10 const path = url.pathname.replace("/api/", "");
1// Utility functions for formatting data in the dashboard
2
3/**
1export default function fileWithLineNumbers(text: string, view_range = []) {
2 return [
3 undefined, // Line numbers are 1-indexed
3import { TownieIcon } from "./components/icons.tsx";
4
5export default async function (loading: boolean) {
6 const svg = renderToString(
7 <TownieIcon color="#ffffff" circle={loading ? "#0EA5E9" : "#000000"} />
A helper function to build a file's email
Simple functional CSS library for Val Town
import { OpenAI } from "https://esm.town/v/std/openai";
export default async function(req: Request): Promise<Response> {
if (req.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
LangChain (https://langchain.com) Ambassador, KubeSphere (https://kubesphere.io) Ambassador, CNCF OpenFunction (https://openfunction.dev) TOC Member.