# Copyright 2026 zhaoxi826 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json from kilostar.plugin.tool_plugin.base_tool import BaseToolData from kilostar.utils.ray_hook import ray_actor_hook from typing import List, Literal, Dict class SendFileToolData(BaseToolData): """``send_file`` 工具元数据:把 agent 生成的文件作为附件推送到对话窗口。""" is_system: bool = True action_scope: List[ Literal[ "control_node", "consciousness_node", "regulatory_node", "growth_node", "", ] ] = [] config_args: Dict[str, str] = {} category: str = "system" async def send_file(filename: str, content: str, trace_id: str) -> str: """把 agent 生成的文件作为附件发送给当前对话窗口。 通过 global_workflow_manager 的 pending 队列推送一条带特殊前缀的 JSON 消息, 前端识别后渲染为可下载的文件卡片。 Args: filename: 文件名(含扩展名),如 "report.md" / "main.py" content: 文件内容(UTF-8 文本) trace_id: 当前会话/工作流的 trace_id Returns: 发送结果说明 """ payload = json.dumps( {"type": "file", "filename": filename, "content": content}, ensure_ascii=False, ) actor_list = ray_actor_hook("global_workflow_manager") await actor_list.global_workflow_manager.put_pending.remote( trace_id, f"__FILE__{payload}" ) return f"已发送文件: {filename}"