diff --git a/wwwroot/api/agent_chat.dspy b/wwwroot/api/agent_chat.dspy index 03f4d3d..8b1bd2d 100644 --- a/wwwroot/api/agent_chat.dspy +++ b/wwwroot/api/agent_chat.dspy @@ -45,14 +45,18 @@ if action == 'send_message': prompt = (params_kw or {}).get('prompt', '') or msg prompt = prompt.strip() - # 处理用户上传的文件(multipart file 字段 → web_path),提取文本作为中性上下文注入 prompt + # 处理用户上传的文件(multipart file 字段 → web_path): + # 1. 抽取文本作为中性上下文注入 prompt + # 2. 收集 (绝对路径, 文件名),稍后复制进项目根目录,让会话 agent 的 read_file 能找到 file_ctx = '' + _uploads = [] # [(src_abs, filename)] _fval = (params_kw or {}).get('file') _fpaths = _fval if isinstance(_fval, list) else ([_fval] if _fval else []) for _fp in _fpaths: try: _abs = FileStorage().realPath(_fp) _name = os.path.basename(_abs) + _uploads.append((_abs, _name)) _txt = _extract_text(_abs, _name) if _txt: file_ctx += f"【文件 {_name} 内容】\n{_txt}\n\n" @@ -60,8 +64,6 @@ if action == 'send_message': file_ctx += f"【文件 {_name}】二进制文件,无法直接读取文本。\n\n" except Exception: pass - if file_ctx: - prompt = "用户本次上传了以下文件:\n\n" + file_ctx + "\n用户指令:" + prompt # ── 意图识别:停止类指令 ── stop_keywords = ['停止', '取消', '停下', '终止', '停', 'stop', 'cancel', 'abort'] @@ -79,6 +81,25 @@ if action == 'send_message': # ── 产线默认能力(入口指定,如 bidding_general):无当前项目时装载该产线能力 ── pipeline_id = (params_kw or {}).get('pipeline_id', '') or '' + # ── 上传文件落盘到项目根目录(会话 agent 的 read_file 以项目目录为根, + # 不复制进去则 agent 永远找不到;无当前项目时仅注入文本)── + _saved_files = [] + if _uploads: + try: + async with DBPools().sqlorContext(dbname) as sor: + _pid = await get_session_project_id(sor, uid, session_id) + _pdir, _ = await get_project_dir_by_id(sor, _pid) + _saved_files = copy_uploads_to_project(_pdir, _uploads) + except Exception: + _saved_files = [] + + if file_ctx or _saved_files: + _loc = '' + if _saved_files: + _loc = "文件已保存到项目根目录(" + _pdir + "),可用 read_file 直接读取:\n" + _loc += "\n".join(" - " + n for n, _ in _saved_files) + "\n\n" + prompt = "用户本次上传了以下文件:\n" + _loc + file_ctx + "\n用户指令:" + prompt + # ── 走 gateway 统一入口(Web AgentIO 通道)── # model_id:前端模型下拉选中的模型 → gateway 校验后持久化到项目(项目模型一经设置 # 即生效,直到用户再次选择),空 = 沿用项目已设模型。