- 当前仓库之前只有
AGENTS.md/Todo.md/write-by-AGENT.md,本次补齐了第一版 Forge mod 代码骨架。 - v0 已实现两条 API:
POST /v1/commandGET /v1/players/{username}/state
- 已新增 AI 驱动入口:
POST /v1/ai/run
- 已新增游戏内命令入口(OP3+):
/agent chat <message>/agent cancel/agent reset
- 当前命令执行使用服务端控制台权限(
CommandSourceStack+ 权限 4)。 - 输出捕获通过
CapturingCommandSource收集sendSystemMessage,若无输出会返回默认提示。 - 玩家查询仅支持在线玩家
username,离线或不存在统一返回 404 +PLAYER_NOT_FOUND。 - OpenAI-compatible 已接入真实请求链路(chat completions),并启用 tools:
execute_commandget_player_state
- 已新增
AgentOrchestrator:- 单实例忙碌锁(不排队)
- 全局滚动上下文(游戏内/HTTP/控制台共享)
- 可取消当前运行(
/agent cancel)
- 实时广播已接入 orchestrator sink:
- 工具调用:立即广播工具名 + 传入参数
- 工具输出:不广播(安全)
- Agent结果:立即完整广播
- 已增加联网工具(始终可用):
search_web:通过 DuckDuckGo HTML 结果页提取title/url/snippetfetch_url:仅允许http/https,并受openai.networkTimeoutMs与openai.networkMaxResponseBytes限制
- 已增加视觉能力开关:
openai.enableVision=false时不向模型暴露视觉工具openai.enableVision=true时暴露get_item_texture
get_item_texture行为:- 输入
itemId(支持省略命名空间时默认minecraft:) - 先检查注册表是否存在该物品,再返回贴图候选路径
- 支持模组 ID 场景:即使无法解析到实际资源,也返回候选与状态码(不中断会话)
- 输入
openai.requestTimeoutMs与openai.maxToolIterations已加入配置。openai.networkTimeoutMs、openai.networkMaxResponseBytes与openai.enableVision已加入配置。agent.contextMaxMessages与agent.commandPermissionLevel已加入配置。- 配置入口在
AutoMinecraftConfig,含 API host/port/token、timeout、OpenAI 兼容配置。 - 单元测试目前只覆盖纯 Java 逻辑(鉴权/路由/命令规范化),未跑 Forge 集成测试。
- 先在真实 Forge 运行一次,检查
Commands/CommandSourceStack在 1.21.8 映射下的方法签名是否完全一致。 - 若命令输出捕获不完整,可切到 callback 或复用 RCON source 策略。
- 如果后续适配 Responses API 或多模型路由,可在
OpenAiAgentService基础上扩展 provider 策略层。 - 目前共享上下文采用“滚动窗口拼接文本”;后续可替换为专用模型压缩上下文。
- 模型配置已升级为
providers[] + models[] + defaultModelKey:- 文件:
config/minecraft-command-agent/models.json - 模型键格式:
providerAlias.modelAlias(支持provider.xxx.yyy)
- 文件:
ModelRegistry现负责:- 维护
defaultModelId/currentModelId - 解析优先级:
request.model>current>default - 热重载时保留旧快照(新配置非法不会覆盖旧目录)
- 校验模型键前缀与 provider alias 一致性
- 维护
- provider 能力已内置三种原生客户端:
OpenAiProviderClient(/chat/completions)AnthropicProviderClient(/messages,含工具调用映射)GeminiProviderClient(:generateContent,含 function call 映射)
OpenAiAgentService改为按ResolvedModelConfig动态选择 provider client;每次运行绑定具体模型键。- 广播保持实时且带模型标记:
- 工具调用:
[AGENT:TOOL][model:<key>] - 结果输出:
[AGENT:RESULT][model:<key>]
- 工具调用:
- 游戏模型管理命令保持:
/agent model list/agent model current/agent model use <key>/agent model reload
- HTTP 侧模型字段:
- 请求
AiRunRequest.model(可选) - 响应
AiRunResponse.resolvedModelId(回显实际执行模型键) - provider 上游异常统一为
502 AI_UPSTREAM_ERROR
- 请求
- 新增模型元数据:
models[].description(人工配置,供模型自动选择调用目标)ModelRegistry新增listModelDescriptors()暴露key + description
- 新增工具
call_model(向模型暴露):- 参数:
targetModel、task、mode(return|handoff)、可选systemPrompt/maxIterations mode=return:被调模型结果作为工具输出返回给当前模型继续处理mode=handoff:当前模型立即结束,本次请求直接返回被调模型结果(不改变全局 current model)
- 参数:
- 编排层支持递归子调用:
AgentOrchestrator可在同一次 run 内创建子模型执行- 子调用也走实时广播,广播
model为实际执行模型 key - 共享同一份主上下文快照(不做模型私有上下文分裂)
- 新增防护阈值配置(
AutoMinecraftConfig):agent.maxModelCallDepth(默认 3)agent.maxModelCallsPerRun(默认 8)- 对应错误码:
MODEL_CALL_DEPTH_EXCEEDED、MODEL_CALL_BUDGET_EXCEEDED、MODEL_CALL_TARGET_NOT_FOUND、MODEL_CALL_SELF_RECURSION_BLOCKED
- 构建约定(已同步到
AGENTS.md):- 构建命令固定为
GRADLE_USER_HOME=/tmp/gradle gradle --no-daemon build - 构建需在沙箱外执行;仅该完整命令免手动确认
- 构建命令固定为
- 新增上下文压缩模型配置:
models.json顶层新增compactModelKey(未配置时回落defaultModelKey)ModelRegistry新增compactModelId()与resolveCompactModel()
- 新增手动压缩命令:
/agent compact- 忙碌时与 chat 一致:直接拒绝,不排队
- 新增自动压缩触发(估算 token):
agent.autoCompactEnabled=trueagent.compactAutoThresholdTokens=12000agent.compactTargetTokens=5000agent.compactKeepRecentMessages=4
- 压缩执行语义:
- 压缩模型运行时禁用所有工具(含
call_model) - 压缩输出要求 JSON(
summary+estimatedTokens),解析失败时降级为文本摘要并本地估算长度 - 写回上下文为:
COMPACT_SUMMARY+ 最近 N 条原上下文 - 自动压缩失败会广播错误并继续原请求(不阻断)
- 压缩模型运行时禁用所有工具(含
- 新增固定用户提示词配置:
agent.fixedUserPrompt(内联字符串)agent.fixedUserPromptFile(UTF-8 文本文件路径,优先于内联)- 解析策略:文件非空用文件;文件空白回退内联;文件不可读直接报错
- 运行时注入语义:
- 每次对话模型调用新增一条独立
user消息作为固定用户提示词(系统提示词之外) - 主模型与
call_model的子模型调用都会携带该固定提示词
- 每次对话模型调用新增一条独立
- 压缩语义更新:
compact输入里会带完整固定用户提示词- 压缩系统指令明确“固定提示词未来会重复完整注入”,避免摘要重复抄全文
- 单测新增:
FixedUserPromptResolverTest(文件/内联优先级与错误路径)OpenAiAgentServiceTest增补固定用户提示词消息注入行为
- 新增会话存储
ChatSessionStore(落盘到config/minecraft-command-agent/chats.json):- 会话类型:
global与私有owner.alias - 持久化内容:会话配置(
model/systemPrompt/userPrompt)、会话上下文、owner 当前会话指针 - 私有别名校验:
[a-z0-9_-]{1,32},global为保留字
- 会话类型:
AgentOrchestrator重构为“按会话运行状态”:- 不同会话可并发执行
- 忙碌锁与取消从全局改为会话级
chat/cancel/reset/compact均以“当前会话”为作用域- 广播回调新增路由上下文(global 或私有 owner/initiator)
- 游戏命令新增:
/agent chatswitch list|new <id>|<id|global>/agent chatconfig <chat> <model|systemPrompt|userPrompt> <value|inherit>/agent model改为废弃提示(引导使用chatconfig global model)
- 推送语义:
global保持全服广播- 私有会话改为仅 owner + 执行者可见(在线玩家)
- HTTP 入口保持 global-only(
/v1/ai/run未开放私有会话) - 单测新增:
ChatSessionStoreTest(默认状态、创建切换、继承覆盖、持久化恢复、保留字校验)
- 已将模组
mod_id从auto_minecraft改为minecraft_command_agent。 gradle.properties同步更新:mod_id=minecraft_command_agentmod_name=Minecraft Command Agentmod_authors=minecraft-command-agent
- 默认配置目录改名:
- 模型目录:
config/minecraft-command-agent/models.json - 会话目录:
config/minecraft-command-agent/chats.json
- 模型目录:
- 示例模型配置文件已迁移到
config/minecraft-command-agent/models.json。
OpenAiAgentService新增 10 个工具并接入统一工具分发:- 方块:
set_block、get_block_data、merge_block_data - 实体:
summon_entity、get_entity_data、merge_entity_data、kill_entity - 管理:
ban_player、kick_player、unban_player
- 方块:
- 新工具实现策略:
- 结构化参数输入 + 固定命令模板拼接
- 通过
execute in <dimension> run ...支持可选维度参数(不传维度时默认控制台当前维度) - 对 token/坐标/资源 ID 做基础格式校验,减少命令拼接风险
- 新增封禁/踢出理由模板配置(Forge config):
agent.banReasonTemplatesagent.kickReasonTemplates- 格式
key=template,变量仅允许{player}/{actor}/{input}/{time} ban_player/kick_player支持templateKey与reasonInput
- 返回语义:
- 新工具统一返回
{ok, exitCode, command, output, executedAt, ...tool-specific-fields} - 参数错误统一
INVALID_ARGUMENTS
- 新工具统一返回
- 单测更新:
OpenAiAgentServiceTest已补充断言,验证工具清单包含上述新增工具
- 新增权限配置中心
PermissionRegistry(文件:config/minecraft-command-agent/permissions.json):- 配置粒度:
chats.<chatId> - 字段:
allow[]、deny[]、defaultPolicy - 匹配语法:
*(单段)与**(多段) - 判定顺序:
deny优先;未命中走defaultPolicy - chat 回退:未配置 chatId 时回退
global
- 配置粒度:
OpenAiAgentService新增工具权限策略接口ToolPermissionPolicy,工具执行前统一鉴权:- 普通工具节点:
tools.<toolName> execute_command额外节点:tools.command.<brigadier_path>- 通过 Brigadier parse 路径生成,参数节点使用占位符如
<targets> - 会生成从“最具体 -> 最泛化”的链路节点(例如到
tools.command)
- 通过 Brigadier parse 路径生成,参数节点使用占位符如
- 被拒绝时返回
TOOL_PERMISSION_DENIED(工具失败,不中断整轮)
- 普通工具节点:
AgentOrchestrator接入会话级权限上下文:- 每次 run 按 chatId 解析权限快照
- 主模型与
call_model子模型共用同一权限上下文(禁止子模型越权) - compact run 继续 tools disabled,不参与工具权限判定
- 新增命令:
/agent perm reload(重载permissions.json)
- 新增默认权限文件:
config/minecraft-command-agent/permissions.json- 默认
global.defaultPolicy=deny+allow=["tools.**"](等价默认兼容全开,可按需收紧)
- 单测新增:
PermissionRegistryTest(默认文件生成、deny优先、chat回退、*/**匹配)
- 新增
WorkflowRegistry(配置:config/minecraft-command-agent/workflows.json):- 支持字段:
id/description/enabled/boundChatId/prompt/model/systemPrompt/userPrompt/allowManual/allowSessionCall/schedules schedules支持两类:interval(intervalSeconds)与cron(5段表达式)- 缺失配置文件会自动生成默认示例(
hourly_audit,默认禁用)
- 支持字段:
AgentOrchestrator新增工作流运行时:- 定时调度线程(1s tick),按 interval/cron 触发
- 同一 workflow 并发保护:运行中重复触发返回
WORKFLOW_BUSY - 运行上下文语义:
- 定时触发:空上下文
run_workflow触发:复制调用方上下文快照(只读)- 工作流执行不写回任何 chat 上下文
- 配置继承语义:workflow 基于
boundChatId的有效配置,可被 workflow 自身model/systemPrompt/userPrompt覆盖 - 权限语义:
- 调用方会话需通过
tools.run_workflow(与可选tools.run_workflow.<id>)检查 - 工作流执行期工具权限使用
boundChatId对应权限策略
- 调用方会话需通过
OpenAiAgentService新增工具run_workflow:- 参数:
workflowId(必填)、input(可选) - 返回结构包含 workflow id、实际模型、finishReason、toolCalls、content/usage
- 默认系统提示词已提示模型可使用
run_workflow
- 参数:
- 新增命令:
/agent workflow list/agent workflow reload/agent workflow run <id> [input]
- 新增测试:
WorkflowRegistryTest(默认文件生成、interval+cron 解析、cron 匹配、重复 id 拒绝)OpenAiAgentServiceTest增加run_workflow工具清单断言