diff --git a/mateclaw-server/src/main/java/vip/mate/agent/context/ConversationWindowManager.java b/mateclaw-server/src/main/java/vip/mate/agent/context/ConversationWindowManager.java index 22482c7a..1e0c4550 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/context/ConversationWindowManager.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/context/ConversationWindowManager.java @@ -26,7 +26,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** - * 会话历史上下文窗口管理器(Hermes 风格升级版) + * 会话历史上下文窗口管理器(四阶段压缩升级版) *

* 四阶段压缩策略: *

    @@ -274,7 +274,7 @@ public class ConversationWindowManager { } int historyBudget = effectiveMax - reservedTokens; - // 尾部保护 token 预算:阈值的 20%(与 Hermes 一致) + // 尾部保护 token 预算:阈值的 20% int tailTokenBudget = (int) (triggerThreshold * 0.20); return compactMessages(messages, historyBudget, tailTokenBudget, chatModel, diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java index 0a51d30e..1122073a 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/NodeStreamingChatHelper.java @@ -772,7 +772,7 @@ public class NodeStreamingChatHelper { boolean broadcast, int attempt) { if (attempt > 0) { long delay = Math.min(BACKOFF_BASE_MS * (1L << (attempt - 1)), BACKOFF_CAP_MS); - // 加入 jitter 防止雷群效应(Hermes 风格) + // 加入 jitter 防止雷群效应 delay += ThreadLocalRandom.current().nextLong(0, Math.max(1, delay / 2)); delay = Math.min(delay, BACKOFF_CAP_MS); log.warn("[{}] Retry attempt {}/{} after {}ms for conversation {}", @@ -813,7 +813,7 @@ public class NodeStreamingChatHelper { AtomicInteger cacheWriteTokens = new AtomicInteger(0); // thinking-only soft cap 触发后设为 true,外层轮询线程据此 dispose 订阅。 - // 注意:内容流的字符级 / 句子级重复检测已整体移除(参考 Hermes 思路: + // 注意:内容流的字符级 / 句子级重复检测已整体移除(设计取舍: // agent 不替模型审核输出退化,靠 max_tokens + max_iterations 兜底); // 仅保留 thinking-only 这条体积兜底,处理 volcengine-plan 等 provider // 在 thinking 通道堆字符不出 content 的死循环(生产 trace c1eefa45)。 diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ObservationNode.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ObservationNode.java index 7bac57ba..9755ce93 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ObservationNode.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ObservationNode.java @@ -72,7 +72,7 @@ public class ObservationNode implements NodeAction { // 合并为单条观察记录 String combinedObservation = String.join("\n---\n", processedObservations); - // Budget Pressure Warning(Hermes 风格):接近上限时注入警告到工具结果中 + // Budget Pressure Warning:接近上限时注入警告到工具结果中 // LLM 下一轮 reasoning 时能看到,从而主动收束,而非被硬性截断 if (maxIterations > 0) { int progress = (int) ((double) nextIteration / maxIterations * 100); diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java index 3bbbb4d0..9c0494a7 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/ReasoningNode.java @@ -83,7 +83,7 @@ public class ReasoningNode implements NodeAction { private static final int DASHSCOPE_MAX_OUTPUT_TOKENS = 8192; /** - * Hermes-agent style enforcement clause appended to every ReasoningNode + * Tool-use enforcement clause appended to every ReasoningNode * system prompt. Treats narration ("I will now …") as a protocol violation * to prevent the recurring failure mode where a model says it will call a * tool but emits the description as final_answer text instead. diff --git a/mateclaw-server/src/main/java/vip/mate/config/ConversationWindowProperties.java b/mateclaw-server/src/main/java/vip/mate/config/ConversationWindowProperties.java index e69483ae..e3898a86 100644 --- a/mateclaw-server/src/main/java/vip/mate/config/ConversationWindowProperties.java +++ b/mateclaw-server/src/main/java/vip/mate/config/ConversationWindowProperties.java @@ -24,7 +24,7 @@ public class ConversationWindowProperties { /** 摘要自身最大 token 数(仅作 LLM maxToken 参数上限,实际预算由动态计算) */ private int summaryMaxTokens = 800; - // ==================== 动态压缩配置(Hermes 风格) ==================== + // ==================== 动态压缩配置 ==================== /** 尾部保护的最小消息数(即使 token 预算用完也至少保留这么多) */ private int protectLastMinMessages = 10; diff --git a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeApiHeaders.java b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeApiHeaders.java index 1d846e54..12c79d61 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeApiHeaders.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeApiHeaders.java @@ -11,8 +11,6 @@ import java.util.List; * *

    OAuth requests get extra beta headers + a User-Agent that masquerades as * Claude Code. Without these, Anthropic's infrastructure intermittently 500s. - * Reference: hermes-agent {@code anthropic_adapter} lines 226-238 + the - * dispatch in {@code build_anthropic_client} (line 423-433). * *

    Header reference

    * @@ -48,8 +46,7 @@ public class ClaudeCodeApiHeaders { /** * Comma-joined beta header list to send in {@code anthropic-beta}. - *

    Order matches hermes-agent {@code anthropic_adapter} line 427: - * {@code common_betas + _OAUTH_ONLY_BETAS} — common betas first, OAuth betas appended. + *

    Order is common betas first, OAuth-only betas appended. */ public String allBetas() { return String.join(",", @@ -61,14 +58,12 @@ public class ClaudeCodeApiHeaders { * Format: {@code claude-cli/} — bare, no suffix. * *

    History note: we previously appended {@code (external, cli)} - * after hermes-agent's pattern. That turned out to be wrong: Anthropic's - * anti-abuse gate uses the suffix to fingerprint third-party clients - * (hermes / OpenCode / Cline) and rate-limits them harder. Real Claude - * Code (Electron + Node + official Anthropic JS SDK) emits the bare - * {@code claude-cli/} form, which is what openclaw - * ({@code anthropic-transport-stream.ts:30,572}) also uses. Verified by - * reproducing 429 with the suffix and {@code anthropic-ratelimit-*} - * headers absent — the diagnostic signature of the anti-abuse path. + * to the User-Agent. That turned out to be wrong: Anthropic's anti-abuse + * gate uses the suffix to fingerprint third-party clients and rate-limits + * them harder. Real Claude Code (Electron + Node + official Anthropic JS + * SDK) emits the bare {@code claude-cli/} form. Verified by reproducing + * 429 with the suffix and {@code anthropic-ratelimit-*} headers absent — + * the diagnostic signature of the anti-abuse path. */ public String userAgent() { return "claude-cli/" + versionDetector.get(); diff --git a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsReader.java b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsReader.java index 150ff3c6..7d066be4 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsReader.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsReader.java @@ -36,9 +36,6 @@ import java.util.concurrent.TimeUnit; * } * } * - * - *

    Reference: hermes-agent {@code anthropic_adapter._read_claude_code_credentials_from_keychain} - * (line 470) and {@code read_claude_code_credentials} (line 530). */ @Slf4j @Component @@ -48,8 +45,8 @@ public class ClaudeCodeCredentialsReader { /** macOS Keychain service name written by Claude Code. */ static final String KEYCHAIN_SERVICE_NAME = "Claude Code-credentials"; - /** Hermes also queries {@code ~/.claude.json primaryApiKey} but that's a - * managed key, not OAuth — intentionally not read here. */ + /** {@code ~/.claude.json primaryApiKey} is a managed key, not OAuth — + * intentionally not read here. */ static final Path JSON_CREDENTIALS_PATH = Paths.get(System.getProperty("user.home"), ".claude", ".credentials.json"); diff --git a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsWriter.java b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsWriter.java index 14ca09f7..e91b5b23 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsWriter.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeCredentialsWriter.java @@ -45,10 +45,6 @@ import java.util.concurrent.TimeUnit; * preserve {@code scopes} (Claude Code >= 2.1.81 requires * {@code user:inference}) and any future fields we don't know about. *

- * - *

Reference: hermes-agent - * {@code anthropic_adapter._write_claude_code_credentials} (line 684-727) - * and {@code _write_claude_code_credentials_to_keychain} (line 730+). */ @Slf4j @Component diff --git a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeOAuthService.java b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeOAuthService.java index f3949f99..7ce5c87d 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeOAuthService.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeOAuthService.java @@ -31,9 +31,6 @@ import java.util.Optional; *

This service does NOT handle the OAuth login flow itself — that is * RFC-062 PR-4. Until then, MateClaw piggybacks on whatever credentials the * user already has on disk from their installed Claude Code client. - * - *

Reference: hermes-agent {@code anthropic_adapter._get_claude_code_token} - * + {@code _ensure_claude_code_token_fresh} (lines 540-605). */ @Slf4j @Service diff --git a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeTokenRefresher.java b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeTokenRefresher.java index 0ce3cc04..3da1432f 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeTokenRefresher.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeTokenRefresher.java @@ -32,16 +32,13 @@ import java.util.Map; *

The refresh request is a vanilla OAuth 2.0 refresh-token grant with the * public Claude Code {@code client_id}. We must spoof the Claude Code * {@code User-Agent} — Anthropic's edge filters drop unrecognised UAs. - * - *

Reference: hermes-agent {@code anthropic_adapter._refresh_claude_code_token} - * (line 605+). */ @Slf4j @Component @RequiredArgsConstructor public class ClaudeCodeTokenRefresher { - /** Public Claude Code OAuth client_id. Same value hermes-agent and OpenCode use. */ + /** Public Claude Code OAuth client_id. */ static final String CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"; /** Endpoints tried in order until one succeeds. */ diff --git a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeVersionDetector.java b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeVersionDetector.java index 389801d0..8e96244e 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeVersionDetector.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/anthropic/oauth/ClaudeCodeVersionDetector.java @@ -22,9 +22,6 @@ import java.util.regex.Pattern; * where Claude Code isn't installed locally (the OAuth flow may still work via * a manually-imported credentials file). * - *

Reference: hermes-agent {@code anthropic_adapter._detect_claude_code_version} - * (line 239) + {@code _CLAUDE_CODE_VERSION_FALLBACK} (line 235). - * *

Result is cached for the JVM lifetime (Anthropic's UA validation tolerates * a stable version per process). Restart MateClaw to pick up a Claude Code * upgrade. @@ -36,7 +33,7 @@ public class ClaudeCodeVersionDetector { /** * Static fallback version. Update this when bumping the floor at which * Anthropic accepts spoofed Claude Code traffic (track Anthropic's - * announcements + hermes-agent's same constant for cadence). + * announcements for cadence). */ static final String FALLBACK_VERSION = "2.1.74"; diff --git a/mateclaw-server/src/main/java/vip/mate/llm/cache/AnthropicCacheOptionsFactory.java b/mateclaw-server/src/main/java/vip/mate/llm/cache/AnthropicCacheOptionsFactory.java index b76e4c9b..7aa31e50 100644 --- a/mateclaw-server/src/main/java/vip/mate/llm/cache/AnthropicCacheOptionsFactory.java +++ b/mateclaw-server/src/main/java/vip/mate/llm/cache/AnthropicCacheOptionsFactory.java @@ -19,7 +19,7 @@ import java.util.Map; * *

映射规则(对应 RFC-014 Change 1 的 SystemAndTailCacheStrategy 默认行为): *