summaryrefslogtreecommitdiff
path: root/e2e
diff options
context:
space:
mode:
Diffstat (limited to 'e2e')
-rw-r--r--e2e/run.lua83
1 files changed, 56 insertions, 27 deletions
diff --git a/e2e/run.lua b/e2e/run.lua
index 56deda6..be58a00 100644
--- a/e2e/run.lua
+++ b/e2e/run.lua
@@ -466,8 +466,8 @@ end
-- 1. One tool batch, seven calls: two children that must overlap, three that
-- report what they were handed, one that fails mid-stream, and one unknown
--- profile that never becomes a child. Six jobs against a bound of four also
--- means two of them start only when a slot frees.
+-- profile that never becomes a child. Six jobs against a bound of five also
+-- means one of them starts only when a slot frees.
scenario("parallel-batch", function()
local install = make_install("parallel-batch")
local script = table.concat({
@@ -487,7 +487,7 @@ scenario("parallel-batch", function()
"Error: unknown agent 'ghost'; known: alpha, beta")
check_contains("child A reported its rendezvous", out, "pair:A")
check_contains("child B reported its rendezvous", out, "pair:B")
- check_contains("the primary's system context reached a child", out, "sys-found PRIMARY-CONTEXT-MARK")
+ check_contains("the primary's system context did not reach a child", out, "sys-missing PRIMARY-CONTEXT-MARK")
-- One child's stream failed; its five siblings settled on their own terms.
check_equal("five children completed", count_occurrences(out, "status: completed"), 5)
@@ -601,15 +601,41 @@ scenario("parallel-batch", function()
end
check_contains(who .. ": the child-role instruction was seeded", text,
"You are a subagent working inside another agent's session")
- check_contains(who .. ": the primary's system context was seeded", text,
- "PRIMARY-CONTEXT-MARK")
+ local primary_context_in_system = false
+ for _, line in ipairs(lines_of(text)) do
+ if line:find('"role":"system"', 1, true)
+ and line:find("PRIMARY-CONTEXT-MARK", 1, true) then
+ primary_context_in_system = true
+ break
+ end
+ end
+ check(who .. ": the primary's system context was not seeded",
+ not primary_context_in_system, excerpt(text, 400))
end
check_equal("every child carries one manifest", seen_manifest, 5)
check_equal("every child recorded one turn's model/reasoning", seen_turn, 5)
check_equal("the two beta children ran on the profile's model", seen_beta, 2)
end)
--- 2. A child outlives its process: a second `panto --resume` continues it, and a
+-- 2. A one-off child can define its own system prompt without a profile or a
+-- workflow wrapper.
+scenario("inline-run", function()
+ local install = make_install("inline-run")
+ local out = turn(install,
+ [[tool subagents.run {"system_prompt":"INLINE-RUN-MARK","prompt":"sys INLINE-RUN-MARK"}]])
+ check_contains("the inline child completed", out, "status: completed")
+ check_contains("the inline prompt reached the child", out, "sys-found INLINE-RUN-MARK")
+ check_contains("the inline child has a stable result label", out, "agent: subagent")
+
+ local dir = assert(session_dir(install))
+ local primary_id = jsonl_ids(dir)[1]
+ local children = jsonl_ids(assert(child_dir(install, primary_id)))
+ check_equal("the inline child persisted normally", #children, 1)
+ local text = read_file(assert(child_dir(install, primary_id)) .. "/" .. children[1] .. ".jsonl") or ""
+ check_contains("the inline manifest is replay-visible", text, meta('"inline":true'))
+end)
+
+-- 3. A child outlives its process: a second `panto --resume` continues it, and a
-- third, unrelated primary cannot.
scenario("resume", function()
local install = make_install("resume")
@@ -662,7 +688,7 @@ scenario("resume", function()
string.format("Error: unknown subagent id '%s' for this session", child_id))
end)
--- 3. A discovered TOML workflow: a diamond, so both branches run concurrently
+-- 4. A discovered TOML workflow: a diamond, so both branches run concurrently
-- off one root and the sink sees both labelled outputs.
scenario("workflow-diamond", function()
local install = make_install("workflow-diamond")
@@ -680,13 +706,14 @@ scenario("workflow-diamond", function()
check_equal("four steps became four children", #jsonl_ids(assert(child_dir(install, primary_id))), 4)
end)
--- 4. The restricted `subagents.lua` sandbox: a one-shot structured worker whose
+-- 5. The restricted `subagents.lua` sandbox: a one-shot structured worker whose
-- decoded output drives the fan-out.
scenario("sandbox-fanout", function()
local install = make_install("sandbox-fanout")
local source = table.concat({
- "return subagents.workflow(function(ctx, input)",
+ "return subagents.workflow(function(ctx)",
" local split = ctx:agent({",
+ " name = 'split',",
" agent = 'alpha',",
[[ prompt = 'emit emit_result {\"items\":[\"X\",\"Y\"]}',]],
" output = { description = 'the work items', schema = { type = 'object',",
@@ -695,37 +722,44 @@ scenario("sandbox-fanout", function()
" }):await()",
" local handles = {}",
" for _, item in ipairs(split.output.items) do",
- " handles[#handles + 1] = ctx:agent({ agent = 'beta', prompt = 'say ITEM-' .. item })",
+ " handles[#handles + 1] = ctx:agent({ name = 'item-' .. item, agent = 'beta', prompt = 'say ITEM-' .. item })",
" end",
- " return ctx:await(handles, 'all')",
+ " local results = ctx:await(handles, 'all')",
+ " return results[1].output .. '\\\\n' .. results[2].output",
"end)",
}, "\\n")
local out = turn(install, string.format(
- [[tool subagents.lua {"prompt":"FANOUT-INPUT","source":"%s"}]], source))
+ [[tool subagents.lua {"source":"%s"}]], source))
- check_contains("the first fan-out branch ran", out, "ITEM-X")
- check_contains("the second fan-out branch ran", out, "ITEM-Y")
- check_equal("the fan-out produced two results", count_occurrences(out, "status: completed"), 2)
+ check_contains("the workflow id returned immediately", out, "workflow-")
-- The one-shot worker is ephemeral: only the two conversational children
-- have a durable file.
local dir = assert(session_dir(install))
local primary_id = jsonl_ids(dir)[1]
- check_equal("the structured worker left no session behind",
- #jsonl_ids(assert(child_dir(install, primary_id))), 2)
+ local children = assert(child_dir(install, primary_id))
+ local ids = jsonl_ids(children)
+ check_equal("the structured worker left no session behind", #ids, 2)
+ local persisted = ""
+ for _, id in ipairs(ids) do persisted = persisted .. (read_file(children .. "/" .. id .. ".jsonl") or "") end
+ check_contains("the first fan-out branch ran", persisted, "ITEM-X")
+ check_contains("the second fan-out branch ran", persisted, "ITEM-Y")
end)
--- 5. An inline profile in the dynamic workflow gets a durable marker and
+-- 6. An inline profile in the dynamic workflow gets a durable marker and
-- body, so restart replay can show the requested system prompt without
-- exposing discovered profile prompts.
scenario("inline-replay-manifest", function()
local install = make_install("inline-replay-manifest")
- local source = "return subagents.workflow(function(ctx, input) return ctx:agent({ agent = 'inline', prompt = 'say INLINE-CHILD' }):await() end)"
+ local source = [[return subagents.workflow(function(ctx)
+ local result = ctx:agent({ name = 'inline-work', agent = 'inline', prompt = 'say INLINE-CHILD' }):await()
+ return result.output
+ end)]]
local script = string.format(
- 'tool subagents.lua {"prompt":"INLINE-INPUT","source":%s,"agents":[{"name":"inline","system_prompt":"INLINE-SYSTEM"}]}',
+ 'tool subagents.lua {"source":%s,"agents":[{"name":"inline","system_prompt":"INLINE-SYSTEM"}]}',
json_string(source))
local out = turn(install, script)
- check_contains("the inline workflow child completed", out, "INLINE-CHILD")
+ check_contains("the inline workflow id returned", out, "workflow-")
local dir = assert(session_dir(install))
local primary_id = jsonl_ids(dir)[1]
@@ -737,15 +771,13 @@ scenario("inline-replay-manifest", function()
check_contains("the inline system prompt remains durable", text, "INLINE-SYSTEM")
end)
--- 6. The catalog tool, in all four shapes, against a provider whose reasoning
+-- 7. The catalog tool, in its three shapes, against a provider whose reasoning
-- levels come from the protocol rather than models.toml.
scenario("catalog", function()
local install = make_install("catalog")
local out = turn(install, table.concat({
[[tool subagents.models {}]],
[[tool subagents.models {"model":"fixture-provider:beta"}]],
- [[tool subagents.models {"agent":"alpha"}]],
- [[tool subagents.models {"agent":"beta"}]],
[[tool subagents.models {"query":"beta"}]],
[[tool subagents.models {"model":"fixture-provider:nope"}]],
}, " && "))
@@ -755,9 +787,6 @@ scenario("catalog", function()
check_contains("the overview counts the fixture provider's models", out, "fixture-provider (")
check_contains("the exact lookup resolves the wire name", out, "wire model: beta-wire")
check_contains("the exact lookup reports the protocol's effort levels", out, "reasoning levels: tiny, deep")
- check_contains("a profile without a model says it inherits", out, "model: inherits the primary model")
- check_contains("a profile with a model resolves it", out, "model: fixture-provider:beta")
- check_contains("a profile's reasoning is reported", out, "profile reasoning: deep")
check_contains("the search found the model", out, "1 match(es):")
check_contains("an unknown model is reported, not resolved", out,
"No configured model matches 'fixture-provider:nope'")