Skip to content

feat:support auto context memory#163

Merged
AlbumenJ merged 24 commits intoagentscope-ai:mainfrom
shiyiyue1102:main-support-auto-context-memory
Dec 9, 2025
Merged

feat:support auto context memory#163
AlbumenJ merged 24 commits intoagentscope-ai:mainfrom
shiyiyue1102:main-support-auto-context-memory

Conversation

@shiyiyue1102
Copy link
Contributor

This pull request introduces the new AutoContextMemory extension for AgentScope, providing advanced context management for LLMs. It adds documentation in both English and Chinese, integrates the extension into the example projects, and demonstrates usage with a new example. The changes also include logging improvements and utility updates for API key management.

AutoContextMemory Extension

  • Added the new agentscope-extensions-autocontext-memory Maven module with its own pom.xml, enabling modular context memory management for AgentScope.
  • Added comprehensive documentation for AutoContextMemory in both English (README.md) and Chinese (README_zh.md), explaining its features, configuration, strategies, and best practices. [1] [2]

Integration and Example Usage

  • Integrated agentscope-extensions-autocontext-memory as a dependency in both agentscope-examples/pom.xml and agentscope-examples/advanced/pom.xml, making the extension available for example projects. [1] [2]
  • Added a new example class, AutoMemoryExample.java, demonstrating how to configure and use AutoContextMemory with other AgentScope components.
  • Updated ExampleUtils.java to provide a utility method for retrieving the Mem0 API key from environment variables, improving configuration robustness.

Logging Improvements

  • Enhanced logging configuration in logback.xml to include a console appender with improved log formatting and filtering, making debugging and monitoring easier.## AgentScope-Java Version

[The version of AgentScope-Java you are working on, e.g. 1.0.1, check your pom.xml dependency version or run mvn dependency:tree | grep agentscope-parent:pom(only mac/linux)]

Description

[Please describe the background, purpose, changes made, and how to test this PR]

Checklist

Please check the following items before code is ready to be reviewed.

  • Code has been formatted with mvn spotless:apply
  • All tests are passing (mvn test)
  • Javadoc comments are complete and follow project conventions
  • Related documentation has been updated (e.g. links, examples, etc.)
  • Code is ready for review

此提交添加了一个新的自动上下文记忆扩展模块及其相关配置和示例代码。同时更新了日志配置以支持控制台输出。

Change-Id: Ieaaa926f392fe9431b79a784169822c7e1449557
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交调整了自动上下文记忆中的压缩策略,增加了迭代次数限制,并特别处理了与计划相关的工具消息,减少了其详细参数和结果的保存。同时更新了提示文本以反映新的压缩规则。

Change-Id: I57b01e62fbc5a2af866422cf061b1813f4c81ccd
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
更新了`MemoryStorage`接口及其相关实现类的注释,增加了关于存储策略和线程安全性的详细说明。同时,调整了`AutoContextConfig`配置类的文档,添加了更多配置项的说明。此外,还完善了`README`文件中的配置参数介绍以及使用示例。

Change-Id: Ic4b231603d76404dc9f57cb90bbb9ad002b6df69
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
@shiyiyue1102 shiyiyue1102 requested a review from a team December 9, 2025 03:54
@codecov
Copy link

codecov bot commented Dec 9, 2025

在多个Java源文件中添加了Apache许可证的版权声明和许可声明。这确保了项目的合法性和开源合规性。

Change-Id: Iba82d07954956377d4a093e51c854347b5295d4f
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交在 `AutoMemoryExample.java` 和 `pom.xml` 文件中添加了版权声明及Apache许可证的相关信息。

Change-Id: I729bb99662b6b1d22c0e20945a913f1ad5dd29b1
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
移除了lombok的@DaTa注解,并为AutoContextConfig类的手动添加了getter和setter方法,以提高代码的透明度和可维护性。

Change-Id: Ica09125a3efb4c0899caa0c9984d70e02a9a328a
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
@shiyiyue1102 shiyiyue1102 changed the title support auto context memory feat:support auto context memory Dec 9, 2025
更新 `AutoContextMemory` 的内存存储机制,将 `MemoryStorage` 替换为 `ArrayList<Msg>`,并添加序列化与反序列化的支持。同时删除不再需要的 `InMemoryStorage` 和 `MemoryStorage` 类。

