Class: Rubino::Tools::AttachFileTool
- Defined in:
- lib/rubino/tools/attach_file_tool.rb
Overview
Hands a previously-written file to the surrounding UI as a downloadable artifact. The tool itself does not move bytes — it validates the path against the workspace and the file’s existence, then surfaces a structured artifact payload that the agent loop turns into an ARTIFACT_CREATED event. Downstream consumers (the web UI’s run job, the CLI) fetch the file separately via GET /v1/files.
Why a dedicated tool rather than inferring artifacts from write/edit tool calls: the model writes lots of intermediate files (helper scripts, scratch JSON, downloaded fixtures) that should NOT show up as user-facing downloads. An explicit attach_file call makes that decision intentional and reviewable.
Constant Summary collapse
- DEFAULT_CONTENT_TYPE =
"application/octet-stream"- CONTENT_TYPES =
Minimal extension → MIME map. Anything not listed falls back to application/octet-stream; the browser will then decide based on filename. Add entries here only when a real run needs a specific type signalled (e.g. inline PDF preview).
{ "pdf" => "application/pdf", "csv" => "text/csv", "txt" => "text/plain", "md" => "text/markdown", "json" => "application/json", "html" => "text/html", "htm" => "text/html", "xml" => "application/xml", "png" => "image/png", "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "gif" => "image/gif", "svg" => "image/svg+xml", "zip" => "application/zip", "tar" => "application/x-tar", "gz" => "application/gzip", "docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", "xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }.freeze
Instance Attribute Summary
Attributes inherited from Base
#cancel_token, #read_tracker, #stream_chunk
Instance Method Summary collapse
- #call(arguments) ⇒ Object
- #description ⇒ Object
- #input_schema ⇒ Object
- #name ⇒ Object
- #risk_level ⇒ Object
Methods inherited from Base
#cancellation_requested?, #config_key, #emit_chunk, #risky?, #to_tool_definition, workspace_root, workspace_roots
Instance Method Details
#call(arguments) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubino/tools/attach_file_tool.rb', line 81 def call(arguments) file_path = (arguments["file_path"] || arguments[:file_path]).to_s return error("file_path is required") if file_path.empty? = File.(file_path) return error("File not found: #{file_path}") unless File.exist?() return error("Not a regular file: #{file_path}") unless File.file?() return error("Path escapes the workspace: #{file_path}") unless within_workspace?() display = (arguments["filename"] || arguments[:filename]).to_s display = File.basename() if display.empty? size = File.size() artifact = { path: , filename: display, content_type: content_type_for(), byte_size: size } { output: "Attached #{display} (#{size} bytes) as a downloadable artifact.", metrics: "#{size} bytes", artifact: artifact } end |
#description ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/rubino/tools/attach_file_tool.rb', line 52 def description "Attach a previously-written file to the current turn as a downloadable artifact " \ "for the user. Call this AFTER you have already created the file with write/edit/shell. " \ "Pass the absolute or workspace-relative path. The tool does not copy or move the file — " \ "it just registers it as a deliverable. Use for final user-facing outputs " \ "(PDF, CSV, ZIP, reports) and not for intermediate helper scripts." end |
#input_schema ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/rubino/tools/attach_file_tool.rb', line 60 def input_schema { type: "object", properties: { file_path: { type: "string", description: "Path to the file to attach. Must exist and live inside the workspace." }, filename: { type: "string", description: "Optional display name; defaults to the basename of file_path." } }, required: %w[file_path] } end |
#name ⇒ Object
48 49 50 |
# File 'lib/rubino/tools/attach_file_tool.rb', line 48 def name "attach_file" end |
#risk_level ⇒ Object
77 78 79 |
# File 'lib/rubino/tools/attach_file_tool.rb', line 77 def risk_level :low end |