diff options
| author | t <t@tjp.lol> | 2026-08-18 14:18:14 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-08-18 14:20:28 -0600 |
| commit | cc69a2e431779528578211a5cb3385bb23e076bf (patch) | |
| tree | 8833171e25bb3dfb71fc4a2e0b8fe583782da764 /spec/fake_ext.lua | |
| parent | 372ef8ff40991644ec2654c61328f31779f4ad21 (diff) | |
Persist and replay subagent progress across sessions
Record durable child-turn metadata, restore bounded progress cards during
startup replay, and keep settled cards attached to transcript entries. Add
workflow-local Lua profiles and expose discovered agents and workflows in the
session header.
Diffstat (limited to 'spec/fake_ext.lua')
| -rw-r--r-- | spec/fake_ext.lua | 82 |
1 files changed, 81 insertions, 1 deletions
diff --git a/spec/fake_ext.lua b/spec/fake_ext.lua index dfdfdb3..5207e03 100644 --- a/spec/fake_ext.lua +++ b/spec/fake_ext.lua @@ -17,7 +17,8 @@ -- panto.agent{ config =, store =, session_id =, conversation = } -> agent -- panto.file_system_jsonl_store{ dir = } / panto.null_store() -- agent:conversation() / :session_id() / :tools() / :set_tools(decls) / :run_async(opts) --- store:resolve(id) / :load(id) +-- store:list() / :list_bounded(opts) / :resolve(id) / :load(id) / +-- :load_messages(id, opts) -- conv:messages() / :message_metadata(i) / :add_system_message(text, { metadata = }) -- job:next_event() / :result() / :request_cancel() / :close() -- @@ -189,6 +190,10 @@ function conv_mt:messages() return out end +function conv_mt:len() + return #self._messages +end + function conv_mt:message_metadata(index) local message = self._messages[tonumber(index) or 0] if message == nil then @@ -239,7 +244,75 @@ function store_mt:resolve(id) return { id = id, message_count = #session, api_style = "messages" } end +function store_mt:list() + if self._harness.reject_unbounded_replay then error("unbounded list was used", 2) end + local ids = {} + for id in pairs(self._harness.sessions) do + ids[#ids + 1] = id + end + table.sort(ids) + local out = {} + for _, id in ipairs(ids) do + out[#out + 1] = { + id = id, + created = "", + modified = "", + message_count = #self._harness.sessions[id], + model = "", + } + end + return out +end + +function store_mt:list_bounded(opts) + local limit = type(opts) == "table" and math.max(0, math.floor(tonumber(opts.limit) or 0)) or 0 + self._harness.bounded_list_calls = self._harness.bounded_list_calls + 1 + local ids = {} + for id in pairs(self._harness.sessions) do ids[#ids + 1] = id end + table.sort(ids) + local out = {} + for index = 1, math.min(limit, #ids) do + local id = ids[index] + out[#out + 1] = { + id = id, + created = "", + modified = "", + message_count = #self._harness.sessions[id], + model = "", + } + end + return out +end + +local function metadata_has_key(metadata, key) + return type(metadata) == "table" and metadata[key] ~= nil +end + +function store_mt:load_messages(id, opts) + self._harness.bounded_load_calls = self._harness.bounded_load_calls + 1 + local source = self._harness.sessions[id] + if type(source) ~= "table" then return nil end + opts = type(opts) == "table" and opts or {} + local selected = {} + for index, message in ipairs(source) do + local role_ok = opts.role == nil or message.role == opts.role + local metadata_ok = opts.metadata_key == nil or metadata_has_key(message.metadata, opts.metadata_key) + if role_ok and metadata_ok then selected[#selected + 1] = index end + end + local indices = {} + if opts.from_end then + local first = math.max(1, #selected - (tonumber(opts.limit) or 0) + 1) + for index = first, #selected do indices[#indices + 1] = selected[index] end + else + for index = 1, math.min(#selected, tonumber(opts.limit) or 0) do indices[#indices + 1] = selected[index] end + end + local messages = {} + for _, index in ipairs(indices) do messages[#messages + 1] = source[index] end + return new_conversation(messages) +end + function store_mt:load(id) + if self._harness.reject_unbounded_replay then error("unbounded load was used", 2) end local session = self._harness.sessions[id] if session == nil then return nil @@ -415,6 +488,11 @@ function agent_mt:conversation() return self._conv end +function agent_mt:set_message_metadata(index, metadata) + self._record.final_metadata = metadata + return true +end + function agent_mt:session_id() return child_id(self._harness, self._record) end @@ -538,6 +616,8 @@ function M.install(opts) polls = 0, live = 0, max_live = 0, + bounded_list_calls = 0, + bounded_load_calls = 0, } function handle.queue(outcome) |