Change-Id: I93b5a488e7eccbdb37c8595c830b4a16f14fb3b5
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交将消息处理方法的返回类型从 `List<Msg>` 更改为 `List<String>`,并相应地调整了序列化与反序列化的实现方式。同时更新了相关调用处的配置。

Change-Id: I8645f01d654785432118b4ba52a7683ed5281d0c
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
更新了关于 AutoContextMemory 的存储机制和配置参数的文档,明确指出了内部使用的 `ArrayList<Msg>` 实现以及状态持久化的支持。移除了旧的工作存储和历史存储配置项的冗余说明。

Change-Id: I402b59f645a1164177db56916f31691acaaedf54
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces the AutoContextMemory extension for AgentScope, providing intelligent context management for LLMs through automatic compression, offloading, and summarization of conversation history. The implementation includes comprehensive documentation in both English and Chinese, along with integration into the example projects.

Key Changes:

  • New agentscope-extensions-autocontext-memory module with core context management functionality
  • Five progressive compression strategies (tool invocation compression, large message offloading, conversation summarization)
  • Support for both in-memory and file-based context storage via pluggable ContextOffLoader interface

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
docs/en/task/autocontext-momery.md English documentation for AutoContextMemory (filename has spelling error)
docs/zh/task/autocontext-memory.md Chinese documentation for AutoContextMemory
agentscope-extensions/pom.xml Adds new autocontext-memory module to extensions
agentscope-extensions/agentscope-extensions-mem0/.../Mem0LongTermMemory.java Filters out compressed history messages from Mem0 recording
agentscope-extensions/agentscope-extensions-autocontext-memory/pom.xml POM configuration for new extension module
agentscope-extensions/.../AutoContextMemory.java Core implementation of intelligent context memory management
agentscope-extensions/.../AutoContextConfig.java Configuration class for compression thresholds and offloading settings
agentscope-extensions/.../ContextOffLoader.java Interface for pluggable context storage backends
agentscope-extensions/.../InMemoryContextOffLoader.java In-memory implementation of context offloading
agentscope-extensions/.../LocalFileContextOffLoader.java File-based implementation of context offloading (has type safety issues)
agentscope-extensions/.../ContextOffloadTool.java Tool for reloading offloaded context by UUID
agentscope-extensions/.../TokenCounterUtil.java Utility for estimating token counts in messages
agentscope-extensions/.../MsgUtils.java Utilities for message serialization/deserialization (has API design issues)
agentscope-extensions/.../Pair.java Generic pair record for holding two values
agentscope-extensions/.../Prompts.java Prompt templates for compression and summarization
agentscope-examples/pom.xml Adds autocontext-memory dependency to examples
agentscope-examples/advanced/pom.xml Adds autocontext-memory dependency to advanced examples
agentscope-examples/.../logback.xml Adds console appender with INFO level filtering
agentscope-examples/.../ExampleUtils.java Adds utility method for retrieving Mem0 API key
agentscope-examples/.../AutoMemoryExample.java Example demonstrating AutoContextMemory usage with ReActAgent

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

