Markdown Converter
Agent skill for markdown-converter
**LibrAgent: A High-Freedom AI Agent Platform - Infinitely Expandable with MCP!**
Sign in to like and favorite skills
LibrAgent: A High-Freedom AI Agent Platform - Infinitely Expandable with MCP!
LibrAgent is a next-generation desktop AI agent platform that combines the lightness of Tauri with the intuitiveness of React. Users can automate all daily tasks by giving AI agents their own unique personalities and abilities.
LibrAgent provides several useful scripts for development and code quality:
pnpm dev ā Start the Vite development server
pnpm tauri dev ā Start the Tauri desktop app with hot reload
pnpm build ā Build the frontend for production
pnpm lint ā Run ESLint checks for code quality
pnpm format ā Format code using Prettier
pnpm rust:fmt ā Check Rust code formatting
pnpm rust:clippy ā Run Rust linter
pnpm dead-code ā Find unused code with unimported
pnpm refactor:validate ā Complete validation pipeline:Workflow Recommendation:
After making any code changes, always run:
pnpm refactor:validate
This ensures:
Note: All contributors must follow this workflow before submitting PRs or merging changes.
libr-agent/ āāā src/ # React Frontend ā āāā app/ # App entry, root layout, global providers ā āāā assets/ # Static assets (images, svgs, etc.) ā āāā components/ # Shared, generic UI components (reusable) ā āāā features/ # Feature-specific components, logic, and hooks ā āāā config/ # Static config files ā āāā context/ # React context providers ā āāā hooks/ # Generic, reusable hooks ā āāā lib/ # Service layer, business logic, data, API ā āāā models/ # TypeScript types and interfaces ā āāā styles/ # Global or shared CSS ā āāā README.md ā āāā vite-env.d.ts āāā src-tauri/ # Rust Backend ā āāā src/ ā āāā Cargo.toml ā āāā tauri.conf.json āāā docs/ # Documentation āāā dist/ # Build artifacts āāā package.json āāā tailwind.config.js āāā vite.config.ts
npm install -g pnpm).pnpm install to install dependencies.pnpm tauri devpnpm tauri buildsrc-tauri/)rustfmt.///) for public APIs.Result<T, E> types.self (or &self, &mut self) as the first parameter in an impl block.self.method_name(...)self parameter.TypeName::function_name(...)impl MyStruct { // Method: requires self fn do_something(&self, arg: i32) { ... } // Associated function: no self fn helper(arg: i32) { ... } } // Calling methods let obj = MyStruct::new(); obj.do_something(42); // ā Method call MyStruct::helper(42); // ā Associated function call
self in a function, declare self as the first parameter.self.fn copy_dir_contents(src: &Path, dst: &Path) -> Result<(), String> { self.copy_dir_contents(&src_path, &dst_path)?; // Error! }
fn copy_dir_contents(src: &Path, dst: &Path) -> Result<(), String> { SessionManager::copy_dir_contents(&src_path, &dst_path)?; }
fn copy_dir_contents(&self, src: &Path, dst: &Path) -> Result<(), String> { self.copy_dir_contents(&src_path, &dst_path)?; }
Summary: Always remember that the presence/absence of
self parameter determines calling method. When compilation errors occur, recheck function declaration and calling patterns.
src/)any in TypeScript. The lint configuration is extremely strict; always use precise types and interfaces. Use unknown or generics if absolutely necessary, but avoid any as much as possible.
// eslint-disable-next-line @typescript-eslint/no-explicit-any). Instead, refactor the code to avoid any or use unknown/proper typing and document the rationale in a code comment and PR description when an exception is truly necessary.getLogger from @/lib/logger and use context-specific logging (e.g., const logger = getLogger('ComponentName')) instead of console.* methods for better debugging and log management.import('../path').Type. This improves readability, maintainability, and IDE support.interface Config { tools?: import('@/lib/mcp').MCPTool[]; messages: import('@/models/chat').Message[]; }
import type { MCPTool } from '@/lib/mcp'; import type { Message } from '@/models/chat'; interface Config { tools?: MCPTool[]; messages: Message[]; }
shadcn/ui components for building accessible, consistent, and customizable UI elements. Prefer shadcn/ui for new UI components unless a custom solution is required.content-text) that are not Tailwind utility classes, as they may be removed by PurgeCSS during build.className="text-sm text-gray-700 leading-relaxed"tailwind.config.jsclassName="[custom-value]"shadcn/ui: Component library for building accessible and customizable UI componentsThe project uses a centralized logging system located at
src/lib/logger.ts that integrates with Tauri's native logging plugin. This provides better debugging capabilities and structured logging across the application.
Always use the centralized logger instead of
methodsconsole.*
Import and use context-specific loggers:
import { getLogger } from '@/lib/logger'; const logger = getLogger('ComponentName'); // Use appropriate log levels logger.debug('Debug information', data); logger.info('General information', data); logger.warn('Warning message', data); logger.error('Error occurred', error);
Context naming: Use descriptive context names that match the component/module name
Log levels: Use appropriate log levels (debug, info, warn, error) based on the importance and type of information
Error logging: When logging errors, pass the Error object as the last parameter for proper error handling
shadcn/ui components as the primary building blocks for UI, customizing as needed for project requirements.src/lib/)src-tauri/src/)The system implements a "Dual-Track" architecture to support advanced agentic workflows while maintaining legacy compatibility.
Dual-Track System:
ChatContext (React).Rust-Based Orchestration:
AgentSessionManager: The central brain residing in Rust (src-tauri/src/agent/). It manages the "Think-Act-Observe" loop independently of the frontend.agent:event) to push status updates and messages to the UI. The frontend (AgentChatContext) is purely reactive.Session Isolation:
MCPServiceProxy.Service Context Pattern:
get_service_context trait method.šØ CRITICAL: Understanding What AI Agents Actually See
When designing MCP tool responses, it's essential to understand the data flow:
MCPResult Structure (LibrAgent-Specific):
pub struct MCPResult { content: Vec<MCPContent>, // Standard MCP: Text that agents SEE structured_content: Option<Value>, // LibrAgent extension: JSON for UI only (agents NEVER see) is_error: Option<bool>, // Standard MCP }
Note:
structured_content is a LibrAgent-specific extension, not part of the standard MCP protocol. External MCP servers only return content arrays. This field exists solely for LibrAgent's UI components to render rich interfaces.
What AI Agents See:
content field (text messages, resource URIs)What AI Agents NEVER See:
Design Implications:
Critical Information Must Be in Text
// ā WRONG: Process ID only in structured_content MCPResult { content: vec![text("Process started successfully")], structured_content: Some(json!({"process_id": "abc123"})) } // ā CORRECT: Process ID in text output MCPResult { content: vec![text("Process started (ID: abc123)")], structured_content: Some(json!({"process_id": "abc123"})) }
List IDs in Text for Follow-up Actions
// ā WRONG: IDs only in JSON array "Found 3 processes" // ā CORRECT: IDs visible in text "Found 3 processes: ⢠abc123 [running]: npm build ⢠def456 [finished]: cargo test"
State Information in Explicit Labels
// ā WRONG: Ambiguous or only in JSON "Shell state: ~/project $" // ā CORRECT: Explicit persistence indicator "Persistent shell state (maintained for next runInPersistentShell call): Working directory: ~/project Exit code: 0"
Use Cases for structured_content:
Best Practices:
@tauri-apps/api: Version 2.x - Enhanced frontend-backend communication@tauri-apps/cli: Version 2.x - Latest development and build toolstauri: Version 2.x - Advanced Rust backend framework with improved securityreact: Version 18.x - UI libraryreact-dom: Version 18.x - React DOM renderertypescript: Version 5.x - Type safetyvite: Version 4.x - Build tool and dev servertailwindcss: Version 4.x - Utility-first CSS frameworktauri: Main framework for desktop app developmentserde: JSON serialization/deserializationtokio: Async runtime for concurrent operationsrmcp: Model Context Protocol implementation@vitejs/plugin-react: React support for Viteautoprefixer: CSS vendor prefixingpostcss: CSS processingeslint: JavaScript/TypeScript lintingprettier: Code formatting// src/components/ComponentName.tsx interface ComponentNameProps { // Type definitions } export default function ComponentName({ props }: ComponentNameProps) { // Component implementation }
// src/lib/service-name.ts export class ServiceName { // Public methods for component usage } export const serviceInstance = new ServiceName();
// src-tauri/src/commands/module_name.rs #[tauri::command] pub async fn command_name(param: Type) -> Result<ReturnType, String> { // Implementation }
.env.example to .env and configure API keyspnpm install for dependenciespnpm tauri dev - Start development serverpnpm tauri build - Create production buildpnpm lint - Run ESLint checkspnpm format - Format code with Prettiercargo fmt - Format Rust codecargo clippy - Rust lintingDO NOT add CSP configuration to
for desktop applications:tauri.conf.json
Why this matters:
Before completing any refactoring work, always run the following commands to ensure code quality and build integrity:
pnpm lint - Verify ESLint rules compliancepnpm format - Apply Prettier formatting standardspnpm build - Ensure the application builds without errorsThese steps must be completed successfully before considering any refactoring task complete. This ensures: