Commit Graph

215 Commits

  • Fix race condition by making window.complete() async and awaiting it
    - window.complete() was fire-and-forget, causing execution-complete to arrive before console messages
    - This caused sandbox to unregister before console message responses arrived
    - Made complete() async and await sendRuntimeMessage()
    - SandboxedIframe wrapper now awaits window.complete()
    - Ensures all messages are processed before cleanup/unregister
    - Fixes 30-second timeout on javascript_repl
  • Fix ConsoleRuntimeProvider hanging by calling respond()
    - ConsoleRuntimeProvider.handleMessage() was not calling respond()
    - This caused sendRuntimeMessage() to hang waiting for response (30s timeout)
    - Now properly acknowledges console, execution-complete, and execution-error messages
    - Fixes javascript_repl hanging on simple console.log() calls
  • Unify completion callback pattern across browser-javascript and javascript-repl
    - Remove fallback timeout from ConsoleRuntimeProvider (was causing 2s delays)
    - Add completion callback support to SandboxedIframe REPL wrapper
    - Call completion callbacks before window.complete() in both success/error paths
    - Both browser-javascript and javascript-repl now use identical completion pattern
    - Ensures console logs are batched and sent before execution completes
  • Add onCompleted callback system for guaranteed console log delivery
    - Add onCompleted() callback registration in RuntimeMessageBridge
    - Modify wrapperFunction to call completion callbacks before returning
    - Update ConsoleRuntimeProvider to immediate send + completion batch pattern
    - Extract DOWNLOADABLE_FILE_RUNTIME_DESCRIPTION from ATTACHMENTS_RUNTIME_DESCRIPTION
    - Logs sent immediately (fire-and-forget), unsent logs batched at completion
    - Ensures all console logs arrive before tool execution completes
  • Add debug logging to RuntimeMessageRouter and increase API key validation tokens
    - Add console.log for user script messages in RuntimeMessageRouter
    - Increase ProviderKeyInput maxTokens from 10 to 200 for better validation
  • Add runtime bridge architecture and fix HTML escaping
    Major refactoring to unify runtime providers across sandbox and user script contexts:
    
    1. Runtime Bridge & Router
       - Add RuntimeMessageBridge for unified messaging abstraction
       - Rename SandboxMessageRouter → RuntimeMessageRouter
       - Router now handles both iframe and user script messages
       - Guard for non-extension environments
    
    2. Provider Refactoring
       - ArtifactsRuntimeProvider: Add offline mode with snapshot fallback
       - AttachmentsRuntimeProvider: Remove returnDownloadableFile (moved to dedicated provider)
       - ConsoleRuntimeProvider: Add message collection, remove lifecycle logic
       - FileDownloadRuntimeProvider: New provider for file downloads
    
    3. HTML Escaping Fix
       - Escape </script> in JSON.stringify output to prevent premature tag closure
       - Applies when injecting provider data into <script> tags
       - JavaScript engine automatically unescapes, no runtime changes needed
    
    4. Function Renaming
       - listFiles → listAttachments
       - readTextFile → readTextAttachment
       - readBinaryFile → readBinaryAttachment
       - returnFile → returnDownloadableFile
    
    5. Updated Exports
       - Export new RuntimeMessageBridge and RuntimeMessageRouter
       - Export FileDownloadRuntimeProvider
       - Update all cross-references
    
    This sets the foundation for reusing providers in browser-javascript tool.
  • Add image artifact support with proper binary downloads
    - Add ImageArtifact component for displaying images (.png, .jpg, .jpeg, .gif, .webp, .bmp, .ico)
    - Images stored as base64, displayed via data URLs
    - Download button properly decodes base64 to Uint8Array for valid binary downloads
    - Fix Lit ChildPart error: use CSS rotation instead of innerHTML manipulation in collapsible headers
    
    Changes:
    - web-ui/src/tools/artifacts/ImageArtifact.ts: New image artifact component
    - web-ui/src/tools/artifacts/artifacts.ts: Add "image" file type support
    - web-ui/src/tools/renderer-registry.ts: Fix collapsible chevron to use CSS rotation
    - web-ui/src/index.ts: Export ImageArtifact
  • Add artifact message persistence for session reconstruction
    - Add ArtifactMessage type as core part of AppMessage union (not CustomMessages)
    - ArtifactsRuntimeProvider appends artifact messages on create/update/delete
    - MessageList filters out artifact messages (UI display only)
    - artifacts.ts reconstructFromMessages handles artifact messages
    - Export ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION from main index
    - Fix artifact creation bug: pass filename as title instead of mimeType
    
    Changes:
    - web-ui/src/components/Messages.ts: Add ArtifactMessage to BaseMessage union
    - web-ui/src/components/MessageList.ts: Skip artifact messages in render
    - web-ui/src/components/sandbox/ArtifactsRuntimeProvider.ts: Append messages, fix title parameter
    - web-ui/src/ChatPanel.ts: Pass agent.appendMessage callback
    - web-ui/src/tools/artifacts/artifacts.ts: Handle artifact messages in reconstructFromMessages
    - web-ui/src/index.ts: Export ARTIFACTS_RUNTIME_PROVIDER_DESCRIPTION
    - web-ui/example/src/custom-messages.ts: Update message transformer to filter artifacts
  • Add ollama dependency and dialog backdrop blur
    - Add ollama package to web-ui dependencies for ModelSelector
    - Add backdrop blur to SettingsDialog (bg-black/50 backdrop-blur-sm)
    - Update mini-lit to 0.1.9 for backdropClassName prop support
    - Fix TypeScript errors in ModelSelector (ollama import, parameter types)
    - Add backward compatibility methods to SessionsStore (saveSession, loadSession, getLatestSessionId)
  • Fix IndexedDB in-line vs out-of-line key handling
    - Check if store has keyPath before calling put()
    - If keyPath exists (in-line keys), only pass value: store.put(value)
    - If no keyPath (out-of-line keys), pass both: store.put(value, key)
    - Apply fix to both set() and transaction.set()
    - Fixes DataError when saving sessions with keyPath: 'id'
  • Refactor to Store-based architecture
    - Create base Store class with private backend and protected getBackend()
    - Add SettingsStore, ProviderKeysStore, SessionsStore
    - Each store defines its own schema via getConfig()
    - AppStorage now takes stores + backend in constructor
    - Remove SessionsRepository (logic moved to SessionsStore)
    - Update all consumers to use store API (storage.settings.get/set, storage.providerKeys.get/set)
    - Update example app to follow new pattern: create stores, gather configs, create backend, wire
    - Benefits: stores own their schema, no circular deps, cleaner separation
  • Implement unified storage architecture
    - Replace fragmented storage backends with single IndexedDBStorageBackend
    - Create multi-store StorageBackend interface (storeName parameter)
    - Remove old backends: IndexedDBBackend, LocalStorageBackend, SessionIndexedDBBackend, WebExtensionStorageBackend
    - Remove old repositories: ProviderKeysRepository, SessionRepository, SettingsRepository
    - Simplify AppStorage to directly expose storage methods (getSetting/setSetting, getProviderKey/setProviderKey)
    - Create SessionsRepository for session-specific operations
    - Update all consumers to use new simplified API
    - Update example app to use new storage architecture
    - Benefits: 10GB+ quota (vs 10MB chrome.storage), single database, consistent API
  • Fix spinner showing on aborted tool calls in javascript-repl and artifacts renderers
    When isStreaming is false and there's no result (aborted state), show 'complete' state instead of 'inprogress' to avoid showing the spinner.
  • Prevent default and stop propagation when clicking artifact pill
    This prevents the collapsible header from toggling when the pill is clicked.
  • Make renderHeader and renderCollapsibleHeader accept string | TemplateResult
    - Update renderHeader and renderCollapsibleHeader in renderer-registry.ts to accept `text: string | TemplateResult`
    - Remove duplicated renderCollapsibleHeaderWithPill helper in artifacts-tool-renderer.ts
    - Update all artifact renderer calls to use renderHeaderWithPill() inline
    - Remove all separate pill rendering below headers
    
    This allows artifact pills to be rendered inline with header text without code duplication.
  • Add clickable artifact pills to tool renderer
    - Create ArtifactPill component (similar to SkillPill)
    - Renders filename as clickable pill with FileCode2 icon
    - Clicking pill opens artifacts panel and selects that artifact
    - Update ArtifactsToolRenderer to accept artifactsPanel reference
    - Pass artifactsPanel from ChatPanel to renderer on initialization
    - Display artifact pill below header for all commands
    - Pill only clickable when artifactsPanel reference is available
  • Update artifacts-tool-renderer to use collapsible headers
    - All actions except DELETE now use collapsible headers
    - CREATE/UPDATE/REWRITE/GET/LOGS: code/output collapsed by default
    - DELETE: keeps simple non-collapsible header
    - Fix isStreaming parameter usage for proper spinner state
    - Add smooth 300ms animation on expand/collapse
    - Full header is clickable to toggle collapse state
  • Make entire collapsible header clickable
    - Changed outer div to button element
    - Added w-full and text-left classes
    - Now click anywhere on header (icon, text, chevron) to expand/collapse
  • Add collapsible tool renderers with animated expand/collapse
    - Add renderCollapsibleHeader() to renderer-registry
      - Places chevron on right, spinner on left
      - Toggles between ChevronRight (collapsed) and ChevronDown (expanded)
      - Uses max-h-0/max-h-[2000px] with transition-all for smooth animation
      - Dynamically adds/removes mt-3 to avoid margin when collapsed
    
    - Update javascript-repl renderer to use collapsible sections
      - Code and console output hidden by default
      - Only file attachments remain visible
      - 300ms smooth animation on expand/collapse
    
    - Export renderCollapsibleHeader from web-ui index
  • Refactor artifacts renderer and add Console component
    - Extract ArtifactsToolRenderer from ArtifactsPanel into standalone renderer
    - Fix ChatPanel to register ArtifactsToolRenderer instead of panel
    - Implement command-specific rendering logic (create/update/rewrite/get/logs/delete)
    - Create reusable Console component with copy button and autoscroll toggle
    - Replace custom console implementation with ExpandableSection and Console
    - Fix Lit reactivity for HtmlArtifact logs using spread operator
    - Add Lucide icons (FileCode2, ChevronsDown, Lock) for UI consistency
    - Follow skill.ts patterns with renderHeader and state handling
    - Add i18n strings for all artifact actions and console features
  • Rename ChromeStorageBackend to WebExtensionStorageBackend for cross-browser support
    - Rename chrome-storage-backend.ts to web-extension-storage-backend.ts
    - Update to use globalThis.browser || globalThis.chrome for Firefox/Chrome compatibility
    - Export both names for backward compatibility
    - Fix tsc --preserveWatchOutput in web-ui dev script to prevent console clearing
    
    This fixes the "browser is not defined" error in Chrome extensions.
  • Make mini-lit a peer dependency in pi-web-ui
    - Move mini-lit from dependencies to peerDependencies
    - Keep in devDependencies for development
    - Prevents bundlers from including mini-lit when consuming pi-web-ui
    - Consumer (sitegeist) provides mini-lit, esbuild bundles it once
    - Fixes duplicate mini-lit bundling issue permanently
  • Clean up browser-extension references from monorepo
    - Update README.md to reference sitegeist repo
    - Update CLAUDE.md to replace browser-extension with web-ui
    - Update packages/web-ui/README.md examples to point to sitegeist
    - Remove browser-extension exclude from tsconfig.json
    - Remove browser-extension from .claude/settings.local.json permissions
  • Remove browser-extension package (migrated to separate sitegeist repo)
    - Remove packages/browser-extension directory
    - Update package.json scripts to remove browser-ext from build and dev
    - Extension now lives at https://github.com/badlogic/sitegeist
    - Uses file: dependencies to pi-ai and pi-web-ui for development
  • Fix navigation tracking and ChatPanel window width initialization
    Navigation tracking fixes:
    - Filter out chrome-extension:// URLs to avoid triggering on extension internal pages
    - Fixes "Could not establish connection" errors when sidepanel URL updates
    - Remove unused currentTabUrl/currentTabIndex tracking variables
    
    ChatPanel layout fixes:
    - Fix windowWidth initialization (was 0 due to too-early evaluation)
    - Set windowWidth in connectedCallback after DOM connection
    - Add requestAnimationFrame to ensure width is measured after layout
    - Add debug logging for troubleshooting layout issues
    - Now properly respects BREAKPOINT (800px) for mobile vs desktop layout
  • Simplify navigation tracking - insert message on every active tab URL change
    - Remove complex agent busy state tracking
    - Remove checkAndInsertNavMessage helper and onBeforeSend logic
    - Directly insert navigation messages when tab URL changes (chrome.tabs.onUpdated)
    - Also insert when user switches to a different tab (chrome.tabs.onActivated)
    - Much simpler: every URL change = navigation message, no conditions
    - Fixes issue where browser_javascript navigation wasn't detected
  • Insert navigation messages when agent finishes working (after tool execution)
    - Track agent busy state: isStreaming OR pendingToolCalls.size > 0
    - When agent transitions from busy to idle, check for URL changes
    - Extract checkAndInsertNavMessage() helper function
    - Call helper from both onBeforeSend (user submit) and agent state subscription (post-tool)
    - Fixes issue where browser_javascript tool navigates page but no nav message inserted
    - Navigation messages now appear after tools that change window.location.href
  • Only insert navigation messages on user message submit, not during idle browsing
    - Remove automatic navigation message insertion from tab change listeners
    - Tab listeners now only track current tab state (currentTabUrl, currentTabIndex)
    - Navigation messages are only inserted via onBeforeSend callback when user submits
    - Prevents spam of navigation messages when user is just browsing without interacting with agent
  • Improve navigation message visibility and favicon handling
    - Add fallback favicon using Google's favicon service (s2/favicons API)
    - If both tab.favIconUrl and Google service fail, gracefully hide broken image
    - Enhance navigation message styling for better visibility:
      - Use accent colors (bg-accent/50 with border-accent) instead of muted secondary
      - Increase padding (px-3 py-2) and add vertical margin (my-2)
      - Add shadow-sm for subtle depth
      - Make title font-medium for better contrast
      - Use border-2 instead of border for more prominence
  • Fix SessionListDialog behavior and document PersistentStorageDialog bug
    - Fix SessionListDialog to not reload when user selects a session after deleting others
      - Track if dialog closed via selection vs other means
      - Only call delete callback if not closed via selection
      - Batch deletions to avoid reload on every delete
    - Comment out PersistentStorageDialog in both web-ui example and browser extension (TODO: fix)
    - Add Known Bugs section to both README.md files documenting PersistentStorageDialog issue
    - Clean up navigation tracking variable names in browser extension
  • Fix new session button and improve navigation message styling
    - Add ?new=true query param to prevent auto-loading latest session
    - Style navigation message as clickable badge with background
    - Add cursor-pointer, truncate, and max-width for proper text overflow
    - Click navigation message to open page in new tab
    - Show URL on hover
  • Add navigation message tracking to browser extension
    - Add onBeforeSend callback to ChatPanel and AgentInterface
    - Add onBeforeToolCall callback (for future permission dialogs)
    - Create NavigationMessage custom message type
    - Add browserMessageTransformer that converts nav messages to <system> tags
    - Track last submitted URL and tab index
    - Auto-insert navigation message when URL/tab changes on user submit
    - Navigation message shows favicon + page title in UI
    - LLM receives: <system>Navigated to [title] (tab X): [url]</system>
  • Add custom message extension system with typed renderers and message transformer
    - Implement CustomMessages interface for type-safe message extension via declaration merging
    - Add MessageRenderer<T> with generic typing for custom message rendering
    - Add messageTransformer to Agent for filtering/transforming messages before LLM
    - Move message filtering from transports to Agent (separation of concerns)
    - Add message renderer registry with typed role support
    - Update web-ui example with SystemNotificationMessage demo
    - Add custom transformer that converts notifications to <system> tags
    - Add SessionListDialog onDelete callback for active session cleanup
    - Handle non-existent session IDs in URL (redirect to new session)
    - Update both web-ui example and browser extension with session fixes
  • Refactor agent architecture and add session storage
    Major architectural improvements:
    - Renamed AgentSession → Agent (state/ → agent/)
    - Removed id field from AgentState
    - Fixed transport abstraction to pass messages directly instead of using callbacks
    - Eliminated circular dependencies in transport creation
    
    Transport changes:
    - Changed signature: run(messages, userMessage, config, signal)
    - Removed getMessages callback from ProviderTransport and AppTransport
    - Transports now filter attachments internally
    
    Session storage:
    - Added SessionRepository with IndexedDB backend
    - Auto-save sessions after first exchange
    - Auto-generate titles from first user message
    - Session list dialog with search and delete
    - Persistent storage permission dialog
    - Browser extension now auto-loads last session
    
    UI improvements:
    - ChatPanel creates single AgentInterface instance in setAgent()
    - Added drag & drop file upload to MessageEditor
    - Fixed artifacts panel auto-opening on session load
    - Added "Drop files here" i18n strings
    - Changed "Continue Without Saving" → "Continue Anyway"
    
    Web example:
    - Complete rewrite of main.ts with clean architecture
    - Added check script to package.json
    - Session management with URL state
    - Editable session titles
    
    Browser extension:
    - Added full session storage support
    - History and new session buttons
    - Auto-load most recent session on open
    - Session titles in header