diff options
| author | t <t@tjp.lol> | 2026-08-19 19:02:30 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-08-19 19:03:52 -0600 |
| commit | d1306506aa7f504b0e91c9c6ed7314afbf99978e (patch) | |
| tree | e5a7295dbc566a3679e99e14dae13376b0469e84 /spec/fake_ext.lua | |
| parent | 94e3fd8358bbdb5d6ed81aed475fab7fc73e2097 (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.lua | 33 |
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 |
