rlm-tools-bsl

repository·master·Indexed 41 days ago

https://github.com/dach-coin/rlm-tools-bsl

An MCP (Model Context Protocol) server for token-efficient analysis of 1C:Enterprise (BSL) codebases. It enables AI agents to explore large repositories directly using Repository-Level Machine-coding (RLM) to reduce context window usage. Version 1.37.0 provides tools for BSL parsing, caller searching, metadata XML parsing, and a BSL-call graph, supporting installation via pip, Docker, or source on Windows and Linux.

Tokens
114.8K
Snippets
229
Records
404
Agent score
52%

What's inside rlm-tools-bsl

  1. Compatibility with original rlm-tools

    master

    The rlm-tools-bsl package is a superset of the original rlm-tools. It preserves all core functionality while adding BSL-specific capabilities.

    Preserved Features:

    • MCP Tools: rlm_start, rlm_execute, and rlm_end.
    • Standard Sandbox Helpers: read_file, grep, glob_files, tree, llm_query, etc.
    • Configuration: Supports RLM_MAX_SESSIONS, RLM_SESSION_TIMEOUT, and various effort levels.
    • Security: Sandbox is read-only, has restricted imports, and a default 45-second timeout.
    • Versatility: Works with any codebase, not just 1C/BSL.

    BSL functionality is layered on top without breaking the original mechanics.

  2. Understand the benchmark metrics and fixture

    master

    The benchmark measures the performance of several core operations:

    • Initialization and internal index construction
    • Module searching (find_module)
    • BSL parsing (extract_procedures, find_exports)
    • Caller searching (find_callers)
    • Text search (grep)
    • XML metadata parsing (parse_metadata_xml)
    • Event subscriptions and scheduled jobs
    • Register movements

    Benchmark Fixture

    The fixture/ directory contains a minimal synthetic 1C configuration in CF format (~20 files) designed to use realistic BSL patterns. It includes:

    • 2 Common Modules (with #Область, Export, and cross-module calls)
    • 1 Document (attributes, tabular sections, OnPosting, OnFill, and forms)
    • 2 Catalogs (XML metadata + object modules)
    • 1 Information Register (dimensions, resources, record set module)
    • 1 Accumulation Register (dimensions, resources)
    • 1 Event subscription
    • 1 Scheduled job
    • 1 Enumeration
  3. What is the BSL Method Index

    master

    The BSL Method Index is a pre-built SQLite database that contains a table of all procedures and functions within a 1C codebase, along with an optional heuristic call graph. It enables near-instantaneous answers to queries such as "what methods are in this module?", "who calls this function?", or "what are the export procedures for this object?" without needing to re-read files from disk.

    Key Features

    • Symbol Table: Uses regex-parsing to populate a methods SQLite table (e.g., ~569K methods in ERP).
    • Call Graph: Uses heuristic regex to populate a calls SQLite table (e.g., ~4.5M edges in ERP).
    • Full-Text Search: Uses SQLite FTS5 with a trigram tokenizer and BM25 ranking via the search_methods function for substring searching on method names.
    • Metadata Support: Includes 17 metadata tables (e.g., ES, SJ, FO, HTTP, WS, XDTO, synonyms, regions, forms, etc.) and an index_meta table.
    • Zero Dependencies: Built with pure Python and the SQLite standard library.
    • Performance: Significantly reduces MCP (Model Context Protocol) calls and improves quality for smaller AI models.
  4. What is RLM (Repository-Level Machine-coding)?

    master

    RLM (Repository-Level Machine-coding) is an approach where an AI agent explores a repository directly in real-time. Instead of relying on pre-indexed vector databases (RAG), the agent performs search queries, reads files, and analyzes structure on demand.

    Key Benefits for 1C (BSL) Codebases:

    • Token Efficiency: Instead of reading a 2000-line file into the context, the agent can call tools like extract_procedures(path) to get only the signatures, or read_procedure(path, "ProcedureName") to get only the specific body. This typically saves 25-95% of context tokens.
    • No Pre-indexing: Unlike RAG, there is no need for time-consuming preliminary vectorization or heavy infrastructure maintenance.
    • Sandbox Execution: The agent sends Python scripts to the server, which execute in a sandbox. Only the print() output is returned to the agent's context, ensuring only filtered, relevant data is consumed.
  5. Identify string provenance with the owner key

    master

    The owner key (introduced in v1.34.0) provides the provenance of a string. It is always present, even in configurations without extensions.

    • Values: Either "main" or "extension:<Name>".
    • Extension Names: The name is extracted from Configuration.xml or .mdo files, not from the directory basename.
    • Detection: Use owner.startswith("extension:") to identify an extension, and the suffix after the colon is the extension name.
  6. Understand the Worker Warning Bridge (v1.34.0)

    master

    In the default process mode, workers use a limited queue to bridge WARNING+ logs to the parent's server.log. This prevents IPC bloat by intentionally excluding DEBUG logs.

    Key constraints and safety behaviors:

    • Validation: The parent process re-validates all bridged logs. It enforces a limit of $\le 20$ records, a maximum length of $\le 300$ characters per record, and checks for printable code points. Violations trigger a SandboxProtocolError.
    • Data Format: Logs are added to existing init_ok and execute_result frames using the log_records additive key. This is a non-breaking protocol update.
    • Lifecycle: Startup logs are read once by the start-boundary. Execute-boundary logs are drained in a finally block around every backend.execute attempt to ensure logs are captured even during parallel shutdowns or lazy restarts.
    • Limitations: The bridge does not guarantee delivery of runtime warnings issued after the last successfully received frame (e.g., during a hard timeout, worker_error, or worker loss).
  7. Work with BSL Extensions and Visibility

    master

    When working with extensions (CFE), the following mechanisms ensure visibility and correct resolution:

    • Resolution: _ext_resolve_safe is a multi-root resolver that searches the base path plus all extension_paths. If a path is not found in these roots, it raises a PermissionError.
    • Indexing Order: To ensure extension modules are visible in idx_reader sessions, you must call _ensure_index, which performs an extension pass always after the main pass.
    • File Access: _ext_read_file provides a reader with a dedicated cache for extension files.
    • Path Prefixes: High-level helpers return extension object and module paths with a ../cfe/… prefix.
    • Live Layer: _live_search_* functions supplement index results with real-time data from extensions, mirroring the IndexReader shape.
  8. Use Git-accelerated incremental updates

    master

    If your source directory is inside a git repository, index update automatically uses git to identify changed files instead of scanning the entire filesystem. This works even if the .git directory is located above the source directory (e.g., in an EDT project).

    How it works:

    1. The git_head_commit (SHA) is stored in index_meta during build or update.
    2. During the next update, the tool checks for a git repository and the git command in PATH.
    3. It calculates a delta of all files changed since the saved commit (including committed, staged, unstaged, and untracked files).
    4. It selectively updates BSL tables and metadata tables based on the file extensions found in the delta.

    Requirements for Git acceleration:

    • The source directory must be within a git repository.
    • The git command must be available in PATH.
    • A valid git_head_commit must exist in index_meta.
    • The saved commit must exist in the git history.
    • The builder_version must match the current version (version mismatches trigger a full rebuild).
  9. How BSL helpers are accelerated by the index

    master

    When rlm_start detects a valid index (FRESH, STALE_AGE, or STALE_CONTENT), it connects helpers via an IndexReader. This transforms slow filesystem/XML operations into near-instantaneous SQL queries.

    HelperWith Index (Instant)Without Index (Slow)
    extract_procedures(path)SELECT from methodsRegex-parsing .bsl
    find_exports(path)SELECT WHERE is_export=1Filter extract_procedures
    find_callers_context(proc)JOIN calls+methods+modulesParallel scan+grep .bsl
    find_event_subscriptions(obj)SELECT from event_subscriptionsXML-parsing EventSubscriptions/**
    find_scheduled_jobs(name)SELECT from scheduled_jobsXML-parsing ScheduledJobs/**
    find_functional_options(obj)SELECT from functional_optionsXML-parsing FunctionalOptions/**
    find_enum_values(name)SELECT from enum_valuesGlob + XML-parsing Enums/**
    analyze_subsystem(name)SELECT from subsystem_contentGlob + XML-parsing Subsystems/**
    find_roles(obj)SELECT from role_rightsParsing Rights.xml / .rights
    find_register_movements(doc)SELECT DISTINCT from register_movementsGrep ObjectModule + ManagerModule
    find_register_writers(reg)SELECT from register_movementsParallel search ObjectModule
    glob_files(pattern)SELECT from file_pathspathlib.Path.glob()
    tree(path)SELECT from file_pathsRecursive iterdir()
    find_files(name)SELECT from file_paths (ranked)os.walk() + in-memory search
    search_methods(query)FTS5 (BM25)Not available
    search_objects(query)SELECT from object_synonymsNot available
    search_regions(query)SELECT from regionsNot available
    search_module_headers(query)SELECT from module_headersNot available
    find_attributes(name)SELECT from object_attributesLive XML-parsing
    find_predefined(name)SELECT from predefined_itemsLive XML-parsing
    find_exchange_plan_content(name)SELECT from exchange_plan_contentLive XML-parsing
    find_references_to_object(obj)SELECT from metadata_referencesLive XML-parsing
    find_code_usages(obj)SELECT from metadata_code_usagesLimited safe_grep
    find_defined_types(name)SELECT from defined_typesLive XML-parsing
    parse_form(object_name)SELECT from form_elementsGlob + XML-parsing
  10. Understand the bsl_strategy_data contract

    master

    The bsl_strategy_data.py module defines the contract for executable strategies. An executable strategy must describe the same contract as the production helper.

    Core Components:

    • Strategy Sections: Defined by STRATEGY_SECTIONS with 6 keys: critical, workflow, performance, batching, io, and coverage.
    • Disambiguation: Uses DISAMBIGUATION_PAIRS (12 pairs containing pair, summary, when_a, when_b, rule, and tags) to support rlm_help(section=...) calls.
    • Transport Boundaries: Requires two boundaries: content_truncated=False for every direct line and subsystems_found == len(subsystems).
    • Constraint: The live:no reverse tail is mandatory; reverse queries are not supported on live branches.
  11. Understand the BSL Method Index and Resolution Tiers

    master

    The BSL Method Index maps how methods are called within the codebase. To maintain accuracy and prevent false positives, the indexer uses a tiered resolution strategy for callee_key:

    • local: A bare call like B() refers to a method within the same module as the caller.
    • common_exported: A qualified call like A.B() refers to an exported method of a common module A (categorized as category=CommonModules, module_type=Module, is_export=1).

    Important Note on Non-Resolved Calls: Object/manager calls (e.g., Справочники.X.Метод, Контрагент.Метод) and platform/external methods are intentionally not resolved (callee_key IS NULL). This prevents false associations. When a call cannot be resolved, the system falls back to a name-based match to ensure recall is not lost.

    Resolution aggregates are tracked in index_meta via calls_total and calls_resolved.

  12. Regex considerations for git_search

    master

    When using regex=True in git_search, be aware of the differences between Python's re engine and git grep's POSIX ERE engine:

    1. Dialect Mismatch: Python re is a superset of POSIX ERE. Features like lookaheads (?=a) or named groups (?P<x>a) work in Python but will cause git grep to fail with a pattern error.
    2. Case Folding: git grep -i and Python's re.IGNORECASE use different Unicode case-folding rules. For exact matches, use literal strings with re.escape().
    3. Line Endings (CRLF): On CRLF files, git grep searches raw bytes. The $ anchor does not account for the CR byte. To match the end of a line in CRLF files, use [[:space:]]*$ instead of $.
    4. Binary Files: git grep -I handles binary files by content. The helper may provide hints if there is an incompatibility between engines when searching binary extensions.