int thresholdToken = (int) (autoContextConfig.maxToken * autoContextConfig.tokenRatio);
boolean tokenCounterReached = calculateToken >= thresholdToken;
if (!msgCountReached && !tokenCounterReached) {
return new ArrayList<>(new ArrayList<>(workingMemoryStorage));
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant nested new ArrayList<>() call. The outer new ArrayList<>() is unnecessary since workingMemoryStorage is already being copied. This should be:

return new ArrayList<>(workingMemoryStorage);
Suggested change
return new ArrayList<>(new ArrayList<>(workingMemoryStorage));
return new ArrayList<>(workingMemoryStorage);

Copilot uses AI. Check for mistakes.
Comment on lines 882 to 895
* compress tools invocation.
*
* @param messages tools msg to compress.
* @return
*/
private Msg compressToolsInvocation(List<Msg> messages, String offloadUUid) {

GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUUid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUUid)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect return type in Javadoc. The method returns boolean but the @return tag is missing. Also, the parameter offloadUUid is misspelled (should be offloadUuid with lowercase 'u').

Suggested change
* compress tools invocation.
*
* @param messages tools msg to compress.
* @return
*/
private Msg compressToolsInvocation(List<Msg> messages, String offloadUUid) {
GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUUid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUUid)
* Compresses tool invocation messages.
*
* @param messages tools msg to compress.
* @param offloadUuid UUID for offloading content (may be null).
* @return a compressed {@link Msg} containing the summarized tool invocation history.
*/
private Msg compressToolsInvocation(List<Msg> messages, String offloadUuid) {
GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUuid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUuid)

Copilot uses AI. Check for mistakes.
Comment on lines 145 to 151
public static String serializeMsgStrings(List<String> msgs) {
try {
return OBJECT_MAPPER.writeValueAsString(msgs);
} catch (Exception e) {
throw new RuntimeException("Failed to serialize messages", e);
}
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method signature and implementation have a type mismatch. The method accepts List<String> but the TypeReference is defined for List<String>, yet the serialization code in serializeMsgList actually produces List<Map<String, Object>>. The method name serializeMsgStrings and parameter name suggest it should handle strings, but it's being used to serialize message objects (maps). This naming and typing inconsistency makes the API confusing and error-prone.

Copilot uses AI. Check for mistakes.
Comment on lines 787 to 793
* that can be compressed. It searches for sequences of more than 4 consecutive tool messages
* before the latest assistant message.
*
* <p>Strategy:
* 1. If rawMessages has less than lastKeep messages, return null
* 2. Find the latest assistant message and protect it and all messages after it
* 3. Search from the beginning for the oldest consecutive tool messages (more than 4 consecutive)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect comment. Line 792 states "more than 4 consecutive" but the code at line 843 checks consecutiveCount > autoContextConfig.minConsecutiveToolMessages where minConsecutiveToolMessages defaults to 6. The comment should be updated to reference the configuration parameter instead of hardcoding "4".

Suggested change
* that can be compressed. It searches for sequences of more than 4 consecutive tool messages
* before the latest assistant message.
*
* <p>Strategy:
* 1. If rawMessages has less than lastKeep messages, return null
* 2. Find the latest assistant message and protect it and all messages after it
* 3. Search from the beginning for the oldest consecutive tool messages (more than 4 consecutive)
* that can be compressed. It searches for sequences of more than autoContextConfig.minConsecutiveToolMessages consecutive tool messages
* before the latest assistant message.
*
* <p>Strategy:
* 1. If rawMessages has less than lastKeep messages, return null
* 2. Find the latest assistant message and protect it and all messages after it
* 3. Search from the beginning for the oldest consecutive tool messages (more than autoContextConfig.minConsecutiveToolMessages consecutive)

Copilot uses AI. Check for mistakes.
int searchEndIndex =
(latestAssistantIndex >= 0) ? latestAssistantIndex : (totalSize - lastKeep);

// Step 3: Find the oldest consecutive tool messages (more than 4 consecutive)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent comment. Line 828 says "more than 4 consecutive" but should reference minConsecutiveToolMessages configuration parameter (defaults to 6, not 4). This is inconsistent with the actual implementation.

Suggested change
// Step 3: Find the oldest consecutive tool messages (more than 4 consecutive)
// Step 3: Find the oldest consecutive tool messages (more than autoContextConfig.minConsecutiveToolMessages consecutive; default is 6)

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,260 @@
# AutoContextMemory
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling error in filename: "momery" should be "memory".

Copilot uses AI. Check for mistakes.
&& !msg.getTextContent().isEmpty())
&& !msg.getTextContent().isEmpty()
&& !msg.getTextContent()
.contains("compressed_history"))
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This filter logic is fragile. Messages containing the string "compressed_history" anywhere in their text content will be filtered out, which could unintentionally exclude legitimate messages that happen to mention this term. Consider using a more robust approach, such as:

  1. Adding a metadata field to Msg to mark compressed messages
  2. Using a more specific marker pattern (e.g., a unique prefix or UUID pattern)
  3. Checking for the exact XML-style tags <compressed_history> instead of just the substring
