Search
Code3,144
import { registerCommands } from "./discord-commands.ts";import { log, getEnv } from "../shared/utils.ts";import { initializeAnthropic } from "./anthropic-service.ts";// Create Hono app log("Database initialized successfully", "info"); // Initialize Anthropic client initializeAnthropic(); // Log successful initialization// Anthropic service integration for Val.townimport Anthropic from "https://esm.sh/@anthropic-ai/sdk@0.16.1";import { getEnv, log, truncateText } from "../shared/utils.ts";import type { ClaudeOptions, MessageRecord, SummaryResult } from "../shared/types.ts";// Initialize Anthropic clientlet anthropic: any;/** * Initialize the Anthropic client */export function initializeAnthropic() { if (!anthropic) { const apiKey = getEnv("ANTHROPIC_API_KEY"); if (!apiKey) { throw new Error("ANTHROPIC_API_KEY environment variable is required"); } anthropic = new Anthropic({ apiKey, }); log("Anthropic client initialized", "info"); } return anthropic;}/** * Process a message with Anthropic Claude * @param prompt - The prompt to send to Claude * @param options - Additional optionsexport async function processWithClaude(prompt: string, options: ClaudeOptions = {}): Promise<string> { try { const client = initializeAnthropic(); // Ensure the prompt isn't too long// Query service for Val.townimport { getMessages, getLinks } from "./database.ts";import { analyzeConversation, summarizeConversation } from "./anthropic-service.ts";/** const links = getLinks(linkFilters); // If no specific categories, use Anthropic to help filter relevant links if ((!categories || categories.length === 0) && links.length > 0) { const relevantLinks = await filterRelevantLinks(links, query); try { // Use Anthropic to analyze the conversation const result = await analyzeConversation(messages.slice(0, 50), query); const messages = getMessages(filters); // Use Anthropic to generate a summary try { const summaryResult = await summarizeConversation(messages.slice(0, 100), query); }); // Use Anthropic to analyze furniture-related content try { // Create prompt for furniture analysis const messages = getMessages(filters); // Use Anthropic to analyze messages try { // Direct analysis of messages with Claude project: any; branchId: string | undefined; anthropicApiKey: string; bearerToken: string; selectedFiles: string[]; project, branchId, anthropicApiKey, bearerToken, selectedFiles, project, branchId, anthropicApiKey, selectedFiles, images: imagesconst TOKEN_KEY = "bearer";const ANTHROPIC_KEY = "anthropic_api_key";export function useAuth () { const [token, setToken, removeToken] = useLocalStorage(TOKEN_KEY, ""); const [anthropicApiKey, setAnthropicApiKey, removeAnthropicApiKey] = useLocalStorage(ANTHROPIC_KEY, ""); const [error, setError] = useState(null); const isAuthenticated = !!token && !!anthropicApiKey; const authenticate = async (valTownAPIKey: string, anthropicKey: string) => { // replace all this with oauth when it's ready try { setError(data.error); removeToken(); removeAnthropicApiKey(); return; } setError(null); setToken(valTownAPIKey); setAnthropicApiKey(anthropicKey); } catch (e) { console.error(e); setError(e.error); removeToken(); removeAnthropicApiKey(); } } const logOut = () => { removeToken(); removeAnthropicApiKey(); } logOut, token, anthropicApiKey, };}- [x] Add a "view source" / "send me a PR" link- [x] Show the HTTP preview in second column if there is one (and let the user pick which one to preview in the iframe)- [x] Figure out a convention to teach in the anthropic prompt mod where the LLM always checks the readme for the scope (if not provided) and keeps it up to take with every change- [x] Ability to create new projects from the interface- [x] Figure out why OpenTownie can't create HTTP vals. Maybe give it a seperate tool for it?- [x] Start a timer for messages- [x] Add more indicators that it's "still working"- [x] Require users supply their own Anthropic token?- [x] Add cost indications on messages- [x] Add a bell noise when the message is done to let us knowimport { anthropic } from "npm:@ai-sdk/anthropic";import { ValTown } from "npm:@valtown/sdk@0.37.0";import fileWithLinesNumbers from "../utils/fileWithLinesNumbers.ts";export function getTextEditorTool(bearerToken: string, project: any, branch_id: string | undefined) { const vt = new ValTown({ bearerToken }); return anthropic.tools.textEditor_20250124({ execute: async ({ command,## How It Works1. **Login**: Authenticate with your Val Town API token and Anthropic API key2. **Select a Project**: Choose which Val Town project you want to work on3. **Select Files**: Browse your project files and select which ones to include in the context window- A Val Town account with API access- An Anthropic API key (Claude 3.7 Sonnet)### Setup1. Visit the OpenTownie app2. Enter your Val Town API token (with `projects:write` and `users:read` permissions)3. Enter your Anthropic API key4. Click "Login" to access your projects- AI SDK for Claude integrationThe application proxies requests to the Anthropic API and Val Town API, allowing Claude to view and edit your project files directly.## Privacy & Security- Your Val Town API token and Anthropic API key are stored locally in your browser- No data is stored on our servers- All communication with the APIs is done directly from your browser <ol> <li>Login with your Val Town API token</li> <li>Add your Anthropic API key</li> <li>Select a project to work on</li> <li>Chat with Claude about your code</li> </ul> <p > The application proxies requests to the Anthropic API and Val Town API, allowing Claude to view and edit your project files directly. </p> <div > refetch: () => void;}) { const { token, anthropicApiKey } = useAuth(); const [images, setImages] = useState<(string|null)[]>([]); const [selectedFiles, setSelectedFiles] = useState<string[]>([]); project, branchId, anthropicApiKey, bearerToken: token, selectedFiles,