diff --git a/.gitignore b/.gitignore index 54ca872..9ae433a 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,6 @@ _BUILDS/cosmos-demo-2026-02-05/ # Manual backup folders scripts/openclaw/restore-feb8/ _BUILDS/ + +# Serena memories (local) +.serena/memories/ diff --git a/.serena/project.yml b/.serena/project.yml index 209832e..51bb4ad 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -1,124 +1,61 @@ # the name by which the project can be referenced within Serena -project_name: "factorylm-monorepo" +project_name: "factorylm" -# list of languages for which language servers are started; choose from: -# al bash clojure cpp csharp -# csharp_omnisharp dart elixir elm erlang -# fortran fsharp go groovy haskell -# java julia kotlin lua markdown -# matlab nix pascal perl php -# php_phpactor powershell python python_jedi r -# rego ruby ruby_solargraph rust scala -# swift terraform toml typescript typescript_vts -# vue yaml zig -# (This list may be outdated. For the current list, see values of Language enum here: -# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py -# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.) -# Note: -# - For C, use cpp -# - For JavaScript, use typescript -# - For Free Pascal/Lazarus, use pascal -# Special requirements: -# Some languages require additional setup/installations. -# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers -# When using multiple languages, the first language server that supports a given file will be used for that file. -# The first language is the default language and the respective language server will be used as a fallback. -# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored. +# list of languages for which language servers are started languages: -- java +- python +- typescript # the encoding used by text files in the project -# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings -encoding: "utf-8" +encoding: utf-8 # whether to use project's .gitignore files to ignore files ignore_all_files_in_gitignore: true # list of additional paths to ignore in this project. -# Same syntax as gitignore, so you can use * and **. -# Note: global ignored_paths from serena_config.yml are also applied additively. -ignored_paths: [] +ignored_paths: +- "node_modules/**" +- "_BUILDS/**" +- "output/**" +- "Io_sim_images/**" +- "traces/**" +- "my-ralph/**" +- "recordings/**" +- "test_images/**" +- "video/**" +- ".claude/**" +- "docs/archive/**" # whether the project is in read-only mode -# If set to true, all editing tools will be disabled and attempts to use them will result in an error -# Added on 2025-04-18 read_only: false -# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details. -# Below is the complete list of tools for convenience. -# To make sure you have the latest list of tools, and to view their descriptions, -# execute `uv run scripts/print_tool_overview.py`. -# -# * `activate_project`: Activates a project by name. -# * `check_onboarding_performed`: Checks whether project onboarding was already performed. -# * `create_text_file`: Creates/overwrites a file in the project directory. -# * `delete_lines`: Deletes a range of lines within a file. -# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. -# * `execute_shell_command`: Executes a shell command. -# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. -# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). -# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). -# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. -# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. -# * `initial_instructions`: Gets the initial instructions for the current project. -# Should only be used in settings where the system prompt cannot be set, -# e.g. in clients you have no control over, like Claude Desktop. -# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. -# * `insert_at_line`: Inserts content at a given line in a file. -# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. -# * `list_dir`: Lists files and directories in the given directory (optionally with recursion). -# * `list_memories`: Lists memories in Serena's project-specific memory store. -# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). -# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). -# * `read_file`: Reads a file within the project directory. -# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. -# * `remove_project`: Removes a project from the Serena configuration. -# * `replace_lines`: Replaces a range of lines within a file with new content. -# * `replace_symbol_body`: Replaces the full definition of a symbol. -# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. -# * `search_for_pattern`: Performs a search for a pattern in the project. -# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. -# * `switch_modes`: Activates modes by providing a list of their names -# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. -# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. -# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. -# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +# list of tool names to exclude. excluded_tools: [] -# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default) +# list of tools to include that would otherwise be disabled included_optional_tools: [] -# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools. -# This cannot be combined with non-empty excluded_tools or included_optional_tools. +# fixed set of tools to use as the base tool set fixed_tools: [] +# initial prompt for the project. +initial_prompt: > + FactoryLM monorepo — industrial AI platform diagnosing factory faults + using NVIDIA Cosmos Reason 2. Key dirs: cosmos/ (client, watcher, agent), + services/matrix/ (FastAPI + SQLite), diagnosis/ (conveyor fault rules), + sim/ (PLC simulator + Factory I/O bridge), core/ (shared Python library). + Pipeline: Factory I/O -> Modbus TCP -> Matrix API -> Cosmos -> Diagnosis. + SAFETY: NEVER modify code tagged # SAFETY, # PLC, or # CRITICAL. + # list of mode names to that are always to be included in the set of active modes -# The full set of modes to be activated is base_modes + default_modes. -# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply. -# Otherwise, this setting overrides the global configuration. -# Set this to [] to disable base modes for this project. -# Set this to a list of mode names to always include the respective modes for this project. base_modes: # list of mode names that are to be activated by default. -# The full set of modes to be activated is base_modes + default_modes. -# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply. -# Otherwise, this overrides the setting from the global configuration (serena_config.yml). -# This setting can, in turn, be overridden by CLI parameters (--mode). default_modes: -# initial prompt for the project. It will always be given to the LLM upon activating the project -# (contrary to the memories, which are loaded on demand). -initial_prompt: "" - -# override of the corresponding setting in serena_config.yml, see the documentation there. -# If null or missing, the value from the global config is used. +# time budget (seconds) per tool call for the retrieval of additional symbol information symbol_info_budget: # The language backend to use for this project. -# If not set, the global setting from serena_config.yml is used. -# Valid values: LSP, JetBrains -# Note: the backend is fixed at startup. If a project with a different backend -# is activated post-init, an error will be returned. language_backend: diff --git a/CLAUDE.md b/CLAUDE.md index 8e0e0d8..b0467ec 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,6 +15,9 @@ doppler run -p openclaw -c dev -- bash -c 'export GEMINI_API_KEY=$(doppler secre ``` Resume-aware — safe to run repeatedly. ~1,400/day (Gemini free tier). 2,706 total turns. +--- + + ## Role: CTO & Lead Engineer You are the CTO and lead engineer for FactoryLM's factory automation stack. diff --git a/agents/serena_agent.py b/agents/serena_agent.py new file mode 100644 index 0000000..b5c9d19 --- /dev/null +++ b/agents/serena_agent.py @@ -0,0 +1,37 @@ +"""FactoryLM Serena Agent — Agno-powered web UI for codebase navigation. + +Launch via: doppler run -p factorylm -c dev -- uv run python agents/serena_agent.py --project . +Requires: serena[agno] installed in Desktop/serena venv. +UI: connect Agent UI at http://localhost:3000 to http://localhost:7777 +""" +import sys +from pathlib import Path + +# Add the serena source to path so we can import it +SERENA_ROOT = Path(__file__).resolve().parent.parent.parent / "serena" +if SERENA_ROOT.exists(): + sys.path.insert(0, str(SERENA_ROOT / "src")) + +from agno.models.anthropic.claude import Claude +from agno.os import AgentOS +from sensai.util import logging as sensai_logging + +from serena.agno import SerenaAgnoAgentProvider + +if __name__ == "__main__": + sensai_logging.configure(level=sensai_logging.INFO) + +model = Claude(id="claude-sonnet-4-20250514") + +serena_agent = SerenaAgnoAgentProvider.get_agent(model) + +agent_os = AgentOS( + description="FactoryLM coding assistant — industrial AI codebase navigation", + id="factorylm-serena", + agents=[serena_agent], +) + +app = agent_os.get_app() + +if __name__ == "__main__": + agent_os.serve(app="serena_agent:app", reload=False) diff --git a/kb/telegram/.brain_backfill_state b/kb/telegram/.brain_backfill_state index 62f33a1..1c090c6 100644 --- a/kb/telegram/.brain_backfill_state +++ b/kb/telegram/.brain_backfill_state @@ -2,4 +2,4 @@ "last_line": 2705, "total_ingested": 2706, "updated_at": "2026-03-03T17:24:30Z" -} \ No newline at end of file +} diff --git a/scripts/start_serena_agent.sh b/scripts/start_serena_agent.sh new file mode 100644 index 0000000..2ad50c5 --- /dev/null +++ b/scripts/start_serena_agent.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Start the FactoryLM Serena Agent with Agno web UI +# Requires: serena[agno] installed in ~/Desktop/serena/.venv +# UI: connect Agent UI at http://localhost:3000 to http://localhost:7777 + +SERENA_ROOT="C:/Users/hharp/OneDrive/Desktop/serena" +FACTORYLM_ROOT="C:/Users/hharp/OneDrive/Desktop/FactoryLM" + +cd "$SERENA_ROOT" || exit 1 + +export SERENA_ROOT + +doppler run -p factorylm -c dev -- \ + uv run python "$FACTORYLM_ROOT/agents/serena_agent.py" \ + --project "$FACTORYLM_ROOT" diff --git a/services/mcp/brain_server.py b/services/mcp/brain_server.py index 7e52642..84008b2 100644 --- a/services/mcp/brain_server.py +++ b/services/mcp/brain_server.py @@ -171,9 +171,16 @@ def brain_ingest_file(file_path: str, source: str = "repo", tags: list[str] = [] except RuntimeError as e: return {"error": str(e)} +<<<<<<< HEAD from kb.chunker import chunk_file chunks = chunk_file(file_path, extra_metadata={"tags": tags}) +======= + with open(file_path, "r", encoding="utf-8") as f: + content = f.read() + # Chunk large files by paragraphs + chunks = [c.strip() for c in content.split("\n\n") if c.strip() and len(c.strip()) > 50] +>>>>>>> 433ffad (feat(brain): graceful fallback + Open Brain startup protocol) if not chunks: with open(file_path, "r", encoding="utf-8") as f: