Storage Architecture:
- New pluggable storage system with backends (LocalStorage, ChromeStorage, IndexedDB)
- SettingsRepository for app settings (proxy config, etc.)
- ProviderKeysRepository for API key management
- AppStorage with global accessors (getAppStorage, setAppStorage, initAppStorage)
Transport Refactoring:
- Renamed DirectTransport → ProviderTransport (calls LLM providers with optional CORS proxy)
- Renamed ProxyTransport → AppTransport (uses app server with user auth)
- Updated TransportMode: "direct" → "provider", "proxy" → "app"
CORS Proxy Integration:
- ProviderTransport checks proxy.enabled/proxy.url from storage
- When enabled, modifies model baseUrl to route through proxy: {proxyUrl}/?url={originalBaseUrl}
- ProviderKeyInput test function also honors proxy settings
- Settings dialog with Proxy tab (Switch toggle, URL input, explanatory description)
Anthropic Prompt Caching:
- System prompt cached with cache_control markers (both OAuth and regular API keys)
- Last user message cached to cache conversation history
- Saves 90% on input tokens for cached content (10x cost reduction)
Settings Dialog Improvements:
- Configurable tab system with SettingsTab base class
- ApiKeysTab and ProxyTab as custom elements
- Switch toggle for proxy enable (instead of Checkbox)
- Explanatory paragraphs for each tab
- ApiKeyPromptDialog reuses ProviderKeyInput component
Removed:
- Deprecated ApiKeysDialog (replaced by ProviderKeyInput in SettingsDialog)
- Old storage-adapter and key-store (replaced by new storage architecture)
|
||
|---|---|---|
| .. | ||
| example | ||
| src | ||
| package.json | ||
| README.md | ||
| tsconfig.build.json | ||
| tsconfig.json | ||
@mariozechner/pi-web-ui
Reusable web UI components for building AI chat interfaces powered by @mariozechner/pi-ai.
Built with mini-lit web components and Tailwind CSS v4.
Features
- 🎨 Modern Chat Interface - Complete chat UI with message history, streaming responses, and tool execution
- 🔧 Tool Support - Built-in renderers for calculator, bash, time, and custom tools
- 📎 Attachments - PDF, Office documents, images with preview and text extraction
- 🎭 Artifacts - HTML, SVG, Markdown, and text artifact rendering with sandboxed execution
- 🔌 Pluggable Transports - Direct API calls or proxy server support
- 🌐 Platform Agnostic - Works in browser extensions, web apps, VS Code extensions, Electron apps
- 🎯 TypeScript - Full type safety with TypeScript
Installation
npm install @mariozechner/pi-web-ui
Quick Start
See the example directory for a complete working application.
import { ChatPanel } from '@mariozechner/pi-web-ui';
import { calculateTool, getCurrentTimeTool } from '@mariozechner/pi-ai';
import '@mariozechner/pi-web-ui/app.css';
// Create a chat panel
const chatPanel = new ChatPanel();
chatPanel.systemPrompt = 'You are a helpful assistant.';
chatPanel.additionalTools = [calculateTool, getCurrentTimeTool];
document.body.appendChild(chatPanel);
Run the example:
cd example
npm install
npm run dev
Core Components
ChatPanel
The main chat interface component. Manages agent sessions, model selection, and conversation flow.
import { ChatPanel } from '@mariozechner/pi-web-ui';
const panel = new ChatPanel({
initialModel: 'anthropic/claude-sonnet-4-20250514',
systemPrompt: 'You are a helpful assistant.',
transportMode: 'direct', // or 'proxy'
});
AgentInterface
Lower-level chat interface for custom implementations.
import { AgentInterface } from '@mariozechner/pi-web-ui';
const chat = new AgentInterface();
chat.session = myAgentSession;
State Management
AgentSession
Manages conversation state, tool execution, and streaming.
import { AgentSession, DirectTransport } from '@mariozechner/pi-web-ui';
import { getModel, calculateTool, getCurrentTimeTool } from '@mariozechner/pi-ai';
const session = new AgentSession({
initialState: {
model: getModel('anthropic', 'claude-3-5-haiku-20241022'),
systemPrompt: 'You are a helpful assistant.',
tools: [calculateTool, getCurrentTimeTool],
messages: [],
},
transportMode: 'direct',
});
// Subscribe to state changes
session.subscribe((state) => {
console.log('Messages:', state.messages);
console.log('Streaming:', state.streaming);
});
// Send a message
await session.send('What is 25 * 18?');
Transports
Transport layers handle communication with AI providers.
DirectTransport
Calls AI provider APIs directly from the browser using API keys stored locally.
import { DirectTransport, KeyStore } from '@mariozechner/pi-web-ui';
// Set API keys
const keyStore = new KeyStore();
await keyStore.setKey('anthropic', 'sk-ant-...');
await keyStore.setKey('openai', 'sk-...');
// Use direct transport (default)
const session = new AgentSession({
transportMode: 'direct',
// ...
});
ProxyTransport
Routes requests through a proxy server using auth tokens.
import { ProxyTransport, setAuthToken } from '@mariozechner/pi-web-ui';
// Set auth token
setAuthToken('your-auth-token');
// Use proxy transport
const session = new AgentSession({
transportMode: 'proxy',
// ...
});
Tool Renderers
Customize how tool calls and results are displayed.
import { registerToolRenderer, type ToolRenderer } from '@mariozechner/pi-web-ui';
import { html } from '@mariozechner/mini-lit';
const myRenderer: ToolRenderer = {
renderParams(params, isStreaming) {
return html`<div>Calling tool with: ${JSON.stringify(params)}</div>`;
},
renderResult(params, result) {
return html`<div>Result: ${result.output}</div>`;
}
};
registerToolRenderer('my_tool', myRenderer);
Artifacts
Render rich content with sandboxed execution.
import { artifactTools } from '@mariozechner/pi-web-ui';
import { getModel } from '@mariozechner/pi-ai';
const session = new AgentSession({
initialState: {
tools: [...artifactTools],
// ...
}
});
// AI can now create HTML artifacts, SVG diagrams, etc.
Styling
The package includes pre-built Tailwind CSS with the Claude theme:
import '@mariozechner/pi-web-ui/app.css';
Or customize with your own Tailwind config:
@import '@mariozechner/mini-lit/themes/claude.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
Platform Integration
Browser Extension
import { ChatPanel, KeyStore } from '@mariozechner/pi-web-ui';
// Use chrome.storage for persistence
const keyStore = new KeyStore({
get: async (key) => {
const result = await chrome.storage.local.get(key);
return result[key];
},
set: async (key, value) => {
await chrome.storage.local.set({ [key]: value });
}
});
Web Application
import { ChatPanel } from '@mariozechner/pi-web-ui';
// Uses localStorage by default
const panel = new ChatPanel();
document.querySelector('#app').appendChild(panel);
VS Code Extension
import { AgentSession, DirectTransport } from '@mariozechner/pi-web-ui';
// Custom storage using VS Code's globalState
const storage = {
get: async (key) => context.globalState.get(key),
set: async (key, value) => context.globalState.update(key, value)
};
Examples
See the browser-extension package for a complete implementation example.
API Reference
See src/index.ts for the full public API.
License
MIT