summaryrefslogtreecommitdiff
path: root/agent/extensions
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-23 09:38:23 -0600
committert <t@tjp.lol>2026-06-23 10:53:26 -0600
commit69a1ee138bb78ad4663fe2d9e58678f7b0d07b74 (patch)
tree453d3ad42a07536220e6ca5d91b439ff57793e32 /agent/extensions
parent538a5d926fa626a00cc3dc12c555f11f82867efd (diff)
ponytail simplifications to panto cli and lua extensiosn
Diffstat (limited to 'agent/extensions')
-rw-r--r--agent/extensions/std_render.lua206
1 files changed, 0 insertions, 206 deletions
diff --git a/agent/extensions/std_render.lua b/agent/extensions/std_render.lua
deleted file mode 100644
index 43a2c86..0000000
--- a/agent/extensions/std_render.lua
+++ /dev/null
@@ -1,206 +0,0 @@
--- Rendering components for the bundled std.* tools.
---
--- The Zig TUI core deliberately renders tools generically. Tool-specific
--- presentation belongs beside the tool implementation and is installed through
--- the extension event system.
-
-local panto = require("panto")
-
-local ok_json, json = pcall(require, "dkjson")
-if not ok_json then
- ok_json, json = pcall(require, "luarocks.vendor.dkjson")
-end
-
-local states_by_index = {}
-local states_by_id = {}
-local index_by_id = {}
-local collapsed_tail_lines = 8
-
-local function decode(s)
- if type(s) ~= "string" or s == "" or not ok_json then return nil end
- local ok, obj = pcall(json.decode, s)
- if ok and type(obj) == "table" then return obj end
- return nil
-end
-
-local function short_name(name)
- if type(name) ~= "string" then return nil end
- return name:match("^std%.(.+)$") or name:match("^std__([%w_%-]+)$") or name
-end
-
-local function is_ours(name)
- local s = short_name(name)
- return s == "read" or s == "write" or s == "shell" or s == "edit"
-end
-
-local function spaces(n) return string.rep(" ", math.max(0, n or 0)) end
-
-local function wrap_text(text, width)
- width = math.max(1, width or 1)
- text = tostring(text or "")
- local out = {}
- for raw in (text .. "\n"):gmatch("(.-)\n") do
- if raw == "" then
- out[#out + 1] = ""
- else
- local line = raw
- while #line > width do
- local cut = width
- local prefix = line:sub(1, width)
- local sp = prefix:match("^.*() %S")
- if sp and sp > 1 then cut = sp - 1 end
- out[#out + 1] = line:sub(1, cut)
- line = line:sub(cut + 1):gsub("^%s+", "")
- end
- out[#out + 1] = line
- end
- end
- if #out == 0 then out[1] = "" end
- return out
-end
-
-local function quote(v)
- if v == nil or v == "" then return nil end
- return tostring(v)
-end
-
-local function derive_header(st)
- local name = short_name(st.name) or st.name or "?"
- local obj = decode(st.input)
- if name == "read" and obj then
- local path = quote(obj.path)
- if path then
- if type(obj.offset) == "number" and type(obj.limit) == "number" then
- return string.format("read %s (lines %d-%d)", path, obj.offset, obj.offset + obj.limit - 1)
- elseif type(obj.offset) == "number" then
- return string.format("read %s (from line %d)", path, obj.offset)
- end
- return "read " .. path
- end
- elseif name == "write" and obj and quote(obj.path) then
- return "write " .. quote(obj.path)
- elseif name == "shell" and obj and quote(obj.command) then
- local tail = ""
- if quote(obj.cwd) then tail = tail .. " cwd=" .. quote(obj.cwd) end
- if type(obj.timeout) == "number" then tail = tail .. string.format(" timeout=%ds", obj.timeout) end
- return "shell $ " .. quote(obj.command) .. tail
- elseif name == "edit" and obj and quote(obj.path) then
- local n = type(obj.edits) == "table" and #obj.edits or 0
- if n == 1 then return "edit " .. quote(obj.path) .. " (1 edit)" end
- if n > 1 then return string.format("edit %s (%d edits)", quote(obj.path), n) end
- return "edit " .. quote(obj.path)
- end
- return string.format("tool (%s) %s", st.name or "?", st.input or "")
-end
-
-local function header(st)
- return st.header_text or derive_header(st)
-end
-
-local function edit_diff(input)
- local obj = decode(input)
- if not obj or type(obj.edits) ~= "table" then return nil end
- local out = {}
- for _, e in ipairs(obj.edits) do
- if type(e) == "table" then
- if type(e.old) == "string" then
- for l in (e.old .. "\n"):gmatch("(.-)\n") do if l ~= "" then out[#out + 1] = "-" .. l end end
- end
- if type(e.new) == "string" then
- for l in (e.new .. "\n"):gmatch("(.-)\n") do if l ~= "" then out[#out + 1] = "+" .. l end end
- end
- end
- end
- return table.concat(out, "\n")
-end
-
-local function component(st)
- return {
- render = function(_, width)
- local inner = math.max(1, (width or 1) - 2)
- local lines = { "" }
- local function add(s)
- for _, l in ipairs(wrap_text(s, inner)) do
- lines[#lines + 1] = " " .. l .. spaces(inner - #l + 1)
- end
- end
- add(header(st))
- lines[#lines + 1] = " " .. spaces(inner) .. " "
- local body
- if short_name(st.name) == "edit" and st.output then
- body = edit_diff(st.input)
- end
- body = body or st.output or "(…)"
- local body_lines = wrap_text(body, inner)
- local start = 1
- if st.collapsed and #body_lines > collapsed_tail_lines then
- add("…")
- start = #body_lines - collapsed_tail_lines + 1
- end
- for i = start, #body_lines do
- local l = body_lines[i]
- lines[#lines + 1] = " " .. l .. spaces(inner - #l + 1)
- end
- lines[#lines + 1] = ""
- return lines
- end,
- }
-end
-
-local function state_for_event(e)
- local idx = e.index
- if not idx and e.id then idx = index_by_id[e.id] end
-
- local st = nil
- if e.id then st = states_by_id[e.id] end
- if not st and idx then st = states_by_index[idx] end
-
- -- Block indexes are per-turn/per-message stream positions and are reused
- -- across later assistant turns. Tool-call ids, however, are unique for the
- -- actual call. If a new call reuses an old index, discard the old render
- -- state; otherwise the pending component temporarily shows the previous
- -- tool's output until the new result arrives.
- if st and e.id and st.id and st.id ~= e.id then
- st = nil
- end
-
- if not st then
- st = { index = idx, input = "" }
- end
- if idx then
- st.index = idx
- states_by_index[idx] = st
- end
- if e.tool_name then st.name = e.tool_name end
- if e.id then
- st.id = e.id
- index_by_id[e.id] = idx or st.index
- states_by_id[e.id] = st
- end
- if e.input then st.input = e.input end
- if e.delta then st.input = (st.input or "") .. e.delta end
- if e.output then st.output = e.output end
- if e.collapsed ~= nil then st.collapsed = e.collapsed end
- if st.collapsed == nil then st.collapsed = true end
- if st.name or st.input ~= "" then st.header_text = derive_header(st) end
- return st
-end
-
-local function on_tool_event(e)
- local name = e.tool_name
- if not name and e.id then
- local idx = index_by_id[e.id]
- local st = idx and states_by_index[idx]
- name = st and st.name
- end
- if not is_ours(name) then return end
- local st = state_for_event(e)
- if not st then return end
- e:set_component(component(st))
-end
-
-panto.ext.on("tool_details", on_tool_event)
-panto.ext.on("tool_delta", on_tool_event)
-panto.ext.on("tool_call_complete", on_tool_event)
-panto.ext.on("tool_result", on_tool_event)
-panto.ext.on("tool_collapse", on_tool_event)