Skip to content

feat: Add VS Code extension with Svelte web UI - #103

Open
wquintal wants to merge 4 commits into
mainfrom
feature/vscode-extension
Open

feat: Add VS Code extension with Svelte web UI#103
wquintal wants to merge 4 commits into
mainfrom
feature/vscode-extension

Conversation

@wquintal

Copy link
Copy Markdown
Contributor

Implements a complete VS Code extension for LogViewer with:

Extension Features:

  • Sidebar panel with context selector, quick filters, and search
  • Results panel with tabbed log viewer and infinite scroll
  • Hash-based tab management (reuses tabs for identical searches)
  • Server lifecycle management (spawns Go binary on demand)

Web UI Features:

  • Svelte 5 with modern runes (, , )
  • Edge-to-edge table design with VS Code theme integration
  • Color-coded log levels (ERROR/WARN/INFO/DEBUG)
  • Row expansion for JSON details
  • Infinite scroll pagination with IntersectionObserver
  • Load more button for manual pagination trigger
  • Toolbar actions: refresh, export JSON, copy to clipboard
  • Recent searches saved in localStorage

Backend Changes:

  • Added pagination support to handlers.go
  • Pass pageToken from request to LogSearch
  • Return nextPageToken via GetPaginationInfo()
  • Support NativeQuery in QueryRequest

Build System:

  • Makefile targets for building web frontend
  • Makefile targets for copying assets to extension
  • Makefile targets for packaging .vsix

Bug Fixes:

  • VS Code API can only be acquired once (fixed in Sidebar.svelte)
  • IntersectionObserver setup with Svelte 5
  • Backend pagination token properly retrieved and returned
  • Reversed log order (newest first, load older on scroll)

Documentation:

  • extension/README.md - User guide and development docs
  • extension/IMPLEMENTATION_NOTES.md - Technical details and bugs fixed

Implements a complete VS Code extension for LogViewer with:

Extension Features:
- Sidebar panel with context selector, quick filters, and search
- Results panel with tabbed log viewer and infinite scroll
- Hash-based tab management (reuses tabs for identical searches)
- Server lifecycle management (spawns Go binary on demand)

Web UI Features:
- Svelte 5 with modern runes (, , )
- Edge-to-edge table design with VS Code theme integration
- Color-coded log levels (ERROR/WARN/INFO/DEBUG)
- Row expansion for JSON details
- Infinite scroll pagination with IntersectionObserver
- Load more button for manual pagination trigger
- Toolbar actions: refresh, export JSON, copy to clipboard
- Recent searches saved in localStorage

Backend Changes:
- Added pagination support to handlers.go
- Pass pageToken from request to LogSearch
- Return nextPageToken via GetPaginationInfo()
- Support NativeQuery in QueryRequest

Build System:
- Makefile targets for building web frontend
- Makefile targets for copying assets to extension
- Makefile targets for packaging .vsix

Bug Fixes:
- VS Code API can only be acquired once (fixed in Sidebar.svelte)
- IntersectionObserver setup with Svelte 5
- Backend pagination token properly retrieved and returned
- Reversed log order (newest first, load older on scroll)

Documentation:
- extension/README.md - User guide and development docs
- extension/IMPLEMENTATION_NOTES.md - Technical details and bugs fixed

Co-Authored-By: Claude <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @wquintal, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a comprehensive VS Code extension for LogViewer, significantly enhancing the user experience by providing an integrated, interactive log analysis tool. The extension leverages a Svelte 5 web UI for its sidebar and results panels, offering features like context selection, quick filters, advanced search, and infinite scroll. Underpinning this is an updated Go backend with improved pagination and native query support, ensuring efficient data handling. The changes also include a refined build system to manage the multi-component architecture, making development and deployment more robust.

