feat: 新建任务改为右侧抽屉(45%宽)+ 支持上传文件写入描述

- 表单从居中弹窗(Dialog)换成右侧 Sheet,宽 45vw(窄屏全宽),整屏高度可
  滚动,长表单不再受弹窗高度限制;头/脚固定、中间字段区独立滚动。
- 高级参数(超时/心跳/首个意图)收进「高级设置」Collapsible 折叠,常用路径
  只露 描述/目标/LLM;描述与目标 textarea 加高(min-h-32)。
- 描述下方加「上传文件」组件(可多选):建任务前任务无 ID,新增上传
  scope=staging,文件落到 <workDir>/drafts/<draftId>/uploads/,后端返回绝对
  路径(chatAttachment.Abs),前端把绝对路径以提示词形式追加到描述末尾,供
  worker 用 Read/Bash 打开;再次上传追加到同一标记块。draftId 用
  crypto.randomUUID(非安全上下文降级),创建成功后清空。
This commit is contained in:
Autumn-27 committed 2026-08-18 09:01:56 -04:00
1 parent 683f5ee684
commit 6a5e7c1b84
4 files changed
+230 -109

No files matched your search

+12 -4
View File
@@ -26,17 +26,23 @@ type chatAttachment struct {
Name string `json:"name"`
Path string `json:"path"`
Size int64 `json:"size"`
// Abs 是落盘的绝对路径(m.dir 已是绝对)。建任务前暂存(scope=staging)时前端要用它把
// 提示词写进描述;task/session 走 composeAgentMessage 在后端拼路径,不依赖此字段。
Abs string `json:"abs,omitempty"`
}
// chatUpload implements method-1 file support: it saves one or more files into a chat's
// working dir under uploads/, so the agent opens them with its existing Read/Bash tools
// and the sent message carries their paths. No LLM-layer change, no multimodal.
//
// POST /api/chat/upload?scope=task|session&id=<id>, multipart field "file" (repeatable).
// Returns {attachments:[{name,path,size}]}. Target dir mirrors the agent CWD layout:
// POST /api/chat/upload?scope=task|session|staging&id=<id>, multipart field "file"
// (repeatable). Returns {attachments:[{name,path,size,abs}]}. Target dir mirrors the
// agent CWD layout:
//
// scope=task → <workDir>/tasks/<id>/uploads/
// scope=session → <workDir>/sessions/<id>/uploads/
// scope=staging → <workDir>/drafts/<id>/uploads/ (建任务前暂存:任务尚无 ID,
// 文件先落这里,前端按返回的 abs 绝对路径写进任务描述)
func (s *Server) chatUpload(w http.ResponseWriter, r *http.Request) {
var sub string
switch r.URL.Query().Get("scope") {
@@ -44,8 +50,10 @@ func (s *Server) chatUpload(w http.ResponseWriter, r *http.Request) {
sub = "tasks"
case "session":
sub = "sessions"
case "staging":
sub = "drafts"
default:
writeErr(w, 400, "scope 必须是 task 或 session")
writeErr(w, 400, "scope 必须是 task / session / staging")
return
}
id := r.URL.Query().Get("id")
@@ -80,7 +88,7 @@ func (s *Server) chatUpload(w http.ResponseWriter, r *http.Request) {
return
}
base := filepath.Base(dest)
out = append(out, chatAttachment{Name: base, Path: "uploads/" + base, Size: hdr.Size})
out = append(out, chatAttachment{Name: base, Path: "uploads/" + base, Size: hdr.Size, Abs: dest})
}
writeJSON(w, 200, map[string]any{"attachments": out})
}