This is an automated email from the ASF dual-hosted git repository.
imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-toolchain.git
The following commit(s) were added to refs/heads/master by this push:
new 43d9447b refactor(client): add graphRequired option in
HugeClientBuilder (#718)
43d9447b is described below
commit 43d9447b0b19646634378f71c97f94ea48bcbe16
Author: Frosty <[email protected]>
AuthorDate: Sun Apr 26 02:10:35 2026 +0800
refactor(client): add graphRequired option in HugeClientBuilder (#718)
* refactor(client): replace skipRequiredChecks bool param with chainable
graphRequired() method
- Move url/graph validation from constructor to build() for true null
support
- Replace boolean constructor param with fluent .graphRequired(false) chain
method
- Rename field to graphRequired (default true) for clearer semantics
- Clean up HugeClient javadoc: remove redundant class/constructor comments
---------
Co-authored-by: imbajin <[email protected]>
---
.serena/project.yml | 125 ++++++++++++++-------
.../org/apache/hugegraph/driver/HugeClient.java | 11 +-
.../apache/hugegraph/driver/HugeClientBuilder.java | 21 ++--
.../org/apache/hugegraph/structure/auth/User.java | 6 +-
.../hugegraph/functional/HugeClientHttpsTest.java | 4 +-
.../hugegraph/unit/HugeClientBuilderTest.java | 78 +++++++++++++
6 files changed, 187 insertions(+), 58 deletions(-)
diff --git a/.serena/project.yml b/.serena/project.yml
index 7cea692f..edbab574 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 091e38fc..c681a76a 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 org.slf4j.LoggerFactory;
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 class HugeClient implements Closeable {
}
}
- // 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 9b9c03b9..2b5d547b 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 class HugeClientBuilder {
}
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 3f7ba4c6..3de439ae 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 class User extends AuthElement {
// Mapping of: graphSpace -> graph -> permission -> resourceType ->
resources
@JsonProperty("roles")
- private Map<String, Map<String, Map<HugePermission, Map<String,
List<HugeResource>>>>> roles;
+ private Map<String, Map<String, Map<HugePermission, Map<String,
+ List<HugeResource>>>>> roles;
- public Map<String, Map<String, Map<HugePermission, Map<String,
List<HugeResource>>>>> roles() {
+ public Map<String, Map<String, Map<HugePermission, Map<String,
+ List<HugeResource>>>>> 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 25b11fc1..3ad10481 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 class HugeClientHttpsTest extends BaseFuncTest {
.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 class HugeClientHttpsTest extends BaseFuncTest {
.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 00000000..c1379218
--- /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();
+ }
+}