diff --git a/.serena/project.yml b/.serena/project.yml index 7cea692f2..edbab5745 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -1,15 +1,26 @@ + + # list of languages for which language servers are started; choose from: -# al bash clojure cpp csharp csharp_omnisharp -# dart elixir elm erlang fortran go -# haskell java julia kotlin lua markdown -# nix perl php python python_jedi r -# rego ruby ruby_solargraph rust scala swift -# terraform typescript typescript_vts zig +# al bash clojure cpp csharp +# csharp_omnisharp dart elixir elm erlang +# fortran fsharp go groovy haskell +# haxe 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: -# - csharp: Requires the presence of a .sln file in the project folder. +# 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. @@ -20,14 +31,12 @@ languages: # For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings encoding: "utf-8" -# whether to use the project's gitignore file to ignore files -# Added on 2025-04-07 +# whether to use project's .gitignore files to ignore files ignore_all_files_in_gitignore: true -# list of additional paths to ignore -# same syntax as gitignore, so you can use * and ** -# Was previously called `ignored_dirs`, please update your config if you are using that. -# Added (renamed) on 2025-04-07 +# 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: [] # whether the project is in read-only mode @@ -35,45 +44,48 @@ ignored_paths: [] # 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. +# list of tool names to exclude. +# This extends the existing exclusions (e.g. from the global configuration) +# # 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. +# * `activate_project`: Activates a project based on the project name or path. # * `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. +# * `delete_memory`: Delete a memory file. Should only happen if a user asks for it explicitly, +# for example by saying that the information retrieved from a memory file is no longer correct +# or no longer relevant for the project. +# * `edit_memory`: Replaces content matching a regular expression in a memory. # * `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). +# * `find_file`: Finds files in the given relative paths +# * `find_referencing_symbols`: Finds symbols that reference the given symbol using the language server backend +# * `find_symbol`: Performs a global (or local) search using the language server backend. # * `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. +# * `initial_instructions`: Provides instructions Serena usage (i.e. the 'Serena Instructions Manual') +# for clients that do not read the initial instructions when the MCP server is connected. # * `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. +# * `list_memories`: List available memories. Any memory can be read using the `read_memory` tool. # * `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. +# * `read_memory`: Read the content of a memory file. This tool should only be used if the information +# is relevant to the current task. You can infer whether the information +# is relevant from the memory file name. +# You should not read the same memory file multiple times in the same conversation. +# * `rename_memory`: Renames or moves a memory. Moving between project and global scope is supported +# (e.g., renaming "global/foo" to "bar" moves it from global to project scope). +# * `rename_symbol`: Renames a symbol throughout the codebase using language server refactoring capabilities. +# For JB, we use a separate tool. +# * `replace_content`: Replaces content in a file (optionally using regular expressions). +# * `replace_symbol_body`: Replaces the full definition of a symbol using the language server backend. +# * `safe_delete_symbol`: # * `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. +# * `write_memory`: Write some information (utf-8-encoded) about this project that can be useful for future tasks to a memory in md format. +# The memory name should be meaningful. excluded_tools: [] # initial prompt for the project. It will always be given to the LLM upon activating the project @@ -82,7 +94,8 @@ initial_prompt: "" # the name by which the project can be referenced within Serena project_name: "toolchain" -# 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 (particularly optional tools that are disabled by default). +# This extends the existing inclusions (e.g. from the global configuration). included_optional_tools: [] # list of mode names to that are always to be included in the set of active modes @@ -103,3 +116,39 @@ default_modes: [] # 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_tools: [] + +# time budget (seconds) per tool call for the retrieval of additional symbol information +# such as docstrings or parameter information. +# This overrides the corresponding setting in the global configuration; see the documentation there. +# If null or missing, use the setting from the global configuration. +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: + +# line ending convention to use when writing source files. +# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default) +# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings. +line_ending: + +# list of regex patterns which, when matched, mark a memory entry as read‑only. +# Extends the list from the global configuration, merging the two lists. +read_only_memory_patterns: [] + +# list of regex patterns for memories to completely ignore. +# Matching memories will not appear in list_memories or activate_project output +# and cannot be accessed via read_memory or write_memory. +# To access ignored memory files, use the read_file tool on the raw file path. +# Extends the list from the global configuration, merging the two lists. +# Example: ["_archive/.*", "_episodes/.*"] +ignored_memory_patterns: [] + +# advanced configuration option allowing to configure language server-specific options. +# Maps the language key to the options. +# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available. +# No documentation on options means no options are available. +ls_specific_settings: {} diff --git a/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java b/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java index 091e38fc2..c681a76a9 100644 --- a/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java +++ b/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java @@ -32,9 +32,8 @@ import com.google.common.base.Strings; /** - * The HugeClient class is the main entry point for interacting with a HugeGraph server. - * It provides methods for managing graphs, schemas, jobs, tasks, and other resources. - * It also implements the Closeable interface, so it can be used in a try-with-resources statement. + * Main entry point for HugeGraph server operations. + * Use {@link #builder(String, String, String)} to create an instance. */ public class HugeClient implements Closeable { @@ -72,11 +71,6 @@ public class HugeClient implements Closeable { private WhiteIpListManager whiteIpListManager; private VermeerManager vermeerManager; - /** - * Constructs a new HugeClient using the provided builder. - * - * @param builder the HugeClientBuilder to use for configuration - */ public HugeClient(HugeClientBuilder builder) { this.borrowedClient = false; this.graphSpaceName = builder.graphSpace(); @@ -111,7 +105,6 @@ public HugeClient(HugeClientBuilder builder) { } } - // QUESTION: add gs to method param? public HugeClient(HugeClient client, String graphSpace, String graph) { this.borrowedClient = true; this.client = client.client; diff --git a/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClientBuilder.java b/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClientBuilder.java index 9b9c03b9e..2b5d547b3 100644 --- a/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClientBuilder.java +++ b/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClientBuilder.java @@ -50,13 +50,9 @@ public class HugeClientBuilder { /** Set them null by default to keep compatibility with 'timeout' */ private Integer connectTimeout; private Integer readTimeout; + private boolean graphRequired = true; public HugeClientBuilder(String url, String graphSpace, String graph) { - E.checkArgument(url != null && !url.isEmpty(), - "Expect a string value as the url parameter argument, but got: %s", url); - E.checkArgument(graph != null && !graph.isEmpty(), - "Expect a string value as the graph name parameter argument, but got: %s", - graph); this.url = url; this.graphSpace = graphSpace; this.graph = graph; @@ -76,11 +72,22 @@ public HugeClientBuilder(String url, String graphSpace, String graph) { } public HugeClient build() { - E.checkArgument(this.url != null, "The url parameter can't be null"); - E.checkArgument(this.graph != null, "The graph parameter can't be null"); + if (this.graphRequired) { + E.checkArgument(this.url != null && !this.url.isEmpty(), + "Expect a string value as the url parameter argument, but got: %s", + this.url); + E.checkArgument(this.graph != null && !this.graph.isEmpty(), + "Expect a string value as the graph name parameter argument, but got: %s", + this.graph); + } return new HugeClient(this); } + public HugeClientBuilder graphRequired(boolean graphRequired) { + this.graphRequired = graphRequired; + return this; + } + public HugeClientBuilder configGraphSpace(String graphSpace) { this.graphSpace = graphSpace; return this; diff --git a/hugegraph-client/src/main/java/org/apache/hugegraph/structure/auth/User.java b/hugegraph-client/src/main/java/org/apache/hugegraph/structure/auth/User.java index 3f7ba4c6e..3de439ae7 100644 --- a/hugegraph-client/src/main/java/org/apache/hugegraph/structure/auth/User.java +++ b/hugegraph-client/src/main/java/org/apache/hugegraph/structure/auth/User.java @@ -155,9 +155,11 @@ public static class UserRole { // Mapping of: graphSpace -> graph -> permission -> resourceType -> resources @JsonProperty("roles") - private Map>>>> roles; + private Map>>>> roles; - public Map>>>> roles() { + public Map>>>> roles() { return Collections.unmodifiableMap(this.roles); } diff --git a/hugegraph-client/src/test/java/org/apache/hugegraph/functional/HugeClientHttpsTest.java b/hugegraph-client/src/test/java/org/apache/hugegraph/functional/HugeClientHttpsTest.java index 25b11fc1e..3ad104816 100644 --- a/hugegraph-client/src/test/java/org/apache/hugegraph/functional/HugeClientHttpsTest.java +++ b/hugegraph-client/src/test/java/org/apache/hugegraph/functional/HugeClientHttpsTest.java @@ -139,7 +139,7 @@ public void testHttpsClientBuilderWithConnectionPoolNoParam() { .configSSL("", "") .build(); }, e -> { - Assert.assertContains("The url parameter can't be null", + Assert.assertContains("Expect a string value as the url parameter argument", e.getMessage()); }); } @@ -153,7 +153,7 @@ public void testHttpsClientBuilderWithConnectionPoolNoGraphParam() { .configSSL("", "") .build(); }, e -> { - Assert.assertContains("The graph parameter can't be null", + Assert.assertContains("Expect a string value as the graph name parameter argument", e.getMessage()); }); } diff --git a/hugegraph-client/src/test/java/org/apache/hugegraph/unit/HugeClientBuilderTest.java b/hugegraph-client/src/test/java/org/apache/hugegraph/unit/HugeClientBuilderTest.java new file mode 100644 index 000000000..c1379218a --- /dev/null +++ b/hugegraph-client/src/test/java/org/apache/hugegraph/unit/HugeClientBuilderTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package org.apache.hugegraph.unit; + +import org.apache.hugegraph.driver.HugeClient; +import org.apache.hugegraph.driver.HugeClientBuilder; +import org.junit.Assert; +import org.junit.Test; + +public class HugeClientBuilderTest { + + @Test + public void testConstructorAcceptsNullUrlAndGraph() { + HugeClientBuilder builder = new HugeClientBuilder(null, "DEFAULT", null); + Assert.assertNotNull(builder); + } + + @Test + public void testGraphRequiredFalseSkipsBuildValidation() { + // graphRequired(false) must skip IllegalArgumentException — only connection-level + // failure is expected since no server is available in unit tests + try { + HugeClient.builder(null, "DEFAULT", null).graphRequired(false).build(); + Assert.fail("Expected connection-level exception"); + } catch (IllegalArgumentException e) { + Assert.fail("Should not throw IllegalArgumentException — validation must be skipped"); + } catch (Exception e) { + // Expected: validation was skipped, failed at HTTP connection as intended + } + } + + @Test(expected = IllegalArgumentException.class) + public void testBuildFailsWithNullUrl() { + HugeClient.builder(null, "DEFAULT", "hugegraph").build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuildFailsWithNullGraph() { + HugeClient.builder("http://127.0.0.1:8080", "DEFAULT", null).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuildFailsWithEmptyUrl() { + HugeClient.builder("", "DEFAULT", "hugegraph").build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuildFailsWithEmptyGraph() { + HugeClient.builder("http://127.0.0.1:8080", "DEFAULT", "").build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuildFailsAfterConfigGraphNull() { + HugeClient.builder("http://127.0.0.1:8080", "DEFAULT", "hugegraph") + .configGraph(null).build(); + } + + @Test(expected = IllegalArgumentException.class) + public void testBuildFailsAfterConfigUrlNull() { + HugeClient.builder("http://127.0.0.1:8080", "DEFAULT", "hugegraph") + .configUrl(null).build(); + } +}