mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-14 19:45:08 +08:00
fix(i18n): dynamically set window title from language pack instead of hardcoding
This commit is contained in:
parent
bcf37d95fe
commit
c8f3a12925
@ -0,0 +1,30 @@
|
|||||||
|
package vip.mate.agent.context;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 运行时上下文注入器 — 在 LLM 消息列表中预注入当前时间等运行时信息。
|
||||||
|
* <p>
|
||||||
|
* 参考 Claude Code 的 prependUserContext 模式:将时间信息作为首条 meta UserMessage 注入,
|
||||||
|
* 而非修改 System Prompt,以保持 prompt cache 命中率。
|
||||||
|
*/
|
||||||
|
public final class RuntimeContextInjector {
|
||||||
|
|
||||||
|
private static final ZoneId ZONE = ZoneId.of("Asia/Shanghai");
|
||||||
|
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
private static final DateTimeFormatter TIME_FMT = DateTimeFormatter.ofPattern("HH:mm");
|
||||||
|
|
||||||
|
private RuntimeContextInjector() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建运行时上下文消息,包含当前日期和时间。
|
||||||
|
*/
|
||||||
|
public static String buildContextMessage() {
|
||||||
|
LocalDateTime now = LocalDateTime.now(ZONE);
|
||||||
|
return "[system-context] 当前时间: " + now.format(DATE_FMT)
|
||||||
|
+ " " + now.format(TIME_FMT) + " (Asia/Shanghai)";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.ai.chat.messages.AssistantMessage;
|
import org.springframework.ai.chat.messages.AssistantMessage;
|
||||||
import org.springframework.ai.chat.messages.Message;
|
import org.springframework.ai.chat.messages.Message;
|
||||||
import org.springframework.ai.chat.messages.SystemMessage;
|
import org.springframework.ai.chat.messages.SystemMessage;
|
||||||
|
import org.springframework.ai.chat.messages.UserMessage;
|
||||||
import org.springframework.ai.chat.model.ChatModel;
|
import org.springframework.ai.chat.model.ChatModel;
|
||||||
import org.springframework.ai.chat.prompt.ChatOptions;
|
import org.springframework.ai.chat.prompt.ChatOptions;
|
||||||
import org.springframework.ai.chat.prompt.Prompt;
|
import org.springframework.ai.chat.prompt.Prompt;
|
||||||
@ -18,6 +19,7 @@ import vip.mate.agent.AgentToolSet;
|
|||||||
import vip.mate.agent.GraphEventPublisher;
|
import vip.mate.agent.GraphEventPublisher;
|
||||||
import vip.mate.agent.graph.NodeStreamingChatHelper;
|
import vip.mate.agent.graph.NodeStreamingChatHelper;
|
||||||
import vip.mate.agent.context.ConversationWindowManager;
|
import vip.mate.agent.context.ConversationWindowManager;
|
||||||
|
import vip.mate.agent.context.RuntimeContextInjector;
|
||||||
import vip.mate.agent.graph.state.FinishReason;
|
import vip.mate.agent.graph.state.FinishReason;
|
||||||
import vip.mate.agent.graph.state.MateClawStateAccessor;
|
import vip.mate.agent.graph.state.MateClawStateAccessor;
|
||||||
import vip.mate.agent.graph.state.MateClawStateKeys;
|
import vip.mate.agent.graph.state.MateClawStateKeys;
|
||||||
@ -155,6 +157,8 @@ public class ReasoningNode implements NodeAction {
|
|||||||
// 构建 Prompt,附带工具定义但禁用内部工具执行
|
// 构建 Prompt,附带工具定义但禁用内部工具执行
|
||||||
List<Message> promptMessages = new ArrayList<>();
|
List<Message> promptMessages = new ArrayList<>();
|
||||||
promptMessages.add(new SystemMessage(systemPrompt));
|
promptMessages.add(new SystemMessage(systemPrompt));
|
||||||
|
// 注入运行时上下文(当前时间),让 LLM 在推理阶段即可感知真实日期
|
||||||
|
promptMessages.add(new UserMessage(RuntimeContextInjector.buildContextMessage()));
|
||||||
promptMessages.addAll(messages);
|
promptMessages.addAll(messages);
|
||||||
|
|
||||||
ChatOptions options;
|
ChatOptions options;
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import vip.mate.agent.graph.plan.state.PlanStateAccessor;
|
|||||||
import vip.mate.agent.graph.plan.state.PlanStateKeys;
|
import vip.mate.agent.graph.plan.state.PlanStateKeys;
|
||||||
import vip.mate.agent.graph.state.MateClawStateKeys;
|
import vip.mate.agent.graph.state.MateClawStateKeys;
|
||||||
import vip.mate.agent.context.ConversationWindowManager;
|
import vip.mate.agent.context.ConversationWindowManager;
|
||||||
|
import vip.mate.agent.context.RuntimeContextInjector;
|
||||||
import vip.mate.planning.service.PlanningService;
|
import vip.mate.planning.service.PlanningService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -125,6 +126,8 @@ public class PlanGenerationNode implements NodeAction {
|
|||||||
// 构建 prompt 消息列表:system + 历史上下文 + 当前规划请求
|
// 构建 prompt 消息列表:system + 历史上下文 + 当前规划请求
|
||||||
List<Message> promptMessages = new ArrayList<>();
|
List<Message> promptMessages = new ArrayList<>();
|
||||||
promptMessages.add(new SystemMessage(systemPrompt + "\n\n" + PLANNING_PROMPT));
|
promptMessages.add(new SystemMessage(systemPrompt + "\n\n" + PLANNING_PROMPT));
|
||||||
|
// 注入运行时上下文(当前时间)
|
||||||
|
promptMessages.add(new UserMessage(RuntimeContextInjector.buildContextMessage()));
|
||||||
|
|
||||||
// 注入 working context(对话历史摘要),让规划能感知之前对话的约束和补充条件
|
// 注入 working context(对话历史摘要),让规划能感知之前对话的约束和补充条件
|
||||||
String workingContext = accessor.workingContext();
|
String workingContext = accessor.workingContext();
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import vip.mate.agent.graph.plan.state.PlanStateAccessor;
|
|||||||
import vip.mate.agent.graph.plan.state.PlanStateKeys;
|
import vip.mate.agent.graph.plan.state.PlanStateKeys;
|
||||||
import vip.mate.agent.graph.state.MateClawStateKeys;
|
import vip.mate.agent.graph.state.MateClawStateKeys;
|
||||||
import vip.mate.agent.context.ConversationWindowManager;
|
import vip.mate.agent.context.ConversationWindowManager;
|
||||||
|
import vip.mate.agent.context.RuntimeContextInjector;
|
||||||
import vip.mate.agent.graph.executor.ToolExecutionExecutor;
|
import vip.mate.agent.graph.executor.ToolExecutionExecutor;
|
||||||
import vip.mate.channel.web.ChatStreamTracker;
|
import vip.mate.channel.web.ChatStreamTracker;
|
||||||
import vip.mate.planning.service.PlanningService;
|
import vip.mate.planning.service.PlanningService;
|
||||||
@ -304,6 +305,8 @@ public class StepExecutionNode implements NodeAction {
|
|||||||
8. 每一步最多做一个必要的检查和一个必要的执行,不要无意义循环。
|
8. 每一步最多做一个必要的检查和一个必要的执行,不要无意义循环。
|
||||||
""";
|
""";
|
||||||
messages.add(new SystemMessage(enhancedSystemPrompt));
|
messages.add(new SystemMessage(enhancedSystemPrompt));
|
||||||
|
// 注入运行时上下文(当前时间)
|
||||||
|
messages.add(new UserMessage(RuntimeContextInjector.buildContextMessage()));
|
||||||
|
|
||||||
// Layer 2: Working context(对话历史 + 步骤结果的受控长度摘要)
|
// Layer 2: Working context(对话历史 + 步骤结果的受控长度摘要)
|
||||||
String workingContext = accessor.workingContext();
|
String workingContext = accessor.workingContext();
|
||||||
|
|||||||
@ -5,7 +5,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, watchEffect } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
import en from 'element-plus/es/locale/lang/en'
|
import en from 'element-plus/es/locale/lang/en'
|
||||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||||
import { currentLocale } from '@/i18n'
|
import { currentLocale } from '@/i18n'
|
||||||
@ -14,5 +15,11 @@ import { useThemeStore } from '@/stores/useThemeStore'
|
|||||||
// Initialize theme — applies .dark class to <html> immediately
|
// Initialize theme — applies .dark class to <html> immediately
|
||||||
useThemeStore()
|
useThemeStore()
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
document.title = t('app.title')
|
||||||
|
})
|
||||||
|
|
||||||
const elementLocale = computed(() => (currentLocale.value === 'en-US' ? en : zhCn))
|
const elementLocale = computed(() => (currentLocale.value === 'en-US' ? en : zhCn))
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
|
app: {
|
||||||
|
title: 'MateClaw - AI Assistant',
|
||||||
|
},
|
||||||
common: {
|
common: {
|
||||||
save: 'Save',
|
save: 'Save',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
|
app: {
|
||||||
|
title: 'MateClaw - AI 助手',
|
||||||
|
},
|
||||||
common: {
|
common: {
|
||||||
save: '保存',
|
save: '保存',
|
||||||
cancel: '取消',
|
cancel: '取消',
|
||||||
|
|||||||
@ -123,7 +123,7 @@
|
|||||||
:loading="isGenerating"
|
:loading="isGenerating"
|
||||||
:assistant-icon="currentAgent?.icon || '🤖'"
|
:assistant-icon="currentAgent?.icon || '🤖'"
|
||||||
:user-icon="userInitial"
|
:user-icon="userInitial"
|
||||||
:title="showModelPrompt ? modelPromptTitle : 'MateClaw'"
|
:title="showModelPrompt ? modelPromptTitle : $t('app.title')"
|
||||||
:subtitle="showModelPrompt ? modelPromptDesc : $t('chat.subtitle')"
|
:subtitle="showModelPrompt ? modelPromptDesc : $t('chat.subtitle')"
|
||||||
:suggestions="showModelPrompt ? [] : suggestions"
|
:suggestions="showModelPrompt ? [] : suggestions"
|
||||||
@regenerate="handleRegenerate"
|
@regenerate="handleRegenerate"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user