- Java 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
浏览器掐断识别为 WARN;上游中断时下发 detached;管理端 SSE 复用 AmcHttpSupport。 Co-authored-by: Cursor <cursoragent@cursor.com> |
||
| src/main | ||
| .gitignore | ||
| pom.xml | ||
| README.md | ||
| version.md | ||
amcc-agent-chat-spring-boot-starter
对接 智能体管理中心(AMC,agent_manage_center_api) 的 Spring Boot Starter。
跑在宿主进程内:换票、缓存 chatToken、代理会话 / SSE / 转写 / 下载 / 智能体绑定,浏览器不直连 AMC,也不直连 Hermes TUI(方案 B)。
| 项 | 值 |
|---|---|
| 源码仓 | https://forgejo.bingjun360.com/SouTan/amcc-agent-chat-spring-boot-starter |
| Maven 坐标 | com.soutan:amcc-agent-chat-spring-boot-starter:1.0.1 |
| Maven 仓库 | https://forgejo.bingjun360.com/api/packages/SouTan/maven |
| 包页 | https://forgejo.bingjun360.com/SouTan/-/packages |
| Java 包名 | com.mvker.amcc.* |
| 运行要求 | Spring Boot 2.7.x / Java 8 |
| 版本说明 | 见 version.md |
1. 相对旧版 amcc 升级了什么
旧依赖是 amcc-agent-chat-client(无 Spring 的 HTTP 客户端)。宿主要自己写 Controller、token 缓存、用户解析、响应包装。
| 能力 | 旧 amcc-agent-chat-client |
现 Starter 1.0.1 |
|---|---|---|
| 形态 | 纯 jar,无自动配置 | Spring Boot Starter + spring.factories |
| Maven 坐标 | com.souta:amcc-agent-chat-client(已废弃) |
com.soutan:amcc-agent-chat-spring-boot-starter |
| 包仓库归属 | 文档曾写 adminUser |
SouTan 组织 |
| HTTP 客户端 | AmcAgentChatClient 需手建 Bean |
amc.enabled=true 时自动注册 |
| chatToken 缓存 | 宿主自写 ConcurrentHashMap | 内置 AmcAgentChatFacade(按 bizUserId) |
| 管理端 HTTP | 宿主手写 Controller | 默认注册 /business/agentChat/*(可关) |
| 大屏 HTTP | 宿主手写 | 默认注册 /dashboard/agentChat/messages(可关) |
| 智能体配置 | 宿主手写 | 默认注册 /system/agentConfig/*(可关) |
| 用户 / 权限 / 响应 | 绑死宿主类型或复制代码 | SPI:AmcBizUserResolver 等 |
| 路由注册方式 | @RestController(易被 com.mvker 扫描重复) |
RouterFunction |
| legacy ws-handoff | 常默认暴露 | 默认关闭(legacy-ws-handoff=false) |
从旧 client 迁到 Starter 的步骤概要:
- 父 POM / 业务模块:去掉
amcc-agent-chat-client,改为com.soutan:amcc-agent-chat-spring-boot-starter,仓库改为…/api/packages/SouTan/maven。 - 删除宿主里自建的
AmcAgentChatClient@Bean、自写 token 缓存 Service(若已切到 Starter 路由,也可删对话/配置 Controller)。 - 配置
amc.*(见下文);实现至少一个AmcBizUserResolver。 - 若前端 axios 要
code=200的信封,实现AmcJsonResponseWrapper;大屏实现AmcDashboardUserResolver,并在安全配置里放行大屏路径(@AuthIgnore扫不到 RouterFunction)。 - Reload Maven,回归管理端对话、下载、大屏发消息、配置 CRUD。
细节以能碳(yuanzhou_api)为准,见第 5 节。
2. Maven 引入
父 POM:
<properties>
<amcc.starter.version>1.0.1</amcc.starter.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.soutan</groupId>
<artifactId>amcc-agent-chat-spring-boot-starter</artifactId>
<version>${amcc.starter.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>forgejo</id>
<url>https://forgejo.bingjun360.com/api/packages/SouTan/maven</url>
</repository>
</repositories>
业务模块:
<dependency>
<groupId>com.soutan</groupId>
<artifactId>amcc-agent-chat-spring-boot-starter</artifactId>
</dependency>
~/.m2/settings.xml 中 server.id 必须是 forgejo,且开启 usePreemptive,否则拉私有包 / 发包会 401。
3. 配置项
amc:
enabled: true
base-url: http://127.0.0.1:9960 # AMC 基址,勿带尾斜杠
tenant-code: your-tenant-code # AMC tenant_info.tenant_code
connect-timeout-ms: 5000
read-timeout-ms: 30000
long-read-timeout-ms: 120000
token-refresh-skew-seconds: 120 # 可省略,视为 0
# sse-read-timeout-ms: 320000
bff:
manage-enabled: true
dashboard-enabled: true
config-enabled: true
legacy-ws-handoff: false
# path-prefix: /business/agentChat
# dashboard-path-prefix: /dashboard
# config-path-prefix: /system/agentConfig
enabled=true 时,base-url / tenant-code / 三个超时必须显式填写,不会用 Java 默认值静默兜底。
| 开关 | 默认 | 作用 |
|---|---|---|
amc.bff.manage-enabled |
true | 管理端对话路由 |
amc.bff.dashboard-enabled |
true | 大屏发消息路由 |
amc.bff.config-enabled |
true | 智能体配置路由 |
amc.bff.legacy-ws-handoff |
false | 暴露 legacy ws-handoff |
宿主若仍保留自己的同名 Controller,对应开关必须设为 false,否则路径冲突。
4. 自动注册的 HTTP
路由使用 RouterFunction,避免宿主 scanBasePackages 含 com.mvker 时再注册一份 Controller。
4.1 管理端(manage-enabled)
前缀默认 /business/agentChat,对齐 @souta/agent-chat-ui transport。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /context |
绑定智能体列表;{ superAdmin, agents[] } |
| GET | /sessions?agentId= |
会话列表 |
| POST | /sessions |
创建 { agentId, title? } |
| POST | /sessions/{storedId}/open |
打开并拉历史 |
| DELETE | /sessions/{storedId}?agentId= |
删除 |
| POST | /sessions/{sessionId}/messages |
SSE;JSON 或 multipart |
| POST | /audio/transcribe |
语音转写 |
| GET | /files/download?path= |
附件字节流 |
| POST | /ws-handoff |
仅 legacy-ws-handoff=true |
当前用户来自 AmcBizUserResolver。chatToken 不出现在响应中。
4.2 大屏(dashboard-enabled)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /dashboard/agentChat/messages |
SSE;body 含 unicode、text,可选 sessionId / agentId / 附件 |
| POST | /dashboard/hermes/ws-handoff |
仅 legacy 打开时 |
unicode 交给 AmcDashboardUserResolver,不走登录用户,也不走对话权限门闩。
4.3 智能体配置(config-enabled)
| 方法 | 路径 |
|---|---|
| POST | /system/agentConfig/list |
| GET | /system/agentConfig/profiles |
| GET | /system/agentConfig/{id} |
| POST | /system/agentConfig/add |
| POST | /system/agentConfig/edit |
| POST | /system/agentConfig/delete |
列表字段:rows/total/current/size,行上可含姓名、部门等(由 AmcConfigUserDirectory 补齐)。
4.4 响应形态
- JSON 成功体经
AmcJsonResponseWrapper(默认原样返回)。 - SSE、文件下载不走包装。
- 业务错误经
AmcExceptionTranslator(默认AmcAgentChatAccessException)。
5. SPI
| SPI | 何时需要 | 作用 |
|---|---|---|
AmcBizUserResolver |
开管理端 | 当前登录用户 → AMC bizUserId |
AmcDashboardUserResolver |
开大屏 | 场景键(如 unicode)→ 大屏业务用户 id |
AmcConfigUserDirectory |
配置页要展示/绑定本地用户 | 查 userName、昵称、部门等 |
AmcJsonResponseWrapper |
前端要统一信封 | 如包成 { code, msg, data } |
AmcExceptionTranslator |
要统一异常类型 | 如转成宿主 BusinessException |
AmcPermissionGate |
要在 Starter 内做权限 | checkConversationAccess / checkConfigAccess;默认放行 |
有 Spring Security 且 principal 为数字时,Starter 可提供默认 AmcBizUserResolver;LoginUser 一类必须自建 Bean。
6. 示范:能碳 yuanzhou_api 如何接入
能碳已完全依赖本 Starter:删除自研 AgentChatController / DashboardAgentChatController / AgentConfigController 及 BFF 实现,只保留适配代码。
6.1 依赖
父 POM nscode-business-base:
amcc.starter.version=1.0.1dependencyManagement管理com.soutan:amcc-agent-chat-spring-boot-starterrepositories增加 ForgejoSouTanMaven
业务模块 nscode-yuanzhou:
<dependency>
<groupId>com.soutan</groupId>
<artifactId>amcc-agent-chat-spring-boot-starter</artifactId>
</dependency>
6.2 yml(节选)
amc:
enabled: true
base-url: http://amc-prod.bingjun360.com/prod-api
tenant-code: yuanzhouzhengfu
connect-timeout-ms: 5000
read-timeout-ms: 30000
long-read-timeout-ms: 120000
token-refresh-skew-seconds: 120
# bff 开关未写 = 全部用默认 true;legacy-ws-handoff 默认 false
6.3 宿主适配类(保留在能碳源码)
| 类 | 路径 | 职责 |
|---|---|---|
YuanzhouAmcConfiguration |
com.mvker.amc.starter |
五个 SPI Bean |
YuanzhouAmcDashboardSecurity |
同上 | 大屏路径 permitAll |
DashboardSysUserSupport |
com.mvker.amc.support |
查 user_name=dashboard 用户 |
AmcJsonResponseWrapper:包成 R.ok(body),满足 axios 拦截器对 code === 200 的要求。SSE / 下载不包装。
AmcBizUserResolver:SecurityUtils.getLoginUser(false).getUser().getUserId()。
AmcExceptionTranslator:转成 BusinessException,走 qlcloud 全局异常处理。
AmcDashboardUserResolver:DashboardUnicodeSupport.requireCommunity(unicode) 后,DashboardSysUserSupport.requireDashboardUserId()。
AmcConfigUserDirectory:SysUserMapper 批量/单条查询,填充 AmcConfigUser(含 userName,供绑定接口使用)。
YuanzhouAmcDashboardSecurity:@Order(1) 的 WebSecurityConfigurerAdapter,只匹配
{dashboardPathPrefix}/agentChat/** 与 …/hermes/** 并 permitAll。
原因:生产 debugMode=false 时,qlcloud 的 @AuthIgnore 只收集 @RequestMapping 的 Controller,扫不到 Starter 的 RouterFunction。
6.4 前端(不变路径)
管理端页 yuanzhou_ui/.../business/agentChat/index.vue:@souta/agent-chat-ui 的 AgentChatApp + transport 打 /business/agentChat/*(JWT 头 YzAuthorization)。
大屏 DashboardVoiceChat:transport 打 /dashboard/agentChat/messages,body 带页面闭包的 unicode。
6.5 能碳侧文件清单(接入后)
应存在:
nscode-business/.../amc/starter/YuanzhouAmcConfiguration.javanscode-business/.../amc/starter/YuanzhouAmcDashboardSecurity.javanscode-business/.../amc/support/DashboardSysUserSupport.java
不应再存在(已删除):
amc/controller/AgentChatController等三套 Controlleramc/service/**BFF- 宿主自建的
amc/config/AmcAgentChatProperties(改用 Starter 的配置类)
7. 完整对接(新宿主)
按下列顺序做完,即可同时具备:管理端对话、大屏发消息、智能体配置 CRUD。
能碳落地细节见第 6 节;本节是可直接照抄改写的通用清单。
7.1 前置条件(AMC 侧)
- AMC 已部署,记下对外基址(如
http://amc-prod…/prod-api,勿带尾斜杠)。 - 在 AMC 建好租户,记下
tenant_code(对应宿主amc.tenant-code)。 - 租户下已有可用 Hermes profile / 智能体定义;业务用户绑定可在宿主配置页完成,或先在 AMC 手工绑一条做联调。
- 宿主能访问 AMC 网络(防火墙 / 内网 DNS)。
7.2 Maven
父 POM(版本集中管理 + 仓库):
<properties>
<amcc.starter.version>1.0.1</amcc.starter.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.soutan</groupId>
<artifactId>amcc-agent-chat-spring-boot-starter</artifactId>
<version>${amcc.starter.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>forgejo</id>
<url>https://forgejo.bingjun360.com/api/packages/SouTan/maven</url>
</repository>
</repositories>
业务模块引入(不要再引旧的 amcc-agent-chat-client):
<dependency>
<groupId>com.soutan</groupId>
<artifactId>amcc-agent-chat-spring-boot-starter</artifactId>
</dependency>
本机 ~/.m2/settings.xml 中 server.id=forgejo,并开启 usePreemptive,否则拉包 401。
7.3 应用配置
amc:
enabled: true
base-url: http://amc-host:9960 # 换成真实 AMC
tenant-code: your-tenant-code
connect-timeout-ms: 5000
read-timeout-ms: 30000
long-read-timeout-ms: 120000
token-refresh-skew-seconds: 120
bff:
manage-enabled: true # /business/agentChat/*
dashboard-enabled: true # /dashboard/agentChat/messages
config-enabled: true # /system/agentConfig/*
legacy-ws-handoff: false
# 路径与前端不一致时再改;默认即可对接 @souta/agent-chat-ui
# path-prefix: /business/agentChat
# dashboard-path-prefix: /dashboard
# config-path-prefix: /system/agentConfig
enabled=true 时 base-url、tenant-code、三个超时必须显式填写。
若宿主还留着同名 Controller,对应 *-enabled 先设 false,删掉旧代码后再打开。
7.4 宿主适配代码(建议单独包)
新建例如 com.example.amc.AmcHostConfiguration,在 amc.enabled=true 时注册 SPI。
下面是完整能力模板(管理端 + 大屏 + 配置页 + 统一 JSON/异常);按宿主类型替换注释处。
package com.example.amc;
import com.mvker.amcc.agentchat.AmcAgentChatClientException;
import com.mvker.amcc.spi.AmcBizUserResolver;
import com.mvker.amcc.spi.AmcConfigUser;
import com.mvker.amcc.spi.AmcConfigUserDirectory;
import com.mvker.amcc.spi.AmcDashboardUserResolver;
import com.mvker.amcc.spi.AmcExceptionTranslator;
import com.mvker.amcc.spi.AmcJsonResponseWrapper;
import com.mvker.amcc.spi.AmcPermissionGate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@Configuration
@ConditionalOnProperty(prefix = "amc", name = "enabled", havingValue = "true")
public class AmcHostConfiguration {
/** 管理端:当前登录用户 → AMC bizUserId。LoginUser 等包装类型必须自建,不能依赖默认数字 principal。 */
@Bean
@ConditionalOnMissingBean
public AmcBizUserResolver amcBizUserResolver() {
return () -> {
// return SecurityUtils.getLoginUser(...).getUser().getUserId();
return null;
};
}
/**
* 前端若要求 { code, msg, data } 一类信封,在此包装。
* 默认不包装;SSE / 文件下载不会调用本方法。
*/
@Bean
@ConditionalOnMissingBean
public AmcJsonResponseWrapper amcJsonResponseWrapper() {
return body -> {
// 例:return body == null ? R.ok() : R.ok(body);
return body;
};
}
/** 把 Starter / AMC 错误转成宿主全局异常处理能识别的类型。 */
@Bean
@ConditionalOnMissingBean
public AmcExceptionTranslator amcExceptionTranslator() {
return new AmcExceptionTranslator() {
@Override
public RuntimeException translate(String message) {
return new IllegalStateException(message); // 换成 BusinessException 等
}
@Override
public RuntimeException translate(AmcAgentChatClientException exception) {
return new IllegalStateException(exception.getMessage());
}
};
}
/**
* 大屏:请求体 sceneKey(能碳为 unicode)→ 固定大屏业务用户 id。
* 不开大屏时可删本 Bean,并设 amc.bff.dashboard-enabled=false。
*/
@Bean
@ConditionalOnMissingBean
public AmcDashboardUserResolver amcDashboardUserResolver() {
return sceneKey -> {
// 1) 校验 sceneKey 合法(社区/门店等)
// 2) 返回大屏专用用户主键(AMC 侧按此 bizUserId 换票、绑智能体)
throw new IllegalStateException("请实现大屏用户解析: " + sceneKey);
};
}
/**
* 配置页:按 bizUserId 补 userName / 昵称 / 部门等;add/edit 绑定时必须能提供 userName。
* 不开配置页时可删,并设 amc.bff.config-enabled=false。
*/
@Bean
@ConditionalOnMissingBean
public AmcConfigUserDirectory amcConfigUserDirectory() {
return new AmcConfigUserDirectory() {
@Override
public AmcConfigUser findById(Long userId) {
if (userId == null) {
return null;
}
// SysUser u = userMapper.selectById(userId);
// return AmcConfigUser.builder().userId(...).userName(...).nickName(...).build();
return null;
}
@Override
public Map<Long, AmcConfigUser> findByIds(Collection<Long> userIds) {
if (userIds == null || userIds.isEmpty()) {
return Collections.emptyMap();
}
// 批量查询后 toMap(AmcConfigUser::getUserId, ...)
return Collections.emptyMap();
}
};
}
/**
* 可选。默认全部放行。
* checkConversationAccess:管理端对话;checkConfigAccess:配置 CRUD(action=list/query/add/edit/remove)。
* 抛出的异常不会再经 AmcExceptionTranslator。大屏不走本门闩。
*/
@Bean
@ConditionalOnMissingBean
public AmcPermissionGate amcPermissionGate() {
return new AmcPermissionGate() {
@Override
public void checkConversationAccess() {
// 例:SecurityUtils.checkPermi("business:agentChat:list");
}
@Override
public void checkConfigAccess(String action) {
// 例:按 action 映射 system:agentConfig:*
}
};
}
}
确保该类被宿主组件扫描到(与启动类同根包,或 @Import / @SpringBootApplication(scanBasePackages=…))。
7.5 安全放行(大屏必做)
Starter 用 RouterFunction 注册路由。若宿主依赖「注解扫 Controller 生成匿名名单」(如 @AuthIgnore),扫不到这些路径。
大屏一般无登录 JWT,必须单独 permitAll,例如(Spring Security 5 / Boot 2.7):
@Configuration
@Order(1)
@ConditionalOnProperty(prefix = "amc", name = "enabled", havingValue = "true")
public class AmcDashboardSecurity extends WebSecurityConfigurerAdapter {
private final AmcAgentChatProperties properties;
public AmcDashboardSecurity(AmcAgentChatProperties properties) {
this.properties = properties;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
String prefix = properties.getBff() != null && StringUtils.hasText(properties.getBff().getDashboardPathPrefix())
? properties.getBff().getDashboardPathPrefix().trim()
: "/dashboard";
if (!prefix.startsWith("/")) {
prefix = "/" + prefix;
}
while (prefix.endsWith("/")) {
prefix = prefix.substring(0, prefix.length() - 1);
}
http.requestMatchers()
.antMatchers(prefix + "/agentChat/**", prefix + "/hermes/**")
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.anyRequest().permitAll();
}
}
管理端 /business/agentChat/**、配置 /system/agentConfig/** 继续走宿主登录与菜单权限即可。
7.6 前端对接
| 场景 | 包 / 页面 | 请求目标(默认前缀) | 鉴权 |
|---|---|---|---|
| 管理端对话 | @souta/agent-chat-ui 的 AgentChatApp + transport |
宿主 /business/agentChat/* |
宿主 JWT(如能碳 YzAuthorization) |
| 大屏 | 自建 VoiceChat / 同 UI 包 | POST /dashboard/agentChat/messages |
通常无 JWT;body 带 unicode(或约定的 sceneKey)、text |
| 智能体配置 | 管理端配置页 | /system/agentConfig/* |
宿主 JWT + 菜单权限 |
约定:
- 浏览器只打宿主,不打 AMC,也不带
chatToken。 - JSON 成功体若走了
AmcJsonResponseWrapper,拦截器按宿主约定认code(能碳为200)。 - SSE、附件下载按二进制 / event-stream 处理,不要当 JSON 信封解析。
7.7 数据与权限约定
| 概念 | 谁负责 |
|---|---|
bizUserId |
宿主用户主键;AMC 按租户 + 该 id 换 chatToken、查绑定 |
| 大屏用户 | 建议固定系统用户(如 user_name=dashboard),由 AmcDashboardUserResolver 返回其 id;智能体绑在该用户上 |
| 配置页展示字段 | AmcConfigUserDirectory 从本地用户表补齐;userName 写入 AMC 绑定 |
| 菜单权限 | 默认不在 Starter 内校验;需要时实现 AmcPermissionGate |
7.8 联调验收清单
- 依赖:Reload Maven,启动日志无
amc.*缺配置报错。 - 管理端:登录后
GET /business/agentChat/context返回智能体列表;能建会话、SSE 回消息、附件下载(含路径含+等字符)。 - 大屏:无登录调用
POST /dashboard/agentChat/messages,带合法 sceneKey,SSE 有回复;非法 sceneKey 被宿主校验拒绝。 - 配置:
POST /system/agentConfig/list有分页;add/edit 后管理端 context 能看到新绑定(必要时重新打开页以触发换票)。 - 负例:未登录打管理端应 401/业务未登录;关闭某
bff.*-enabled后对应路径 404。 - 不要在浏览器 Network 里看到
X-Agent-Chat-Token或 AMC 域名(应只出现在宿主→AMC)。
7.9 常见坑
| 现象 | 处理 |
|---|---|
| 拉包 401 | settings.xml 的 forgejo + usePreemptive |
| 启动失败缺配置 | enabled=true 时补齐 base-url / tenant-code / 超时 |
| 路径 404 或双注册 | 删旧 Controller,或关掉对应 amc.bff.*-enabled |
| 前端一直无数据 / code 不对 | 实现 AmcJsonResponseWrapper |
| 大屏 401 | 按 7.5 对 RouterFunction 路径 permitAll |
| 绑了智能体 context 仍空 | 增绑后需重新换票;Starter 在 contextAgents 场景会强制刷新 |
| 配置 add 缺 userName | AmcConfigUserDirectory.findById 必须填 userName |
裁剪能力时:只用管理端 → 可省 Dashboard / Config SPI,并设 dashboard-enabled、config-enabled 为 false。完整三端对接以本节 7.1–7.8 为准;对照实现见第 6 节能碳。
8. 与 AMC / 前端的关系
浏览器 (@souta/agent-chat-ui)
│ 宿主 JWT
▼
宿主应用 + 本 Starter(换票、缓存 chatToken、BFF HTTP)
│ X-Agent-Chat-Token
▼
AMC agent_manage_center_api (/open/agentChat、/open/agentConfig)
│
▼
Hermes Dashboard
- 本仓库:宿主侧依赖(源码 + Maven 包)。
agent_manage_center_api:AMC 服务端;README 里有对接摘要,完整用法以本文为准。- 前端包
@souta/agent-chat-ui:npm 作用域名,与 Forgejo 组织名 SouTan、Maven groupId com.soutan 不是同一概念。
9. 发布新版本
mvn -q clean package source:jar -DskipTests
mvn deploy:deploy-file -DgroupId=com.soutan -DartifactId=amcc-agent-chat-spring-boot-starter -Dversion=x.y.z -Dpackaging=jar -Dfile=target/amcc-agent-chat-spring-boot-starter-x.y.z.jar -Dsources=target/amcc-agent-chat-spring-boot-starter-x.y.z-sources.jar -DgeneratePom=true -DrepositoryId=forgejo -Durl=https://forgejo.bingjun360.com/api/packages/SouTan/maven
同一版本不能重复发;覆盖前先在包页删除旧版本。发版后更新 version.md,并 bump 宿主的 amcc.starter.version。