v0.2.7
Pre-releasev0.2.7
本 Release 作为 Development Techology Preview Level 1 的一部分发布。
本版本为 v0.2.6 的紧急修复。
安装
# Linux
curl -sSL https://alk.cxykevin.top/i.sh | bash# Windows
irm https://alk.cxykevin.top/i.ps1 | iexv0.2.7 紧急修复
紧急修复了 Filesystem Over ACP 的 Windows 的跨平台编译问题。
go fix && go fmt 了代码
v0.2.6 更新日志
概述
本次变更合并了安全审计报告的 bug 修复(P0/P1/P2)、内容大小限制的新功能以及 LLM 请求重试机制。涉及 18 个文件,共约 ~345 行插入、~87 行删除。
1. 安全修复
P0 — AI 模型可触发恐慌(DoS/崩溃)
| 文件 | 变更 | 严重性 |
|---|---|---|
provider/parser/parser.go |
JSON 流式解析器中添加 4 处 nil 判空:toolNameOrigin、toolCallIDOrigin、toolParametersOrigin 及参数 value 可能为 null。同时处理 jsonParser.AddToken() 的 error 返回值 |
模型发送 {"name":null} 等畸形 JSON 即可触发 nil 指针 panic |
tools/tools/edit/edit.go |
@insert:{lineNum} 增加 lineNum < 1 下界校验,防止 AI 传入 0 或负数时 panic |
@insert:0 即可崩溃 |
P0 — Tree 工具路径遍历 / 敏感文件泄露
| 文件 | 变更 | 严重性 |
|---|---|---|
tools/tools/tree/files.go |
敏感文件防护:扩展 dirBlacklistsOrigin 列表(.env、.ssh、.aws/.gcp/.azure/.kube/.docker 配置、证书密钥文件);新增 sensitiveFilePatterns(20 条正则匹配 .pem/.key/.cert/credentials 等);新增 isSensitivePath() 函数在 Delete/Move 前预检拒绝 |
阻止 AI 删除/移动 SSH 密钥、云凭证、TLS 证书、K8s 配置等 |
tools/tools/tree/files.go |
修复 7 处 filepath.Join 参数顺序错误(d.Target, path → path, d.Target),此前导致 diff 操作的目标路径错误 |
Move/Copy 时路径拼接结果不符合预期 |
P1 — Linux 沙箱逃逸
| 文件 | 变更 | 严重性 |
|---|---|---|
terminal/sandbox/sandbox_linux.go |
generateWritableMounts() 中每个可写目录 bind mount 后,额外检查 .alkaid0 子目录并 remount ro,bind 保护 |
可写目录中的聊天记录/配置可被沙箱内进程篡改 |
P2 — 并发 map 无锁访问(fatal error: concurrent map writes)
| 文件 | 变更 | 严重性 |
|---|---|---|
server/actions/session.go |
为 bindedSessionOnConn map 新增 bindedSessionOnConnMu 互斥锁 |
多连接并发绑定/解绑 session 时 fatal |
server/actions/main.go |
Close() 中 bindedSessionOnConn 和 clientConnCaps 加锁访问 |
服务关闭时并发写 map |
server/actions/prompt.go |
SessionCancel() 读 sessions map 补加 sessLock |
取消 prompt 时与新建 session 并发读写冲突 |
server/actions/update.go |
updateCfgsToConns() 重写,分离 sessLock(读 sessions)与 sessionConnLock(读 sessionConnMap),释放锁后再广播 |
配置热更新时多锁嵌套 + 写 map |
tools/tools.go |
ExecOneToolGetPrompts() 用 maps.Copy 深拷贝 t.Parameters 后再合并到全局参数 |
多 session 并发执行工具时写同一个 map |
server/client/jsonrpc/connect/stdio.go |
新增 writeMu sync.Mutex 保护 fmt.Println 输出 |
多 goroutine 并发写 stdout 时输出交错 |
P2 — 正确性 Bug
| 文件 | 变更 | 严重性 |
|---|---|---|
server/actions/session.go |
loadSession() 移除 sess.ReferCount = 1(改用 obj.referCnt 独家计数);closeSession() 将 obj.session.ReferCount-- 改为 obj.referCnt-- |
双计数器不一致导致 session 提前释放或泄漏 |
ui/loop/loop.go |
call() 函数中 recvSyncQueue send/recv 改为 select { case ...: case <-p.done: },防止 Cancel 后永久阻塞 |
Cancel 后的响应卡死主循环 |
tools/tools/edit/edit.go |
非 g 模式正则替换从 ReplaceAllString 改为 FindStringIndex + 手动替换;@ln:{from}-{to} 增加 from > to 校验 |
非全局替换实际执行了全替换;范围倒置未拒绝 |
prompts/prompts/delta_wrap.md |
模板条件 eq → ne,修复 <think>/<tools> 包裹逻辑 |
本应在有内容时才包裹标签,实际在空内容时才包裹(导致工具调用丢失) |
server/actions/fs.go |
fs 超时从 time.After 改为 context.WithTimeout + ctx.Done() |
time.After 无 cancel 机制,goroutine 泄漏 |
helper/helper.go |
stdin 首字节判换行改为 bytes.TrimLeft 完整清除 |
仅检查首字节导致换行为首的读块被整块丢弃 |
2. 新功能:FsRead/FsWrite 改进
| 文件 | 变更 |
|---|---|
server/actions/fs.go |
1MB 内容限制:FsWrite 中解码 content 后检查 len(content) > maxFileContentSize,超出返回明确错误 |
server/actions/fs.go |
静默 EOF 截断:FsRead 新增 f.Stat() 获取文件大小;offset 超出文件大小时返回空;offset+length 超出时自动截断到文件结尾 |
docs/acp/fs.md |
新增 Content Size Limit 小节;FsRead 补充静默截断行为;FsWrite 补充 1MB 上限说明 |
3. 新功能:Loop 请求重试机制
| 文件 | 变更 |
|---|---|
ui/loop/loop.go |
重试常量配置:新增 maxRetries = 3 和 baseBackoff = 1s 作为包级 const |
ui/loop/loop.go |
指数退避重试:将 SendRequest 调用包装为 sendRequestWithRetry 闭包;失败时依次等待 1s→2s→4s 后重试,最多 3 次 |
ui/loop/loop.go |
安全重试边界:仅在流式响应尚未开始(!responseStarted)时重试;已输出内容后失败不重试,避免客户端收到重复/混乱的流数据 |
ui/loop/loop.go |
取消感知:退避期间同时监听 p.ctx 和 responseCtx,用户取消时立即跳过后续重试;context.Canceled/DeadlineExceeded 错误不触发重试 |
server/client/jsonrpc/server.go |
Set() 泛型函数中 u.Apply[T] 拆分调用并处理 error 返回值,带参错误时返回 invalid params 而非静默丢弃 |
本次更新由
Claude Opus 4.8扫描,并由Deepseek V4 Flash完成全程编写。使用 Claude Code 进行。期待 alkaid0 能早日完成自举!
从 v0.1.0 的迁移指南
参考下面的配置补齐 Server 字段即可。
程序不再内置客户端,需要自行安装任意 ACP 客户端(如 multicoder,ACP UI 等)使用!配置请参考下方 客户端 内说明配置。
在启动客户端前,你需要预先启动服务器(不带任何参数启动)!
配置
路径 ~/.config/alkaid0/config.json
"$schema": "https://raw.githubusercontent.com/cxykevin/alkaid0/refs/heads/main/docs/schemas/config.json",
"Version": 1,
"Model": {
"ProviderURL": "https://openrouter.com/api/v1(这里暂时没有用)",
"ProviderKey": "sk-or-xxx(这里暂时没有用)",
"DefaultModelID": 1,
"Models": {
"1": {
"ModelName": "模型名",
"ModelID": "模型ID",
"ProviderURL": "https://模型供应商/v1",
"ProviderKey": "sk-模型密钥",
"EnableThinking": true,
"CompressSize": 128000,
"ProviderSpecificConfig": {
"EnableDeepseekThinking": false,
"EnableReasoningEffort": true,
"EnableTopP": false,
"EnableTopK": false,
"EnableTemperature": false
}
}
}
},
"Agent": {
"Agents": {
"frontend": {
"AgentName": "前端工程",
"AgentDescription": "前端工程Agent",
"AgentPrompt": "你是一个前端工程师,请根据用户的需求,提供前端工程解决方案。",
"AgentModel": 1,
"AutoApprove": "",
"AutoReject": ""
}
},
"GlobalPrompt": "始终使用中文回答",
"SummaryModel": 1,
"MaxCallCount": 50,
"AutoApprove": "",
"AutoReject": ""
},
"ThemeID": 0,
"Server": {
"Key": "<你的 webcsocket key>",
"Path": "/acp",
"Host": "127.0.0.1",
"Port": 7433,
"DisableStdioServer": false
}
}
客户端
配置完上述 json 后直接启动主程序,服务端会在 ws://<host>:<port>/<path> 开启一个 websocket 服务。此时服务端同时会启动一个标准的 stdio 服务器便于调试。
服务端使用 Query 参照认证。在 Query 参数中添加 key=<key> 即可。如果没有 Query 参数选项,则可以在 Path 中设置 /acp?k=<key>。
支持 Websocket 桥接的客户端可以直接链接。只支持 stdio 的客户端可以使用提供的 helper 链接。
目前 helper 只支持
ws,不支持wss。
可以通过 ./可执行文件 acp 启动服务端内置 helper。如果你需要轻量化部署并链接到远程,则可以使用单独的 helper 可执行文件并不带任何参数启动。如果你使用 go install 安装,则服务器绑定到了 alkaid0,单独的 helper 可以使用 alk 命令。
helper 会自动读取本机的 ~/.config/alkaid0/config.json 并自动链接,一般本机无需再次手动配置 key。
如果你需要链接到远程或自动链接无效,可以使用以下参数:
-config配置文件路径-host服务器的 host-port服务器的 port-path服务器的 path-key服务器配置的 websocket key
如果你无法链接请检查是否在服务端和客户端都设置了
Key。服务端不允许空key启动(stdio 服务器正常工作)。如果内置的 stdio 导致服务器自动退出或其它问题,则可在
config.json中设置DisableStdioServer为true以禁用。
不要在用户目录或者根目录运行 Alkaid!
平台支持
Linux(amd64,arm64) (binary,deb,rpm,apk,archlinux)Windows(amd64) (binary,msix)MacOS(实验性amd64,实验性arm64)(沙盒除外) (binary)
本 Release 仅供测试,不代表任何效果!不要在生产环境使用!
--- alkaid0 启航 ---
日志位于配置文件同目录 log.log,经过简单脱敏,会包含您的聊天记录!提交前请手动审计!