Highlights

  • VS Code Extension Introduced: A complete VS Code extension for LogViewer has been implemented, providing a rich graphical interface for log viewing and searching directly within the IDE.
  • Svelte Web UI for Panels: The extension features a Svelte 5-based web UI for both the sidebar search panel and the results panel, offering a modern and reactive user experience with VS Code theme integration.
  • Enhanced Log Viewing Features: The results panel includes an edge-to-edge table design, color-coded log levels, row expansion for JSON details, infinite scroll pagination, and toolbar actions for refresh, export, and copy.
  • Intelligent Tab Management: Hash-based tab management ensures that identical searches reuse existing tabs, preventing duplication and improving navigation efficiency.
  • Backend Pagination and Native Query Support: The Go backend has been updated to support pagination tokens and native query strings, enabling efficient retrieval of large log datasets and flexible search capabilities for the frontend.
  • Robust Build System Integration: New Makefile targets have been added to streamline the build process for both the web frontend and the VS Code extension, including dependency installation, compilation, asset copying, and VSIX packaging.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .gitignore
    • Added new ignore rules for web frontend (node_modules, dist) and VS Code extension (node_modules, out, bin, media, vsix) build artifacts.
  • Makefile
    • Extended .PHONY declaration to include new targets for web frontend and VS Code extension build processes.
    • Added new sections and targets for web frontend build (install, build, dev, check, lint, clean).
    • Added new sections and targets for VS Code extension build (install, compile, binaries, media, build, package, watch, dev/setup, dev/binary, clean).
    • Introduced combined VS Code extension targets (vscode, vscode/clean) for a unified build experience.
  • extension/.vscodeignore
    • Added a new file to specify files and directories to be excluded when packaging the VS Code extension.
  • extension/CHANGELOG.md
    • Added a new changelog file, documenting the initial release (0.0.1) of the LogViewer VS Code extension with its core features.
  • extension/IMPLEMENTATION_NOTES.md
    • Added a new document detailing implementation decisions, development timeline, bug fixes (VS Code API acquisition, search button, infinite scroll, pagination token), UX improvements (reversed log order, clickable load more button), technical decisions (Svelte 5, separate panels, hash-based tabs, IntersectionObserver, HTTP server), performance, security, and testing approaches.
  • extension/README.md
    • Added a new README file providing an overview of the LogViewer VS Code Extension, its architecture, supported backends, features, usage instructions, configuration, commands, settings, and development guidelines.
  • extension/package-lock.json
    • Added a new package-lock.json file to manage Node.js dependencies for the VS Code extension.
  • extension/package.json
    • Added a new package.json file defining the VS Code extension's metadata, scripts, and development dependencies.
  • extension/src/LogViewerResults.ts
    • Added a new TypeScript file to manage the LogViewer results webview panels, including hash-based tab management, HTML content generation, and resource handling.
  • extension/src/LogViewerSidebar.ts
    • Added a new TypeScript file implementing the VS Code WebviewViewProvider for the LogViewer sidebar, handling server startup, HTML content, and message passing for search requests.
  • extension/src/ServerManager.ts
    • Added a new TypeScript file to manage the lifecycle of the LogViewer Go backend binary, including starting, stopping, restarting, and selecting platform-specific binaries.
  • extension/src/extension.ts
    • Added a new TypeScript file as the main entry point for the VS Code extension, activating components, registering commands (open, restart, showOutput), and handling search events from the sidebar.
  • extension/tsconfig.json
    • Added a new tsconfig.json file for TypeScript compilation settings specific to the VS Code extension.
  • pkg/server/handlers.go
    • Updated the QueryRequest struct to include PageToken and NativeQuery fields for enhanced search capabilities.
    • Modified the QueryMetadata struct to include a NextPageToken field for pagination support.
    • Implemented logic to set PageToken and NativeQuery on the LogSearch object if provided in the request.
    • Added retrieval of pagination information from the search result and included nextPageToken in the LogsResponse metadata.
  • pkg/server/server.go
    • Imported the 'net' package for network operations.
    • Modified the server startup logic to create a listener first, allowing the actual assigned port to be retrieved, especially when a random port (0) is requested.
    • Updated server logging to print the actual listening port in a format parsable by the VS Code extension.
  • web/.gitignore
    • Added a new .gitignore file for the web frontend, excluding common build artifacts and editor-specific files.
  • web/README.md
    • Added a new README file detailing the Svelte-based web frontend, its architecture, features, development setup, API contract, and build configuration.
  • web/index.html
    • Added a new index.html file, serving as the entry point for the main Svelte application.
  • web/package-lock.json
    • Added a new package-lock.json file to manage Node.js dependencies for the web frontend.
  • web/package.json
    • Added a new package.json file defining the web frontend's metadata, scripts (dev, build, check), and development dependencies.
  • web/public/vite.svg
    • Added a new SVG asset for the Vite logo.
  • web/results.html
    • Added a new HTML file serving as the entry point for the results panel webview, with specific styling for full-height display.
  • web/sidebar.html
    • Added a new HTML file serving as the entry point for the sidebar webview, with specific styling for full-height display.
  • web/src/App.svelte
    • Added a new Svelte component representing the main application layout, integrating ContextSelector, SearchBar, and LogTable components.
  • web/src/app.css
    • Added a new CSS file for global styling of the web application.
  • web/src/assets/svelte.svg
    • Added a new SVG asset for the Svelte logo.
  • web/src/lib/Counter.svelte
    • Added a simple Svelte component demonstrating state management with runes.
  • web/src/lib/api/client.ts
    • Added a new TypeScript file implementing an API client for interacting with the LogViewer Go backend, handling requests, error parsing, and specific endpoints for contexts, logs, and fields.
  • web/src/lib/api/index.ts
    • Added a new index file to re-export API client and types.
  • web/src/lib/api/types.ts
    • Added a new TypeScript file defining interfaces for LogEntry, QueryMeta, LogsResponse, Context, ContextsResponse, FieldsResponse, SearchParams, and ApiError.
  • web/src/lib/components/ContextSelector.svelte
    • Added a new Svelte component for selecting log contexts, fetching available contexts from the API, and managing the selected context state.
  • web/src/lib/components/LogRow.svelte
    • Added a new Svelte component to display individual log entries, featuring timestamp formatting, color-coded levels, message display, and expandable JSON details with copy functionality.
  • web/src/lib/components/LogTable.svelte
    • Added a new Svelte component to display a table of log entries, handling search execution, infinite scroll pagination using IntersectionObserver, and displaying loading/error states.
  • web/src/lib/components/Results.svelte
    • Added a new Svelte component for the results panel, displaying logs, handling refresh, export, copy actions, and managing infinite scroll with a 'Load more' button.
  • web/src/lib/components/SearchBar.svelte
    • Added a new Svelte component for the search bar, allowing users to input queries, select time ranges, and filter by log level.
  • web/src/lib/components/Sidebar.svelte
    • Added a new Svelte component for the LogViewer sidebar, including context selection, quick filters, time range, size, query input, recent searches, and communication with the VS Code extension API.
  • web/src/lib/stores/context.ts
    • Added a new TypeScript file defining Svelte stores for managing available contexts and the currently selected context.
  • web/src/lib/stores/logs.ts
    • Added a new TypeScript file defining Svelte stores for managing log entries, query metadata, loading state, and errors.
  • web/src/lib/stores/search.ts
    • Added a new TypeScript file defining a Svelte store for managing the current search parameters (query, time range, level, size).
  • web/src/main.ts
    • Added a new TypeScript entry point for the main Svelte application.
  • web/src/results.ts
    • Added a new TypeScript entry point for the Svelte results panel, mounting the Results component with initial search parameters.
  • web/src/sidebar.ts
    • Added a new TypeScript entry point for the Svelte sidebar panel, mounting the Sidebar component.
  • web/svelte.config.js
    • Added a new Svelte configuration file for Vite preprocessing.
  • web/tsconfig.app.json
    • Added a new tsconfig.app.json file for TypeScript compilation settings specific to the Svelte application.
  • web/tsconfig.json
    • Added a new tsconfig.json file referencing other TypeScript configuration files.
  • web/tsconfig.node.json
    • Added a new tsconfig.node.json file for TypeScript compilation settings specific to Node.js environments within the web project.
  • web/vite.config.ts
    • Added a new Vite configuration file for the Svelte web frontend, including plugin setup, base path, alias resolution, and rollup options for multi-entry point builds.
