Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,55 @@ Uses OpenAI chat completions format with tool support:
- Verify temperature is set to 0.1 for consistent results
- Tests expect multiple tool calls for comprehensive validation

### Logging
### Debug Logging System

- Background script logs appear in service worker console
- Sidepanel logs appear in sidepanel DevTools console
- Use `console.log()` for debugging (remove in production)
The extension features a comprehensive debug logging system that works across all contexts (background, sidepanel, content scripts, options).

#### Using the Debug Logger

```typescript
// Import the logger
import { backgroundLogger, sidepanelLogger, contentLogger, optionsLogger } from '~/utils/debug-logger';
// Or use the context-aware logger
import { getContextLogger } from '~/utils/debug-logger';

// Use the appropriate logger for your context
const logger = backgroundLogger; // or getContextLogger() for automatic detection

// Log at different levels
logger.debug('Debug information', { data: 'example' });
logger.info('Information message', { userId: 123 });
logger.warn('Warning message', { issue: 'performance' });
logger.error('Error occurred', new Error('Something went wrong')); // Automatically captures stack traces
```

#### Viewing Debug Logs

1. **In Sidepanel**: Click the debug icon (🐛) in the header to open the debug log viewer
2. **In DevTools**: Logs also appear in the browser console for immediate debugging
3. **Export Logs**: Use the export button in the debug viewer to save logs as JSON

#### Debug Viewer Features

- **Real-time filtering** by log level (debug, info, warn, error)
- **Context filtering** by source (background, sidepanel, content, options)
- **Text search** through log messages and data
- **Time-based filtering** (last hour, last 10 minutes, all time)
- **Auto-refresh** for live log monitoring
- **Export functionality** for sharing or analysis

#### Configuration

- **Max Log Entries**: Configurable limit (default: 10,000 entries)
- **Auto-pruning**: Old entries are automatically removed when limit is exceeded
- **Persistent Storage**: Logs survive extension restarts and browser sessions

#### Performance Considerations

- Logs are stored efficiently using chunked storage
- Only recent entries are kept in memory
- Background logging has minimal performance impact
- Type validation ensures data integrity

## Contributing

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ https://github.com/user-attachments/assets/7a584180-e8dd-4c7f-838a-efd051fa2968

## Quick Start

Ready-to-use extension builds are available in the releases section. For development setup, see [DEVELOPMENT.md](DEVELOPMENT.md).
Currently there aren't ready-to-use extension builds.

If you want to see a quick demo, go to Google.com and type `click Reject All, search fluffy robots, and tell me which 3 are the most popular`
For development setup, see [DEVELOPMENT.md](DEVELOPMENT.md).

Once you got the extension running, if you want to see a quick demo go to Google.com and type `click Reject All, search fluffy robots, and tell me which 3 are the most popular`

## Installation

Expand Down
63 changes: 30 additions & 33 deletions entrypoints/sidepanel/ChatInterface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
MessageToSidebar,
} from '~/utils/types';
import { createStableId, isExtensionSettings } from '~/utils/types';
import DebugLogViewer from './components/DebugLogViewer';
import ManualToolInterface from './ManualToolInterface';
import { MemoizedMarkdown } from './MemoizedMarkdown';

Expand Down Expand Up @@ -278,6 +279,8 @@ const ChatInterface: React.FC = () => {
const [isLoading, setIsLoading] = useState(false);
const [status, setStatus] = useState<{ text: string; type?: 'error' | 'thinking' }>({ text: '' });
const [tabId, setTabId] = useState<number | null>(null);
const [showDebugLogs, setShowDebugLogs] = useState(false);
const [showToolsPanel, setShowToolsPanel] = useState(false);

const messagesEndRef = useRef<HTMLDivElement>(null);
const isRefreshingRef = useRef(false);
Expand All @@ -295,12 +298,6 @@ const ChatInterface: React.FC = () => {

const getTabChatHistory = useCallback(
(settings: ExtensionSettings | null, currentTabId: number | null): ChatMessage[] => {
sidepanelLogger.debug('getTabChatHistory called', {
hasSettings: !!settings,
currentTabId,
settingsType: typeof settings,
});

if (!settings) {
sidepanelLogger.debug('No settings, returning empty array');
return [];
Expand All @@ -314,12 +311,6 @@ const ChatInterface: React.FC = () => {
}

const tabConversations = settings.tabConversations?.[currentTabId.toString()];
sidepanelLogger.debug('Tab conversations lookup', {
hasTabConversations: !!settings.tabConversations,
tabKey: currentTabId.toString(),
foundConversation: !!tabConversations,
conversationLength: tabConversations?.length || 0,
});

return tabConversations || [];
},
Expand Down Expand Up @@ -560,18 +551,9 @@ const ChatInterface: React.FC = () => {
};

const renderAssistantMessage = (message: ChatMessage) => {
sidepanelLogger.debug('renderAssistantMessage called', {
messageId: message.id,
hasContent: !!message.content,
});

// Process AI SDK UI parts structure
const messageWithParts = message as StreamingChatMessageWithParts;
if (messageWithParts.parts && Array.isArray(messageWithParts.parts)) {
sidepanelLogger.debug('Processing message parts (AI SDK UI)', {
partCount: messageWithParts.parts.length,
});

return (
<div className="assistant-message">
{messageWithParts.parts.map((part: MessagePart, index: number) => (
Expand Down Expand Up @@ -601,23 +583,41 @@ const ChatInterface: React.FC = () => {
<header className="chat-header">
<h1>LLM Chat</h1>
<div className="header-buttons">
{settings?.debugMode && (
<button
type="button"
onClick={() => setShowDebugLogs(!showDebugLogs)}
className="header-btn"
title="View debug logs"
>
🐛 Logs
</button>
)}
<button
type="button"
onClick={() => setShowToolsPanel(!showToolsPanel)}
className="header-btn"
title="Toggle manual tools panel"
>
🛠️ Tools
</button>
<button
type="button"
id="clear-btn"
onClick={clearChat}
className="clear-btn"
className="header-btn"
title="Clear Chat"
>
🗑️
🗑️ Clear
</button>
<button
type="button"
id="settings-btn"
onClick={openSettings}
className="settings-btn"
className="header-btn"
title="Open Settings"
>
⚙️
⚙️ Settings
</button>
</div>
</header>
Expand All @@ -637,13 +637,6 @@ const ChatInterface: React.FC = () => {
</div>
) : (
(() => {
sidepanelLogger.debug('Rendering messages', {
messageCount: messages?.length || 0,
isArray: Array.isArray(messages),
messageTypes: Array.isArray(messages)
? messages.filter((m) => m).map((m) => m.role)
: [],
});
return (Array.isArray(messages) ? messages : [])
.filter((message) => {
if (!message) {
Expand Down Expand Up @@ -676,7 +669,11 @@ const ChatInterface: React.FC = () => {
</span>
</div>

<ManualToolInterface onExecuteTool={testFunction} isExecuting={isLoading} />
{showToolsPanel && (
<ManualToolInterface onExecuteTool={testFunction} isExecuting={isLoading} />
)}

<DebugLogViewer isVisible={showDebugLogs} onClose={() => setShowDebugLogs(false)} />

<div className="input-container">
<textarea
Expand Down
Loading