feat: 会话附件删除接口与图片输入模型兼容投影#712
Conversation
- 从 RuntimePort 拆出 SessionAssetPort 独立端口,新增 DeleteSessionAsset 方法 - Gateway 注册 DELETE /api/session-assets 端点,多工作区路由和安全 ACL 适配 - CLI Bridge 实现 DeleteSessionAsset,修复 Save 缺少会话存在性校验、Open 缺少 os.ErrNotExist 映射 - Runtime 图片投影:不支持图片的模型对历史图片替换为占位文本,不修改持久化消息 - Runtime 拒绝不支持的当前图片输入,避免上游 400 - Web ChatInput 取消上传时调用 deleteSessionAsset 释放服务端资源 - Web useSessionStore 新增 _pendingNewSession 防止新会话期间自动切换
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
There was a problem hiding this comment.
发现 2 个需要处理的问题,已以内联评论标出。
验证:尝试运行 go test ./internal/gateway ./internal/context 和 go test ./internal/runtime,但当前环境没有 go 命令,无法执行。
未能定位到 diff 行的发现
internal/context/builder.go:22:NewConfiguredBuilder的 source 仍是可选注入,但这里不再跳过nil。一旦调用方传入nil(旧测试也覆盖过这个兼容场景),collectPromptSections会在调用source.Sections(...)时直接 panic。请恢复 nil 过滤,或在收集 section 前做保护,避免可选 source 缺失时把 runtime 拉崩。
| } | ||
| if !s.isHTTPControlPlaneMethodAllowed(sessionAssetReadMethod) { | ||
| s.writeHTTPAccessDenied(writer, sessionAssetReadMethod) | ||
| if !s.isHTTPControlPlaneMethodAllowed(sessionAssetDeleteMethod) { |
There was a problem hiding this comment.
这里把 GET 附件读取的 ACL 检查成了 sessionAssetDeleteMethod,而下面的 DELETE 处理器又检查 sessionAssetReadMethod。这样一来,只允许读取的配置会错误拒绝 GET、却可能放行 DELETE,破坏新删除端点的最小权限边界。建议 GET 使用 sessionAssetReadMethod,DELETE 使用 sessionAssetDeleteMethod,并补一个只允许其中一个方法的测试。
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
- 修复 handleSessionAssetRead 中 ACL 检查使用了 sessionAssetDeleteMethod 的 bug - 修复 handleSessionAssetDelete 中 ACL 检查使用了 sessionAssetReadMethod 的 bug - 为 newStablePromptSources 添加 nil source 过滤,防止 collectPromptSections panic - 补充 ACL 独立生效测试(read-only 和 delete-only ACL 场景) - 补充 nil source 和 mixed nil/valid source 测试 - 补充 multi_workspace Delete 不支持 SessionAssetPort 的错误返回测试 - 补充图片投影空消息和混合消息的边界测试
Review 回复ACL 方法名互换已修复(commit ca378b0)。 ACL 方法名确实写反了:handleSessionAssetRead(GET)错误检查了 sessionAssetDeleteMethod,handleSessionAssetDelete(DELETE)错误检查了 sessionAssetReadMethod。 修复内容:
NewConfiguredBuilder nil source 保护已修复(commit ca378b0)。 在 newStablePromptSources 的循环中添加了 nil source 过滤,防止 collectPromptSections 调用 source.Sections() 时 panic。补充了 nil source 和 mixed nil/valid source 的测试。 |
…setPort 方法被提升的测试缺陷 将 recordingPortWithoutSessionAsset 的嵌入类型从 *recordingPort 改为 RuntimePort 接口, 避免 Go 方法提升机制将 SessionAssetPort 的方法也一并提升,导致类型断言永远成功。
TestNetworkServerSessionAssetACLIndependent 直接用 sessionAssetReadMethod/ sessionAssetDeleteMethod(混合大小写)作为 allow map 键,但 IsAllowed 查找时 用 strings.ToLower 归一化,导致键不匹配返回 403。改用 normalizedMethodSet() 构造内层 map,与生产代码 NewStrictControlPlaneACL 保持一致。
|
本 PR 存在大量纯空格/格式变更的脏提交,已由干净替代 PR #713 取代。 |
| const res = await fetch( | ||
| `${this.baseURL}/api/session-assets/${encodeURIComponent(sessionId)}/${encodeURIComponent(assetId)}`, | ||
| { | ||
| method: 'DELETE', |
There was a problem hiding this comment.
这里新增了带 Authorization / X-NeoCode-Workspace-Hash 的浏览器 DELETE 请求,但 NetworkServer.withCORS 仍只返回 Access-Control-Allow-Methods: GET, POST, OPTIONS。当前端和网关跨源(例如 Web dev server 访问本地 gateway)时,浏览器会先发 preflight,并因为允许方法里没有 DELETE 而拦截,清理请求到不了新端点。建议把 DELETE 加到 CORS allow methods,并补一个 OPTIONS preflight 覆盖。
变更内容
会话附件删除(Session Asset Delete)
RuntimePort拆出SessionAssetPort独立接口,新增DeleteSessionAsset方法DELETE /api/session-assets/{sessionID}/{assetID}端点,多工作区路由和安全 ACL 适配DeleteSessionAsset,修复Save缺少会话存在性校验、Open缺少os.ErrNotExist映射ChatInput取消上传时调用deleteSessionAsset释放服务端资源图片输入模型兼容投影(Image Projection)
rejectUnsupportedCurrentImageInput:当前模型不支持图片但用户上传了图片则直接拒绝projectImagesForModelRequest:对历史消息中的图片做投影降级,不支持图片的模型将历史图片替换为占位文本,不修改持久化消息新会话防自动切换
useSessionStore新增_pendingNewSession标记,防止创建新会话期间被fetchSessions回调自动切换破坏性变更
RuntimePort移除了SaveSessionAsset/OpenSessionAsset,拆入独立的SessionAssetPort接口。所有RuntimePort实现方需适配。行为变更
SaveSessionAsset新增会话存在性校验:不存在的 sessionID 之前静默创建文件,现在返回ErrRuntimeResourceNotFound。验证
gofmt -w ./cmd ./internal通过go build ./...通过go test ./internal/gateway/... ./internal/runtime/... ./internal/cli/...通过Closes #711