Activity
  • The pull request introduces a significant new feature, laying the groundwork for a VS Code extension. All changes are new additions or modifications to support this new functionality.
  • No significant human activity (comments, reviews) has been recorded on this pull request yet, indicating it's fresh for review.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive VS Code extension for LogViewer, featuring a Svelte 5 web UI and robust backend integration. The implementation of hash-based tab management and infinite scroll pagination significantly enhances the user experience. However, there are critical issues regarding file export and clipboard operations within the webview sandbox that need to be addressed by delegating these tasks to the extension host via message passing. Additionally, the port discovery mechanism and asset path handling in the webview should be made more robust to ensure reliability across different environments.

Comment on lines +29 to +39

function handleExport() {
const json = JSON.stringify(logs, null, 2);
const blob = new Blob([json], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `logs-${contextId}-${Date.now()}.json`;
a.click();
URL.revokeObjectURL(url);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Triggering a file download using document.createElement('a').click() will likely fail within a VS Code webview due to security sandbox restrictions. The recommended approach is to send a message to the extension host and use the vscode.workspace.fs or vscode.window.showSaveDialog APIs to handle file saving.

Comment on lines +95 to +97
/(?:listening|started|port)[^\d]*(\d+)/i
);
if (portMatch) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current regex for port discovery is too broad and could accidentally match other numbers in the server's output (like process IDs or timestamps). Since the Go backend explicitly prints a specific string for this purpose, the regex should be anchored to that string to ensure reliability.

          const portMatch = output.match(/Server listening on port (\d+)/i);

Comment on lines +41 to +44
function handleCopy() {
const text = logs.map(l => `${l.timestamp} ${l.level} ${l.message}`).join('\n');
navigator.clipboard.writeText(text);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Direct access to navigator.clipboard may be restricted in VS Code webviews depending on the environment and security settings. It is more reliable to use vscode.postMessage to request the extension host to perform the clipboard operation using vscode.env.clipboard.writeText.

Comment on lines +143 to +144
html = html.replace(/href="\.\/assets\//g, `href="${assetsUri}/`);
html = html.replace(/src="\.\/assets\//g, `src="${assetsUri}/`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The asset path replacement logic is brittle as it strictly expects ./assets/. Depending on Vite's configuration or version, paths might be generated as assets/ or /assets/. A more flexible regex would improve the robustness of the webview loading process.

Suggested change
html = html.replace(/href="\.\/assets\//g, `href="${assetsUri}/`);
html = html.replace(/src="\.\/assets\//g, `src="${assetsUri}/`);
html = html.replace(/(href|src)="\.?\/?assets\//g, `$1="${assetsUri}/`);

Comment on lines +1 to +146
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { api } from '$lib/api';
import { logs, meta, isLoading, error } from '$lib/stores/logs';
import { selectedContextId } from '$lib/stores/context';
import { searchState } from '$lib/stores/search';
import LogRow from './LogRow.svelte';
import { get } from 'svelte/store';

let sentinel: HTMLDivElement;
let observer: IntersectionObserver;

export async function executeSearch(append = false) {
const contextId = get(selectedContextId);
if (!contextId) return;

isLoading.set(true);
error.set(null);

try {
const currentSearch = get(searchState);
const currentMeta = get(meta);

const response = await api.queryLogs({
contextId,
nativeQuery: currentSearch.query || undefined,
range: { last: currentSearch.timeRange },
fields: currentSearch.level ? { level: currentSearch.level } : undefined,
size: 100,
pageToken: append ? currentMeta?.nextPageToken : undefined,
});

if (append) {
logs.update((current) => [...current, ...response.logs]);
} else {
logs.set(response.logs);
}
meta.set(response.meta);
} catch (e) {
error.set(e instanceof Error ? e.message : 'Query failed');
} finally {
isLoading.set(false);
}
}

function loadMore() {
const loading = get(isLoading);
const currentMeta = get(meta);
if (!loading && currentMeta?.nextPageToken) {
executeSearch(true);
}
}

onMount(() => {
observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadMore();
}
},
{ threshold: 0.1 }
);

if (sentinel) {
observer.observe(sentinel);
}
});

onDestroy(() => {
observer?.disconnect();
});
</script>

<div class="log-table">
{#if $error}
<div class="error">{$error}</div>
{/if}

<table>
<thead>
<tr>
<th class="timestamp">Timestamp</th>
<th class="level">Level</th>
<th class="message">Message</th>
</tr>
</thead>
<tbody>
{#each $logs as log, i (log.timestamp + i)}
<LogRow {log} />
{/each}
</tbody>
</table>

{#if $isLoading}
<div class="loading">Loading...</div>
{/if}

<!-- Sentinel for infinite scroll -->
<div bind:this={sentinel} class="sentinel"></div>

{#if $meta}
<div class="meta">
{$meta.resultCount} results in {$meta.queryTime}
</div>
{/if}
</div>

<style>
.log-table {
flex: 1;
overflow: auto;
}
table {
width: 100%;
border-collapse: collapse;
font-family: monospace;
font-size: 12px;
}
th {
text-align: left;
padding: 0.5rem;
background: var(--vscode-editor-background, #1e1e1e);
position: sticky;
top: 0;
border-bottom: 1px solid var(--vscode-panel-border, #333333);
}
.timestamp {
width: 180px;
}
.level {
width: 60px;
}
.error {
padding: 1rem;
color: var(--vscode-errorForeground, #f44336);
}
.loading,
.meta {
padding: 0.5rem;
text-align: center;
color: var(--vscode-descriptionForeground, #888888);
}
.sentinel {
height: 1px;
}
</style>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This component appears to be redundant as Results.svelte implements the same functionality using modern Svelte 5 runes. Maintaining two separate implementations of the log table increases technical debt and the risk of inconsistent behavior. Consider removing this file and unifying the logic in Results.svelte.

wquintal and others added 3 commits February 20, 2026 14:54
Implements comprehensive configuration management features:

New Settings:
- logviewer.configPath: Specify custom config file path
  - Supports default ~/.logviewer/config.yaml
  - Supports drop-in configs in ~/.logviewer/configs/*.yaml
  - Respects LOGVIEWER_CONFIG environment variable

- logviewer.watchConfigFiles (default: true)
  - Watches config files for changes
  - Detects modifications, creations, and deletions
  - Automatically recreates watcher when settings change

- logviewer.autoRestartOnConfigChange (default: false)
  - Auto-restart: Server restarts silently on config change
  - Manual mode: Shows notification with 'Restart Now' button
  - Prevents concurrent restarts with isRestarting flag

Features:
- File watching for config files (FileSystemWatcher)
- Multi-file config support (main + drop-in directory)
- Custom config path support with dynamic watcher recreation
- Notification on config change with restart options
- Warning notification on config file deletion
- Comprehensive logging to LogViewer Server output channel
- Graceful error handling for restart failures

Implementation:
- Added getConfigPaths() to resolve all watched config files
- Added setupConfigWatcher() with change/create/delete handlers
- Added handleConfigChangeRestart() with auto/manual modes
- Added disposeConfigWatcher() for cleanup on setting changes
- Settings change listener to recreate watcher dynamically
- Proper disposal in deactivate() to clean up resources

Documentation:
- extension/SETTINGS.md: Complete settings reference
  - All settings with descriptions and examples
  - Recommended configurations for different scenarios
  - Troubleshooting guide
  - Environment variable documentation

- extension/TESTING_CONFIG_WATCH.md: Comprehensive test suite
  - 10 manual test cases covering all scenarios
  - Edge case testing (permissions, symlinks, network drives)
  - Performance testing guidance
  - Debugging instructions

Benefits:
- Development: Auto-restart on config save speeds up iteration
- Production: Manual restart prevents unexpected disruptions
- Flexibility: Works with default paths, custom paths, and env vars
- Reliability: Proper error handling and user feedback

Note: The Go server loads config at startup (no hot-reload).
Extension handles config changes via server restart.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds a convenient footer link in the sidebar panel to quickly open
the LogViewer configuration file in VS Code.

Features:
- Footer button at bottom of sidebar with gear icon (⚙️)
- Styled as VS Code link with hover/active states
- Uses margin-top: auto to stick to bottom of sidebar
- Sends 'openConfig' message to extension host

Extension handling:
- New message handler for 'openConfig' type
- getConfigPath() resolves config file path:
  - Uses logviewer.configPath setting if set
  - Falls back to LOGVIEWER_CONFIG environment variable
  - Defaults to ~/.logviewer/config.yaml
- handleOpenConfig() opens file in editor:
  - Prompts to create file if it doesn't exist
  - Creates directory structure if needed
  - Includes basic YAML template (clients/contexts)
  - Opens in main editor column (not preview)

Benefits:
- Quick access to config without leaving VS Code
- Helps new users discover config file location
- Streamlines config editing workflow
- Follows VS Code patterns (like settings.json link)

UI Design:
- Consistent with VS Code sidebar styling
- Uses semantic colors (textLink-foreground)
- Proper focus states for accessibility
- Tooltip shows 'Open configuration file'

Co-Authored-By: Claude <noreply@anthropic.com>
Implements real-time configuration updates via SSE, allowing the
sidebar to automatically refresh when config files change.

Backend Changes (pkg/server/events.go):
- EventBroker: Manages SSE client subscriptions and broadcasts
  - Subscribe/Unsubscribe methods for client management
  - Broadcast sends events to all connected clients
  - Non-blocking with timeouts to prevent slow clients blocking

- Event types:
  - config-reloaded: Sent when config file changes
  - server-error: Sent when config reload fails
  - connected: Initial connection confirmation

- ConfigWatcher: Watches config file with fsnotify
  - Monitors file Write and Create events
  - Debounces rapid changes (1 second)
  - Prevents concurrent reloads with mutex
  - Graceful error handling with error events

- SSE Handler (/events endpoint):
  - Proper SSE headers (text/event-stream, no-cache)
  - Heartbeat every 30 seconds
  - Automatic reconnection on disconnect
  - Request context cancellation support

Backend Changes (pkg/server/server.go):
- Added fields:
  - eventBroker: Manages SSE connections
  - configWatcher: Watches config file
  - configPath: Path to config file for reloading
  - configMutex: Thread-safe config access

- NewServer: Now accepts configPath parameter
  - Initializes EventBroker
  - Creates event route /events

- Start: Initializes config watcher if path provided
  - Starts watcher in background
  - Stops watcher on shutdown

- ReloadConfig: Hot-reloads configuration
  - Loads new config file
  - Recreates client and search factories
  - Atomically swaps config with mutex
  - Thread-safe for concurrent requests

- GetConfig: Thread-safe config access

Frontend Changes (web/src/lib/components/Sidebar.svelte):
- setupEventSource: Connects to SSE endpoint
  - Reads port from window.LOGVIEWER_PORT
  - Listens for config-reloaded events
  - Auto-refreshes contexts on config change
  - Handles errors and reconnection

- loadContexts: Extracted as reusable function
  - Called on mount and on config-reloaded event
  - Clears errors on successful load

- onMount: Now calls setupEventSource
  - SSE connection established immediately
  - Logs connection status to console

Dependencies:
- Added github.com/fsnotify/fsnotify for file watching

Benefits:
- No manual restart needed after config changes
- Real-time context list updates in sidebar
- Seamless UX - just save config file
- Works alongside extension's file watcher (two-tier)
- Multiple clients supported (all browsers/panels)

Architecture:

Two-tier watching:
1. Extension watches → prompts to restart server
2. Server watches → hot-reloads config + broadcasts SSE

User can choose:
- Disable extension watching (manual restart only)
- Enable auto-restart (server restarts, loses state)
- Keep both (notification + SSE hot-reload without restart)

Thread safety:
- configMutex protects config reads/writes
- EventBroker uses RWMutex for client map
- Concurrent requests use current config safely

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant