Log Collection Plugin
The Log Collection Plugin enables Codumentor to analyze and interact with log files. It provides a complete source type with a full-featured UI for managing collections of log files and starting conversations scoped to them.
This plugin also serves as the reference implementation for developers building custom source-type plugins (e.g., database schema analyzer, S3 bucket browser, API endpoint explorer). See Building a Source-Type Plugin below.
Architecture
The plugin extends Codumentor's source types through three mechanisms:
- Source Provider Registration — Registers a custom source provider via the
onRegisterSourceProvidershook - Dynamic Tool Registration — Provides tool factories for runtime tool registration per session
- UI Integration — Delivers custom UI components through the plugin manifest
src/codumentor/plugins/log_collection/
├── __init__.py
├── plugin.py # Main plugin class
└── sources/
├── provider.py # LogCollectionSourceProvider
├── routes.py # FastAPI CRUD routes
├── store.py # SQLite storage
├── tools.py # Agent tools
└── workspace.py # Symlink workspace manager
ui/plugins/log_collection/
└── src/components/
├── collections-widget.ts # Welcome page widget
├── collection-form-page.ts # Create/edit form
└── collection-banner.ts # Conversation header banner
Configuration
plugins:
- module: codumentor.plugins.log_collection
class: LogCollectionPlugin
priority: 50
args:
enabled: true
Building the UI Bundle
cd ui/plugins/log_collection
npm install
npm run build
The built bundle is served automatically at /ui/extensions/plugins/log_collection/index.js.
Usage
Creating a Log Collection
Via UI:
- Navigate to the welcome page
- Click + New Collection in the Log Collections widget
- Fill in the collection details: - Name: Collection identifier - Description: Optional description - Isolation Mode:
isolated(log files only) ormerged(log files + code repos) - Add files with Label, Real Path, and Symlink Name
- Click Create Collection
Via API:
curl -X POST http://localhost:2638/ui/plugins/log_collection \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name": "production-logs", "description": "Prod logs", "isolation_mode": "isolated"}'
Starting a Conversation with a Log Collection
Via UI: Click Analyze on a collection in the widget.
Via API:
curl -X POST "http://localhost:2638/ui/conversations?source_type=log_collection&source_id=1" \
-H "Authorization: Bearer $TOKEN"
API Reference
All endpoints are mounted under /ui/plugins/log_collection/:
| Method | Path | Description |
|---|---|---|
GET | /summary | Collection summaries with file counts (for UI widget) |
POST | / | Create a new collection |
GET | / | List all collections for the authenticated user |
GET | /{id} | Get collection details with files |
PUT | /{id} | Update collection metadata |
DELETE | /{id} | Delete a collection |
POST | /{id}/files | Add files to a collection |
DELETE | /{id}/files/{file_id} | Remove a file from a collection |
Adding Files
curl -X POST http://localhost:2638/ui/plugins/log_collection/1/files \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"files": [{"label": "App Log", "real_path": "/var/log/app.log", "symlink_name": "app.log"}]
}'
UI Components
| Component | Element | Placement | Description |
|---|---|---|---|
| Collections Widget | x-log-collections-widget | Welcome page | List collections; start, edit, delete; auto-refreshes every 30s |
| Collection Form | x-log-collection-form-page | /plugins/log_collection/create and edit/:id | Create/edit form with dynamic file list |
| Collection Banner | x-log-collection-banner | Message list header | Shows active collection name, description, file count |
Agent Tools
The plugin provides two tools for runtime collection management during a conversation:
manage_log_collection
Create, list, get, update, or delete collections.
{"action": "create", "name": "debug-logs", "isolation_mode": "isolated"}
manage_log_collection_files
Add, list, or remove files within a collection.
{"action": "add", "collection_id": 1, "files": [{"label": "Error Log", "real_path": "/var/log/error.log", "symlink_name": "error.log"}]}
Isolation Modes
| Mode | Description | Disabled Tools |
|---|---|---|
isolated | Only log files are visible; no code repos | knowledge_search, replace_in_file, write_file, agentic_developer |
merged | Log files + all code repos; all tools enabled | — |
Troubleshooting
Collections widget doesn't appear: Check plugin config, verify enabled: true, check server logs for "LogCollectionPlugin registered", rebuild UI bundle.
404 on collection API: Verify the collection belongs to the authenticated user and the ID is correct.
Agent can't read log files: Verify real_path exists and is readable, check that paths are absolute, verify file permissions.
Building a Source-Type Plugin
This plugin is the canonical reference for creating custom source types. The pattern has four parts:
1. Register a Source Provider
async def _on_register_source_providers(self, agent, ctx, payload):
providers = dict(payload.get("providers", {}))
providers["my_source"] = lambda cfg: MySourceProvider(cfg)
return {"type": "continue", "patch": {"providers": providers}}
2. Implement SourceProvider
from codumentor.sources.protocol import SourceContext, SourceProvider
class MySourceProvider(SourceProvider):
def prepare(self, session_id: str, **kwargs) -> SourceContext:
working_dir = Path("/tmp/workspaces") / session_id
working_dir.mkdir(parents=True, exist_ok=True)
return SourceContext(
source_type="my_source",
working_dir=working_dir,
repo_paths={"my_source": str(working_dir)},
tool_factories=[
lambda cfg, cb: MySourceTool(cfg, input_callback=cb),
],
cleanup=lambda: shutil.rmtree(working_dir, ignore_errors=True),
)
3. Create UI Components
import { BasePluginElement } from "@codumentor/plugin-sdk";
class MySourceWidget extends BasePluginElement {
connectedCallback() {
this._shadowRoot.innerHTML = `<div>My Source Widget</div>`;
}
}
customElements.define("x-my-source-widget", MySourceWidget);
4. Declare the UI Manifest
def ui_manifest(self):
return {
"plugin_id": "my_source",
"name": "My Source",
"version": "1.0.0",
"ui": {
"bundle_url": "/ui/extensions/plugins/my_source/index.js",
"sdk_version": "1.0.0",
"custom_elements": ["x-my-source-widget"],
"placements": ["welcome"],
"widgets": [{"widget_id": "list", "title": "My Sources", "placement": "welcome", "priority": 20, "custom_element": "x-my-source-widget"}],
},
}
See the full implementation at src/codumentor/plugins/log_collection/ and ui/plugins/log_collection/.
See Also
- Plugin Development Guide — Plugin lifecycle and hook reference
- Backend Hooks — Complete hook documentation
- UI Components — Plugin SDK and component patterns