web-ui package

This commit is contained in:
Mario Zechner 2025-10-05 13:30:08 +02:00
parent 7159c9734e
commit f2eecb78d2
55 changed files with 10932 additions and 13 deletions

3
packages/web-ui/example/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules
dist
.DS_Store

View file

@ -0,0 +1,61 @@
# Pi Web UI - Example
This is a minimal example showing how to use `@mariozechner/pi-web-ui` in a web application.
## Setup
```bash
npm install
```
## Development
```bash
npm run dev
```
Open [http://localhost:5173](http://localhost:5173) in your browser.
## What's Included
This example demonstrates:
- **ChatPanel** - The main chat interface component
- **System Prompt** - Custom configuration for the AI assistant
- **Tools** - JavaScript REPL and artifacts tool
## Configuration
### API Keys
The example uses **Direct Mode** by default, which means it calls AI provider APIs directly from the browser.
To use the chat:
1. Click the settings icon (⚙️) in the chat interface
2. Click "Manage API Keys"
3. Add your API key for your preferred provider:
- **Anthropic**: Get a key from [console.anthropic.com](https://console.anthropic.com/)
- **OpenAI**: Get a key from [platform.openai.com](https://platform.openai.com/)
- **Google**: Get a key from [makersuite.google.com](https://makersuite.google.com/)
API keys are stored in your browser's localStorage and never sent to any server except the AI provider's API.
## Project Structure
```
example/
├── src/
│ ├── main.ts # Main application entry point
│ └── app.css # Tailwind CSS configuration
├── index.html # HTML entry point
├── package.json # Dependencies
├── vite.config.ts # Vite configuration
└── tsconfig.json # TypeScript configuration
```
## Learn More
- [Pi Web UI Documentation](../README.md)
- [Pi AI Documentation](../../ai/README.md)
- [Mini Lit Documentation](https://github.com/mariozechner/mini-lit)

View file

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pi Web UI - Example</title>
<meta name="description" content="Example usage of @mariozechner/pi-web-ui - Reusable AI chat interface" />
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

1965
packages/web-ui/example/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
{
"name": "pi-web-ui-example",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@mariozechner/mini-lit": "^0.1.7",
"@mariozechner/pi-ai": "file:../../ai",
"@mariozechner/pi-web-ui": "file:../",
"@tailwindcss/vite": "^4.1.13",
"lit": "^3.3.1",
"lucide": "^0.544.0"
},
"devDependencies": {
"typescript": "^5.7.3",
"vite": "^7.1.6"
}
}

View file

@ -0,0 +1 @@
@import "../../dist/app.css";

View file

@ -0,0 +1,51 @@
import { Button, icon } from "@mariozechner/mini-lit";
import "@mariozechner/mini-lit/dist/ThemeToggle.js";
import { ChatPanel, ApiKeysDialog } from "@mariozechner/pi-web-ui";
import { html, render } from "lit";
import { Settings } from "lucide";
import "./app.css";
const systemPrompt = `You are a helpful AI assistant with access to various tools.
Available tools:
- JavaScript REPL: Execute JavaScript code in a sandboxed browser environment (can do calculations, get time, process data, create visualizations, etc.)
- Artifacts: Create interactive HTML, SVG, Markdown, and text artifacts
Feel free to use these tools when needed to provide accurate and helpful responses.`;
// Create and configure the chat panel
const chatPanel = new ChatPanel();
chatPanel.systemPrompt = systemPrompt;
chatPanel.additionalTools = [];
// Render the app structure
const appHtml = html`
<div class="w-full h-screen flex flex-col bg-background text-foreground overflow-hidden">
<!-- Header -->
<div class="flex items-center justify-between border-b border-border shrink-0">
<div class="px-4 py-3">
<span class="text-base font-semibold text-foreground">Pi Web UI Example</span>
</div>
<div class="flex items-center gap-1 px-2">
<theme-toggle></theme-toggle>
${Button({
variant: "ghost",
size: "sm",
children: icon(Settings, "sm"),
onClick: () => ApiKeysDialog.open(),
title: "API Keys Settings",
})}
</div>
</div>
<!-- Chat Panel -->
${chatPanel}
</div>
`;
const app = document.getElementById("app");
if (!app) {
throw new Error("App container not found");
}
render(appHtml, app);

View file

@ -0,0 +1,104 @@
const simpleHtml = {
"systemPrompt": "You are a helpful AI assistant with access to various tools.\n\nAvailable tools:\n- Calculator: Perform mathematical calculations\n- Current Time: Get the current date and time in any timezone\n- Artifacts: Create interactive HTML, SVG, Markdown, and text artifacts\n\nFeel free to use these tools when needed to provide accurate and helpful responses.",
"model": {
"id": "claude-sonnet-4-5-20250929",
"name": "Claude Sonnet 4.5",
"api": "anthropic-messages",
"provider": "anthropic",
"baseUrl": "https://api.anthropic.com",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 3,
"output": 15,
"cacheRead": 0.3,
"cacheWrite": 3.75
},
"contextWindow": 200000,
"maxTokens": 64000
},
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "simple html"
}
]
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll create a simple HTML page for you!"
},
{
"type": "toolCall",
"id": "toolu_01JXaq9rMAUt1goJ5tMQXgLh",
"name": "artifacts",
"arguments": {
"command": "create",
"filename": "index.html",
"title": "Simple HTML Page",
"content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Simple HTML Page</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n background-color: #f5f5f5;\n }\n \n header {\n background-color: #4CAF50;\n color: white;\n padding: 20px;\n text-align: center;\n border-radius: 8px;\n }\n \n main {\n background-color: white;\n padding: 20px;\n margin-top: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n }\n \n button {\n background-color: #4CAF50;\n color: white;\n padding: 10px 20px;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 16px;\n }\n \n button:hover {\n background-color: #45a049;\n }\n </style>\n</head>\n<body>\n <header>\n <h1>Welcome to My Simple Page</h1>\n </header>\n \n <main>\n <h2>Hello!</h2>\n <p>This is a simple HTML page with some basic styling.</p>\n \n <h3>Features:</h3>\n <ul>\n <li>Clean design</li>\n <li>Responsive layout</li>\n <li>Interactive button</li>\n </ul>\n \n <button onclick=\"showMessage()\">Click Me!</button>\n <p id=\"message\"></p>\n </main>\n \n <script>\n function showMessage() {\n document.getElementById('message').textContent = '✨ Thanks for clicking!';\n }\n </script>\n</body>\n</html>"
}
}
],
"api": "anthropic-messages",
"provider": "anthropic",
"model": "claude-sonnet-4-5-20250929",
"usage": {
"input": 2108,
"output": 666,
"cacheRead": 0,
"cacheWrite": 0,
"cost": {
"input": 0.006324,
"output": 0.00999,
"cacheRead": 0,
"cacheWrite": 0,
"total": 0.016314000000000002
}
},
"stopReason": "toolUse"
},
{
"role": "toolResult",
"toolCallId": "toolu_01JXaq9rMAUt1goJ5tMQXgLh",
"toolName": "artifacts",
"output": "Created file index.html\n\nExecution timed out. Partial logs:\nKeine Logs für index.html",
"isError": false
},
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I've created a simple HTML page for you! It includes:\n\n- **Clean header** with a green background\n- **Main content area** with a white card-style design\n- **A list** showing some features\n- **An interactive button** that displays a message when clicked\n- **Responsive styling** that looks good on different screen sizes\n\nThe page has a light gray background and uses simple, clean styling. Try clicking the button to see it in action! \n\nWould you like me to modify anything or add more features?"
}
],
"api": "anthropic-messages",
"provider": "anthropic",
"model": "claude-sonnet-4-5-20250929",
"usage": {
"input": 2811,
"output": 115,
"cacheRead": 0,
"cacheWrite": 0,
"cost": {
"input": 0.008433,
"output": 0.001725,
"cacheRead": 0,
"cacheWrite": 0,
"total": 0.010158
}
},
"stopReason": "stop"
}
]
};

View file

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"useDefineForClassFields": false
},
"include": ["src/**/*"]
}

View file

@ -0,0 +1,6 @@
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [tailwindcss()],
});