Suggested change
.contains("compressed_history"))
.contains("<compressed_history>"))

Copilot uses AI. Check for mistakes.

int totalSize = rawMessages.size();

// Step 1: If rawMessages has less than 20 messages, return null
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic number without clear justification. The comment on line 809 says "If rawMessages has less than 20 messages, return null", but the code checks against lastKeep (which defaults to 50, not 20). Either:

  1. Update the comment to match the actual logic: "If rawMessages has less than lastKeep messages, return null"
  2. Or if 20 is the intended threshold, use a constant instead of lastKeep
Suggested change
// Step 1: If rawMessages has less than 20 messages, return null
// Step 1: If rawMessages has less than lastKeep messages, return null

Copilot uses AI. Check for mistakes.
* a summary containing the first 100 characters and a hint to reload if needed.
*
* @param rawMessages the list of messages to process
* @param lastKeep whether to keep the last N messages (unused in current implementation)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lastKeep parameter is documented as "unused in current implementation" (line 681), but it is actually used in the method starting at line 690. This comment is incorrect and misleading.

Suggested change
* @param lastKeep whether to keep the last N messages (unused in current implementation)
* @param lastKeep unused parameter (retained for compatibility; not used in current implementation)

Copilot uses AI. Check for mistakes.
msg, new TypeReference<Map<String, Object>>() {});
} catch (Exception e) {
throw new RuntimeException(
"Failed to serialize message: " + msg, e);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default toString(): Msg inherits toString() from Object, and so is not suitable for printing.

Copilot uses AI. Check for mistakes.
移除了对外部上下文存储实现的依赖,将相关逻辑整合到 `AutoContextMemory` 类内部。同时更新了序列化与反序列化的处理方法。

Change-Id: I5b289284fa4ddf6e2c0343285b7ac28ccb482484
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交主要进行了代码格式的调整以及相关文档的更新,具体包括移除多余的导入语句、调整方法调用的格式以及更新关于内存管理的相关文档说明。

Change-Id: Ic9f561d799dc6d21813c3fb9dbc6bf95832997d5
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交为`MsgUtils`类添加详细的注释,并优化各个方法的功能说明,使其更易于理解和维护。主要涉及序列化和反序列化消息列表及其映射的方法。

Change-Id: Iaa202afaf8d9119bfb3a052265ca0634487f777c
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
修正了文档文件名中的拼写错误,从 `autocontext-momery.md` 更改为 `autocontext-memory.md`。

Change-Id: Id4bbf321cbc11baec1252ebf342ff8329a114c0f
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
简化了内存压缩逻辑中的冗余部分,并更新了相关方法的注释以便更清楚地说明其工作原理及处理流程。同时修正了一些检查条件中的字符串匹配问题。

Change-Id: Ibd3b3de28f090702b647e08ce8100676feb69ac4
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 11 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* Extract tool messages from raw messages for compression.
*
* <p>This method finds consecutive tool invocation messages in historical conversations
* that can be compressed. It searches for sequences of more than consecutive tool messages
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete documentation: The Javadoc mentions "Extract tool messages from raw messages for compression" and states "sequences of more than consecutive tool messages", but it's missing the number. It should say "more than minConsecutiveToolMessages consecutive tool messages" to be complete and accurate.

Suggested change
* that can be compressed. It searches for sequences of more than consecutive tool messages
* that can be compressed. It searches for sequences of more than {@code minConsecutiveToolMessages} consecutive tool messages

Copilot uses AI. Check for mistakes.
* a summary containing the first 100 characters and a hint to reload if needed.
*
* @param rawMessages the list of messages to process
* @param lastKeep whether to keep the last N messages (unused in current implementation)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misleading parameter documentation: The Javadoc states "(unused in current implementation)" for the lastKeep parameter, but this is incorrect. The parameter is actually used extensively in the method starting from line 692 to determine whether to protect the last N messages. This documentation should be corrected to accurately reflect the parameter's usage.

Suggested change
* @param lastKeep whether to keep the last N messages (unused in current implementation)
* @param lastKeep (currently ignored) - whether to keep the last N messages; the value from configuration (autoContextConfig.getLastKeep()) is used instead

Copilot uses AI. Check for mistakes.
Comment on lines +915 to +923
private Msg compressToolsInvocation(List<Msg> messages, String offloadUUid) {

GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUUid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUUid)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in variable name: offloadUUid should be offloadUuid (with lowercase 'u'). This variable is referenced throughout the method and should follow consistent camelCase naming.

Suggested change
private Msg compressToolsInvocation(List<Msg> messages, String offloadUUid) {
GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUUid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUUid)
private Msg compressToolsInvocation(List<Msg> messages, String offloadUuid) {
GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUuid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUuid)

Copilot uses AI. Check for mistakes.
<module>agentscope-extensions-mem0</module>
<module>agentscope-extensions-studio</module>
<module>agentscope-extensions-session-redis</module>
<module>agentscope-extensions-session-redis</module>
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent whitespace: This line uses tabs for indentation while the rest of the file uses spaces. This violates consistent formatting and may cause issues with code style checkers.

Suggested change
<module>agentscope-extensions-session-redis</module>
<module>agentscope-extensions-session-redis</module>

Copilot uses AI. Check for mistakes.
Comment on lines +906 to +923
* If an {@code offloadUUid} is provided, the compressed message will include a hint
* indicating that the original content can be reloaded using the UUID via
* {@link ContextOffloadTool}.
*
* @param messages the list of tool invocation messages to compress (must not be null or empty)
* @param offloadUUid the UUID of the offloaded original messages, or null if not offloaded
* @return a new ASSISTANT message containing the compressed tool invocation summary
* @throws RuntimeException if LLM processing fails or is interrupted
*/
private Msg compressToolsInvocation(List<Msg> messages, String offloadUUid) {

GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUUid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUUid)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in variable name: offloadUUid should be offloadUuid (with lowercase 'u'). This parameter name is used in the method signature and should match the correct camelCase convention.

Suggested change
* If an {@code offloadUUid} is provided, the compressed message will include a hint
* indicating that the original content can be reloaded using the UUID via
* {@link ContextOffloadTool}.
*
* @param messages the list of tool invocation messages to compress (must not be null or empty)
* @param offloadUUid the UUID of the offloaded original messages, or null if not offloaded
* @return a new ASSISTANT message containing the compressed tool invocation summary
* @throws RuntimeException if LLM processing fails or is interrupted
*/
private Msg compressToolsInvocation(List<Msg> messages, String offloadUUid) {
GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUUid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUUid)
* If an {@code offloadUuid} is provided, the compressed message will include a hint
* indicating that the original content can be reloaded using the UUID via
* {@link ContextOffloadTool}.
*
* @param messages the list of tool invocation messages to compress (must not be null or empty)
* @param offloadUuid the UUID of the offloaded original messages, or null if not offloaded
* @return a new ASSISTANT message containing the compressed tool invocation summary
* @throws RuntimeException if LLM processing fails or is interrupted
*/
private Msg compressToolsInvocation(List<Msg> messages, String offloadUuid) {
GenerateOptions options = GenerateOptions.builder().build();
ReasoningContext context = new ReasoningContext("tool_compress");
String compressContentFormat =
Prompts.COMPRESSED_HISTORY_FORMAT
+ ((offloadUuid != null)
? String.format(
Prompts.COMPRESSED_HISTORY_OFFLOAD_HINT, offloadUuid)

Copilot uses AI. Check for mistakes.
Comment on lines 735 to 771
String uuid = null;
// Check if message content exceeds threshold
if (textContent != null && textContent.length() > threshold) {
// Offload the original message
uuid = UUID.randomUUID().toString();
List<Msg> offloadMsg = new ArrayList<>();
offloadMsg.add(msg);
offload(uuid, offloadMsg);
log.info(
"Offloaded large payload message at index "
+ i
+ ", size: "
+ textContent.length()
+ " chars, uuid: "
+ uuid);
}

// Create replacement message with first 100 characters and offload hint
String preview =
textContent.length() > autoContextConfig.offloadSinglePreview
? textContent.substring(0, autoContextConfig.offloadSinglePreview)
+ "..."
: textContent;

String offloadHint = String.format(Prompts.OFFLOAD_HINT_FORMAT, preview, uuid);

// Create replacement message preserving original role and name
Msg replacementMsg =
Msg.builder()
.role(msg.getRole())
.name(msg.getName())
.content(TextBlock.builder().text(offloadHint).build())
.build();

// Replace the original message
rawMessages.set(i, replacementMsg);
hasOffloaded = true;
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic error: The code creates and replaces messages unconditionally for all messages in the loop (lines 752-771), even when they don't exceed the threshold. The uuid variable is only assigned when textContent.length() > threshold (line 737-750), but it's used unconditionally on line 759, which will result in null being passed to String.format. The replacement logic should be inside the if block (lines 737-750) so that only messages exceeding the threshold are offloaded and replaced.

Copilot uses AI. Check for mistakes.
Comment on lines +753 to +757
String preview =
textContent.length() > autoContextConfig.offloadSinglePreview
? textContent.substring(0, autoContextConfig.offloadSinglePreview)
+ "..."
: textContent;
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable textContent may be null at this access as suggested by this null guard.

Suggested change
String preview =
textContent.length() > autoContextConfig.offloadSinglePreview
? textContent.substring(0, autoContextConfig.offloadSinglePreview)
+ "..."
: textContent;
String preview;
if (textContent != null) {
preview =
textContent.length() > autoContextConfig.offloadSinglePreview
? textContent.substring(0, autoContextConfig.offloadSinglePreview) + "..."
: textContent;
} else {
preview = "";
}

Copilot uses AI. Check for mistakes.
Comment on lines +144 to +145
throw new RuntimeException(
"Failed to serialize message: " + msg, e);
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default toString(): Msg inherits toString() from Object, and so is not suitable for printing.

Suggested change
throw new RuntimeException(
"Failed to serialize message: " + msg, e);
String msgJson;
try {
msgJson = OBJECT_MAPPER.writeValueAsString(msg);
} catch (Exception jsonEx) {
msgJson = "[unserializable Msg: " + jsonEx.getMessage() + "]";
}
throw new RuntimeException(
"Failed to serialize message: " + msgJson, e);

Copilot uses AI. Check for mistakes.
public void offload(String uuid, List<Msg> messages) {
offloadContext.put(uuid, messages);
}

Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides ContextOffLoader.reload; it is advisable to add an Override annotation.

Suggested change
@Override

Copilot uses AI. Check for mistakes.
此次更新改进了 `AutoMemoryExample` 和 `AutoContextConfig` 的配置构建方式,采用Builder模式替代直接实例化的方式,并删除了一些不再需要的代码部分。

Change-Id: I4e72cf7134d38df36712d90142bb40f087b1e58c
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此修复在处理自动上下文记忆时添加了对UUID为空的检查,从而避免潜在的空指针异常。

Change-Id: Ia7447f4a564712ed3842cef5533605982fcea6bc
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
修正了pom.xml中的模块配置格式问题,保证其正确性与一致性。

Change-Id: I2912b6fa5fb62fb79ef5f6d9edf472b6069e425a
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交修复了在处理空消息列表时返回空列表的问题,并改进了助手响应检测逻辑,确保不将工具调用视为最终响应。同时增加了获取存储上下文的方法。

Change-Id: I1b4a5808afe122f0fd90629f98c73927afc19b86
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
此提交删除了已过时的任务自动上下文内存相关文档,以保持文档集的准确性和时效性。

Change-Id: I1164f38d027b25e9bdca2b94fb0e5a654d4412a0
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
shiyiyue1102 and others added 3 commits December 9, 2025 19:40
此提交删除了已过时的任务自动上下文内存相关文档,以保持文档集的准确性和时效性。

Change-Id: Iaca9a8774564681dd9c8bf7074552c9688161778
Co-developed-by: Aone Copilot <noreply@alibaba-inc.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@AlbumenJ AlbumenJ merged commit ca28e87 into agentscope-ai:main Dec 9, 2025
3 checks passed
qingTang0305 pushed a commit to qingTang0305/agentscope-java that referenced this pull request Dec 10, 2025
JGoP-L pushed a commit to JGoP-L/agentscope-java that referenced this pull request Dec 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants