mirror of
https://github.com/RuoJi6/ARTEX.git
synced 2026-10-28 01:03:50 +08:00
feat: 独立对话(ChatAgent)也支持文件上传(方式1:落盘 + Read/Bash 读取)
补齐上次只做了任务主 Agent 的遗留:独立对话面此前只共用了 transcript 渲染,
后端注入 + Composer 上传缺失,现补上。
- 后端(pgSendConversationMessage):收 attachments;用 userActivityWithAttachments
存 {text,attachments} JSON 供卡片渲染(无附件仍存全文 Detail 供懒加载);用
composeAgentMessage 把【绝对路径】清单拼进发给 ChatAgent 的消息,baseDir=
<workDir>/sessions/conv-<id>/,与 chatUpload 落盘、chat.go 的 sessionWorkDir 对齐;
纯附件无文本也可发,首条会话名兜底"附件消息"。
- 前端(chat/page.tsx):Composer 加回形针上传按钮 + 附件 chip 预览(可移除);
ChatView 上传到 scope=session&id=conv-<id> 并带附件发送;DraftChat 草稿态没有
会话 id,点回形针先懒创建会话再上传,交接文本+附件给 ChatView 发送。
- api.sendConversationMessage 增加 attachments 参数。
This commit is contained in:
1 parent
071414063e
commit
683f5ee684
3 files changed
+162
-17
No files matched your search
+26
-5
@@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -254,13 +255,16 @@ func (s *Server) pgSendConversationMessage(w http.ResponseWriter, r *http.Reques
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req struct{ Message string }
|
||||
var req struct {
|
||||
Message string `json:"message"`
|
||||
Attachments []chatAttachment `json:"attachments,omitempty"` // 方式1 上传的文件(路径相对会话工作目录)
|
||||
}
|
||||
if err := decode(r, &req); err != nil {
|
||||
writeErr(w, 400, err.Error())
|
||||
return
|
||||
}
|
||||
msg := strings.TrimSpace(req.Message)
|
||||
if msg == "" {
|
||||
if msg == "" && len(req.Attachments) == 0 {
|
||||
writeErr(w, 400, "消息不能为空")
|
||||
return
|
||||
}
|
||||
@@ -283,15 +287,32 @@ func (s *Server) pgSendConversationMessage(w http.ResponseWriter, r *http.Reques
|
||||
// persist + float the human turn; auto-title the thread from the first message.
|
||||
// Worker is the agent key (not "user") so the transcript stays a single lane
|
||||
// (no worker chips) — the kind='user' already right-aligns it as a human bubble.
|
||||
if _, err := pg.AppendConvActivity(c.ID, db.Activity{Worker: c.AgentKey, Kind: "user", Summary: firstLine(msg, 200), Detail: msg}); err != nil {
|
||||
// With attachments, Detail carries {text, attachments} JSON so the transcript
|
||||
// renders attachment cards; without, Detail is the full text (Summary is truncated,
|
||||
// so the transcript lazy-loads Detail to show the message untruncated).
|
||||
ua := userActivityWithAttachments(c.AgentKey, msg, req.Attachments)
|
||||
ua.Summary = firstLine(msg, 200)
|
||||
if ua.Detail == "" {
|
||||
ua.Detail = msg
|
||||
}
|
||||
if _, err := pg.AppendConvActivity(c.ID, ua); err != nil {
|
||||
log.Printf("[conv %d] append user msg failed: %v", c.ID, err)
|
||||
}
|
||||
if c.Title == "" || c.Title == "新对话" {
|
||||
_ = pg.RenameConversation(c.ID, firstLine(msg, 40))
|
||||
title := firstLine(msg, 40)
|
||||
if title == "" {
|
||||
title = "附件消息"
|
||||
}
|
||||
_ = pg.RenameConversation(c.ID, title)
|
||||
}
|
||||
_ = pg.TouchConversation(c.ID)
|
||||
|
||||
s.runConversation(c, msg, busyKey)
|
||||
// Append the uploaded files' ABSOLUTE paths so the ChatAgent opens them with its
|
||||
// Read/Bash tools. baseDir = the agent's per-session CWD (<workDir>/sessions/
|
||||
// conv-<id>/), matching chatUpload's landing dir and agent/chat.go's sessionWorkDir
|
||||
// — busyKey == convBusyKey(c.ID) == "conv-<id>" == that session id.
|
||||
baseDir := filepath.Join(s.m.dir, "sessions", busyKey)
|
||||
s.runConversation(c, composeAgentMessage(msg, req.Attachments, baseDir), busyKey)
|
||||
writeJSON(w, 202, map[string]any{"status": "accepted"})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user