summaryrefslogtreecommitdiff
path: root/spec/fake_ext.lua
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-08-19 19:02:30 -0600
committert <t@tjp.lol>2026-08-19 19:03:52 -0600
commitd1306506aa7f504b0e91c9c6ed7314afbf99978e (patch)
treee5a7295dbc566a3679e99e14dae13376b0469e84 /spec/fake_ext.lua
parent94e3fd8358bbdb5d6ed81aed475fab7fc73e2097 (diff)
Add background Lua workflows, inline child prompts, and layered config
subagents.lua now starts a workflow on its own coroutine and returns a session-scoped id immediately, so fan-out continues while the primary keeps working; completion wakes the primary, and later calls read immutable records from subagents.workflows. Every ctx:agent takes a workflow-unique name so those records are addressable. A session_start guidance message tells the primary when to reach for run vs lua. Children no longer inherit the primary's system context: a child starts from the fixed child-role instruction plus its profile, and subagents.run/ctx:agent accept an inline system_prompt instead of a profile. The now-redundant `agent` form of subagents.models is gone. Concurrency defaults to five and is configurable through [subagents] max_concurrent in any layered config.toml; turn boundaries reap only settled jobs so background workflows survive, while interrupt and session end cancel. Config roots come from panto.ext.dirs.layers rather than a hand-rolled XDG lookup, which picks up the base and git-ignored local layers for both agents/ and workflows/. TOML workflows tighten up: the subagents.workflow tool takes a discovered name only (inline `steps` duplicated subagents.lua at less power), an optional top-level `output` array chooses the reported steps and their order instead of the terminal set, a step with no workflow input gets no empty input heading, and a workflow naming an undiscovered agent is rejected at discovery rather than part-way through a run.
Diffstat (limited to 'spec/fake_ext.lua')
-rw-r--r--spec/fake_ext.lua33
1 files changed, 33 insertions, 0 deletions
diff --git a/spec/fake_ext.lua b/spec/fake_ext.lua
index 5207e03..88c4b56 100644
--- a/spec/fake_ext.lua
+++ b/spec/fake_ext.lua
@@ -334,6 +334,7 @@ local function new_job(cfg)
_events = cfg.events or {},
_finish = cfg.finish,
_harness = cfg.harness,
+ _wake_fd = cfg.wake_fd,
_polls = 0,
_settled = false,
_result = nil,
@@ -372,6 +373,7 @@ function job_mt:result()
elseif self._polls >= self._settle_after then
self._result = self._finish(self)
else
+ if self._wake_fd then pcall(require("luv").fs_write, self._wake_fd, "x", -1) end
return nil
end
self._settled = true
@@ -488,6 +490,17 @@ function agent_mt:conversation()
return self._conv
end
+function agent_mt:add_system_message(text)
+ return self._conv:add_system_message(text)
+end
+
+function agent_mt:submit(value)
+ if not self._borrowed then
+ error("panto: submit is only available on the host session agent", 2)
+ end
+ self._harness.submissions[#self._harness.submissions + 1] = value
+end
+
function agent_mt:set_message_metadata(index, metadata)
self._record.final_metadata = metadata
return true
@@ -552,6 +565,7 @@ function agent_mt:run_async(options)
settle = outcome_for(h, record).settle,
events = outcome_for(h, record).events,
harness = h,
+ wake_fd = options.wake_fd,
finish = function()
return settled_result(h, record)
end,
@@ -559,6 +573,7 @@ function agent_mt:run_async(options)
h.jobs[#h.jobs + 1] = job
record.job = job
h.live = h.live + 1
+ if options.wake_fd then pcall(require("luv").fs_write, options.wake_fd, "x", -1) end
if h.live > h.max_live then
h.max_live = h.live
end
@@ -609,6 +624,8 @@ function M.install(opts)
commands_by_name = {},
models_queries = {},
subscriptions = {},
+ submissions = {},
+ emitted = {},
on_by_name = {},
mkdirs = made_dirs,
queued = {},
@@ -653,6 +670,18 @@ function M.install(opts)
local ext = {}
+ -- The host's layer list, in the same shape and order panto installs it.
+ ext.dirs = opts.dirs or {
+ home = "/home/u",
+ project_root = "/proj",
+ layers = {
+ { name = "base", dir = "/data/panto/agent" },
+ { name = "user", dir = "/home/u/.config/panto" },
+ { name = "project", dir = "/proj/.panto" },
+ { name = "local", dir = "/proj/.panto/local" },
+ },
+ }
+
function ext.session_info()
return copy(handle.session)
end
@@ -697,6 +726,10 @@ function M.install(opts)
handle.on_by_name[name] = fn
end
+ function ext.emit(name)
+ handle.emitted[#handle.emitted + 1] = name
+ end
+
-- Fire a subscribed lifecycle handler, the way the host would.
function handle.emit(name, event)
for _, subscription in ipairs(handle.subscriptions) do