summaryrefslogtreecommitdiff
path: root/agent/tools
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-03 09:11:36 -0600
committert <t@tjp.lol>2026-06-03 12:34:13 -0600
commitac5c4898dfa0a9e57424336774893dfc72b132e9 (patch)
tree03eb8e32a001845dbaec163dfd4905ffc23d9fa6 /agent/tools
parent2416a308c0e467f8dbdbe09942aa903bca751c0e (diff)
image uploads
Diffstat (limited to 'agent/tools')
-rw-r--r--agent/tools/read.lua54
1 files changed, 54 insertions, 0 deletions
diff --git a/agent/tools/read.lua b/agent/tools/read.lua
index f232890..ab92c05 100644
--- a/agent/tools/read.lua
+++ b/agent/tools/read.lua
@@ -15,6 +15,30 @@
local uv = require("luv")
+-- Minimal magic-byte sniff: binary attachment (image/PDF) vs. text.
+-- We only decide *whether* the bytes are an attachment; libpanto does the
+-- precise type detection, resizing, and encoding from the raw bytes. Keep
+-- this in lockstep with `libpanto/src/image.zig`'s `detectCodec`.
+local function is_attachment(head)
+ local b = { head:byte(1, 12) }
+ -- PNG: 89 50 4E 47 0D 0A 1A 0A
+ if b[1] == 0x89 and b[2] == 0x50 and b[3] == 0x4E and b[4] == 0x47
+ and b[5] == 0x0D and b[6] == 0x0A and b[7] == 0x1A and b[8] == 0x0A then
+ return true
+ end
+ -- JPEG: FF D8 FF
+ if b[1] == 0xFF and b[2] == 0xD8 and b[3] == 0xFF then return true end
+ -- GIF: "GIF87a" / "GIF89a"
+ if head:sub(1, 6) == "GIF87a" or head:sub(1, 6) == "GIF89a" then return true end
+ -- BMP: "BM"
+ if b[1] == 0x42 and b[2] == 0x4D then return true end
+ -- WEBP: "RIFF"????"WEBP"
+ if head:sub(1, 4) == "RIFF" and head:sub(9, 12) == "WEBP" then return true end
+ -- PDF: "%PDF-"
+ if head:sub(1, 5) == "%PDF-" then return true end
+ return false
+end
+
local MAX_BYTES = 50 * 1024 -- 50 KB
local MAX_LINES = 2000
local READ_CHUNK_SIZE = MAX_BYTES
@@ -229,6 +253,36 @@ return {
return "Error: " .. (open_err or ("could not open " .. path))
end
+ -- Binary attachment path. We do the *minimal* magic-byte sniff
+ -- here — only enough to decide "binary attachment vs. text". If
+ -- it's an attachment, we return the raw file bytes; libpanto does
+ -- the real work (precise type detection, resizing, encoding).
+ do
+ local herr, header = fs_read(fd, 16, 0)
+ if not herr and header and #header > 0 and is_attachment(header) then
+ local whole, rerr = (function()
+ local chunks = {}
+ local off = 0
+ while true do
+ local e, d = fs_read(fd, READ_CHUNK_SIZE, off)
+ if e then return nil, e end
+ if d == nil or #d == 0 then break end
+ chunks[#chunks + 1] = d
+ off = off + #d
+ end
+ return table.concat(chunks)
+ end)()
+ fs_close(fd)
+ if not whole then
+ return "Error: read failed: " .. tostring(rerr)
+ end
+ return {
+ text = string.format("[read %s as binary attachment]", path),
+ attachments = { { data = whole } },
+ }
+ end
+ end
+
local parts = {}
local emitted_lines = 0
local emitted_bytes = 0