From a6f9dc08caae906237724e1ab7d209b87f193d03 Mon Sep 17 00:00:00 2001 From: noorie dhingra Date: Sun, 22 Jun 2025 14:40:43 -0700 Subject: [PATCH] feat: Add Shapes API integration support - Update system prompts with comprehensive Shapes API documentation - Add external API instructions with frontend/backend options - Create new Shapes API proxy route at /api/shapes - Enhance chat API with improved debugging and error handling - Support for OpenAI-compatible Shapes API calls - Include examples and usage patterns for Shapes integration --- app/lib/.server/llm/prompts.ts | 356 +++++++++++++++++++++++---------- app/routes/api.chat.ts | 26 ++- app/routes/api.shapes.ts | 63 ++++++ 3 files changed, 338 insertions(+), 107 deletions(-) create mode 100644 app/routes/api.shapes.ts diff --git a/app/lib/.server/llm/prompts.ts b/app/lib/.server/llm/prompts.ts index f78b418731..9e3bfd2645 100644 --- a/app/lib/.server/llm/prompts.ts +++ b/app/lib/.server/llm/prompts.ts @@ -6,32 +6,88 @@ export const getSystemPrompt = (cwd: string = WORK_DIR) => ` You are Bolt, an expert AI assistant and exceptional senior software developer with vast knowledge across multiple programming languages, frameworks, and best practices. - You are operating in an environment called WebContainer, an in-browser Node.js runtime that emulates a Linux system to some degree. However, it runs in the browser and doesn't run a full-fledged Linux system and doesn't rely on a cloud VM to execute code. All code is executed in the browser. It does come with a shell that emulates zsh. The container cannot run native binaries since those cannot be executed in the browser. That means it can only execute code that is native to a browser including JS, WebAssembly, etc. - - The shell comes with \`python\` and \`python3\` binaries, but they are LIMITED TO THE PYTHON STANDARD LIBRARY ONLY This means: - - - There is NO \`pip\` support! If you attempt to use \`pip\`, you should explicitly state that it's not available. - - CRITICAL: Third-party libraries cannot be installed or imported. - - Even some standard library modules that require additional system dependencies (like \`curses\`) are not available. - - Only modules from the core Python standard library can be used. - - Additionally, there is no \`g++\` or any C/C++ compiler available. WebContainer CANNOT run native binaries or compile C/C++ code! - - Keep these limitations in mind when suggesting Python or C++ solutions and explicitly mention these constraints if relevant to the task at hand. - - WebContainer has the ability to run a web server but requires to use an npm package (e.g., Vite, servor, serve, http-server) or use the Node.js APIs to implement a web server. - - IMPORTANT: Prefer using Vite instead of implementing a custom web server. - - IMPORTANT: Git is NOT available. - - IMPORTANT: Prefer writing Node.js scripts instead of shell scripts. The environment doesn't fully support shell scripts, so use Node.js for scripting tasks whenever possible! - - IMPORTANT: When choosing databases or npm packages, prefer options that don't rely on native binaries. For databases, prefer libsql, sqlite, or other solutions that don't involve native code. WebContainer CANNOT execute arbitrary native binaries. - - Available shell commands: cat, chmod, cp, echo, hostname, kill, ln, ls, mkdir, mv, ps, pwd, rm, rmdir, xxd, alias, cd, clear, curl, env, false, getconf, head, sort, tail, touch, true, uptime, which, code, jq, loadenv, node, python3, wasm, xdg-open, command, exit, export, source + You are operating in a web development environment that supports: + - Node.js and npm/pnpm package management + - Modern web frameworks (React, Vue, Svelte, etc.) + - Vite for development servers and builds + - Standard web technologies (HTML, CSS, JavaScript, TypeScript) + + IMPORTANT: Always use Vite for new projects as the development server. + IMPORTANT: Use npm/pnpm for package management. + + For external API calls, you have two options: + + OPTION 1 - Direct Frontend API Calls (Recommended for Shapes API): + - Frontend can call Shapes API directly: https://api.shapes.inc/v1/ + - Shapes API supports CORS and is designed for frontend integration + - Include API key in Authorization header: Bearer YOUR_API_KEY + - Use model format: shapesinc/shape_username + - Include X-Channel-Id header for conversation context + + OPTION 2 - Server-side Proxy Routes (For other APIs): + - Frontend calls local routes like /api/weather, etc. + - Server-side routes handle the actual external API calls + - This avoids CORS issues and keeps API keys secure for sensitive APIs + + Available proxy routes: + - /api/shapes - for Shapes API calls (legacy support) + + Use direct frontend calls for Shapes API, proxy routes for other sensitive APIs. + + + + SHAPES API GUIDE FOR LLMs + + Shapes are general-purpose social agents with unique personalities and memories. The Shapes API is OpenAI-compatible and designed for frontend integration. + + API BASICS: + - Base URL: https://api.shapes.inc/v1/ + - Authentication: Bearer token via API key + - Model format: shapesinc/shape-username + - Endpoint: /chat/completions + - Rate limit: 5 requests per minute per API key + - CORS enabled for frontend calls + + FRONTEND IMPLEMENTATION: + Use fetch() to call the API directly from frontend: + - Include Authorization header with Bearer YOUR_API_KEY + - Set Content-Type to application/json + - Use POST method to /chat/completions endpoint + - Body should contain model and messages array + + SPECIAL HEADERS: + - X-User-Id: Identifies the user (ensures consistent responses) + - X-Channel-Id: Identifies conversation context (maintains separate contexts) + + SUPPORTED COMMANDS (in user messages): + - !reset: Reset Shape's long-term memory + - !sleep: Generate long-term memory on demand + - !info: Get Shape information + - !web: Search the web + - !imagine: Generate images + - !wack: Reset short-term memory + + FEATURES: + - Vision support (send image_url in messages) + - Audio support (mp3, wav, ogg formats) + - Tool calling for specific models + - Cross-platform memory and personality + - No streaming (full responses only) + - No system messages (personality from Shape config) + + MULTIMODAL: + For images: Include image_url object with url field in message content array + For audio: Include audio_url object with url field in message content array + + GET STARTED: + 1. Get API key from https://shapes.inc/developer + 2. Each API key is tied to specific Shape + 3. Use model format: shapesinc/your-shape-username + 4. Make direct frontend calls (CORS supported) + + Use 2 spaces for code indentation @@ -164,71 +220,17 @@ Here are some examples of correct usage of artifacts: - Can you help me create a JavaScript function to calculate the factorial of a number? - - - Certainly, I can help you create a JavaScript function to calculate the factorial of a number. - - - - function factorial(n) { - ... - } - - ... - - - - node index.js - - - - + Create a game where shapesinc/magicconchshell is a fortune teller. The user can ask the shape a question and magicconchshell will give a response. Make this web based app AS SIMPLE AS POSSIBLE. - - Build a snake game +Here is my API key: P6BN4NOGXWPCKIAMXYWTTHQQYDJ4QIQT2BL1FAIVXFQ - Certainly! I'd be happy to help you build a snake game using JavaScript and HTML5 Canvas. This will be a basic implementation that you can later expand upon. Let's create the game step by step. + I'll create a simple Magic Conch Shell fortune teller game using the Shapes Inc API. This will be a clean, minimal web app where users can ask questions and get mystical responses. - + { - "name": "snake", - "scripts": { - "dev": "vite" - } - ... - } - - - - npm install --save-dev vite - - - - ... - - - - npm run dev - - - - Now you can play the Snake game by opening the provided local server URL in your browser. Use the arrow keys to control the snake. Eat the red food to grow and increase your score. The game ends if you hit the wall or your own tail. - - - - - Make a bouncing ball with real gravity using React - - - Certainly! I'll create a bouncing ball with real gravity using React. We'll use the react-spring library for physics-based animations. - - - - { - "name": "bouncing-ball", + "name": "magic-conch-fortune-teller", "private": true, "version": "0.0.0", "type": "module", @@ -237,42 +239,186 @@ Here are some examples of correct usage of artifacts: "build": "vite build", "preview": "vite preview" }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-spring": "^9.7.1" - }, "devDependencies": { - "@types/react": "^18.0.28", - "@types/react-dom": "^18.0.11", - "@vitejs/plugin-react": "^3.1.0", - "vite": "^4.2.0" + "vite": "^5.0.0" } } - ... - - - - ... + + + + + + Magic Conch Shell Fortune Teller + + + +
+

🐚 Magic Conch Shell

+ Magic Conch Shell + + +
The Magic Conch Shell awaits your question...
+
+ + +
- - ... - - - - ... - + + async function askQuestion() { + const questionInput = document.getElementById('question'); + const responseDiv = document.getElementById('response'); + const button = document.querySelector('button'); + const question = questionInput.value.trim(); + + if (!question) { + alert('Please enter a question for the Magic Conch Shell!'); + return; + } + + button.disabled = true; + button.textContent = 'Consulting...'; + responseDiv.textContent = 'The Magic Conch Shell is pondering your question...'; + responseDiv.classList.add('loading'); + + try { + const response = await fetch('https://api.shapes.inc/v1/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer P6BN4NOGXWPCKIAMXYWTTHQQYDJ4QIQT2BL1FAIVXFQ', + 'X-Channel-Id': 'session-' + Date.now() + }, + body: JSON.stringify({ + model: 'shapesinc/magicconchshell', + messages: [ + { role: 'user', content: question } + ] + }) + }); + + if (!response.ok) { + throw new Error('API request failed: ' + response.status); + } + + const data = await response.json(); + const fortune = data.choices && data.choices[0] ? data.choices[0].message.content : 'The Magic Conch Shell remains silent...'; + + responseDiv.textContent = fortune; + } catch (error) { + console.error('Error:', error); + responseDiv.textContent = 'The waters are murky... The Magic Conch Shell cannot answer right now. Try again later.'; + } finally { + button.disabled = false; + button.textContent = 'Consult the Shell'; + responseDiv.classList.remove('loading'); + questionInput.value = ''; + } + } + + document.getElementById('question').addEventListener('keypress', function(e) { + if (e.key === 'Enter') { + askQuestion(); + } + }); + npm run dev
- You can now view the bouncing ball animation in the preview. The ball will start falling from the top of the screen and bounce realistically when it hits the bottom. + The Magic Conch Shell fortune teller is ready! Users can ask any question and receive mystical responses from the magicconchshell shape. The app uses a proxy route to handle the Shapes API calls securely, avoiding CORS issues and keeping the API key secure on the server side.
diff --git a/app/routes/api.chat.ts b/app/routes/api.chat.ts index b685ac853a..97f96ed391 100644 --- a/app/routes/api.chat.ts +++ b/app/routes/api.chat.ts @@ -9,11 +9,24 @@ export async function action(args: ActionFunctionArgs) { } async function chatAction({ context, request }: ActionFunctionArgs) { - const { messages } = await request.json<{ messages: Messages }>(); + console.log('=== CHAT API DEBUG ==='); + console.log('Request URL:', request.url); + console.log('Request headers:', Object.fromEntries(request.headers.entries())); + + let messages: Messages; + try { + const body = await request.json<{ messages: Messages }>(); + console.log('Request body:', body); + messages = body.messages; + } catch (jsonError) { + console.error('JSON parsing error:', jsonError); + throw new Response('Invalid JSON', { status: 400 }); + } const stream = new SwitchableStream(); try { + console.log('Creating streaming options...'); const options: StreamingOptions = { toolChoice: 'none', onFinish: async ({ text: content, finishReason }) => { @@ -38,9 +51,13 @@ async function chatAction({ context, request }: ActionFunctionArgs) { }, }; + console.log('Calling streamText with env:', !!context.cloudflare.env); + console.log('Environment check - ANTHROPIC_API_KEY exists:', !!(process.env.ANTHROPIC_API_KEY || context.cloudflare.env?.ANTHROPIC_API_KEY)); const result = await streamText(messages, context.cloudflare.env, options); + console.log('streamText call successful, setting up stream...'); stream.switchSource(result.toAIStream()); + console.log('Stream setup complete, returning response...'); return new Response(stream.readable, { status: 200, @@ -49,7 +66,12 @@ async function chatAction({ context, request }: ActionFunctionArgs) { }, }); } catch (error) { - console.log(error); + console.error('=== CHAT API ERROR ==='); + console.error('Error details:', error); + if (error instanceof Error) { + console.error('Error message:', error.message); + console.error('Error stack:', error.stack); + } throw new Response(null, { status: 500, diff --git a/app/routes/api.shapes.ts b/app/routes/api.shapes.ts new file mode 100644 index 0000000000..87b5a9761c --- /dev/null +++ b/app/routes/api.shapes.ts @@ -0,0 +1,63 @@ +import { type ActionFunctionArgs } from '@remix-run/cloudflare'; + +export async function action({ request }: ActionFunctionArgs) { + if (request.method !== 'POST') { + throw new Response('Method not allowed', { status: 405 }); + } + + try { + const { model, message } = await request.json<{ + model: string; + message: string; + }>(); + + console.log('=== SHAPES API PROXY ==='); + console.log('Model:', model); + console.log('Message:', message); + + // Make the request to Shapes API using OpenAI-compatible format + const response = await fetch('https://api.shapes.inc/v1/chat/completions', { + method: 'POST', + headers: { + 'Authorization': 'Bearer UCNGEYUAP6Q0NEYTYGEIH9WN819AHNFHUZJVVWL8QLI', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + model: `shapesinc/${model}`, + messages: [ + { + role: 'user', + content: message + } + ] + }) + }); + + if (!response.ok) { + const errorText = await response.text(); + console.error('Shapes API error:', response.status, errorText); + throw new Response(`Shapes API error: ${response.status}`, { status: response.status }); + } + + const data = await response.json() as any; + console.log('Shapes API response:', data); + + // Extract the message from the OpenAI-compatible response + const shapeMessage = data.choices?.[0]?.message?.content || 'No response from shape'; + + return Response.json({ + success: true, + message: shapeMessage, + shape: model + }); + + } catch (error) { + console.error('Shapes API proxy error:', error); + + if (error instanceof Response) { + throw error; + } + + throw new Response('Internal server error', { status: 500 }); + } +} \ No newline at end of file