diff options
Diffstat (limited to 'subagents/workflow.lua')
| -rw-r--r-- | subagents/workflow.lua | 47 |
1 files changed, 16 insertions, 31 deletions
diff --git a/subagents/workflow.lua b/subagents/workflow.lua index b1d3e46..3cf58d9 100644 --- a/subagents/workflow.lua +++ b/subagents/workflow.lua @@ -40,12 +40,14 @@ -- * Handles the callback never awaited are awaited ("all") after it returns, -- purely so no child is orphaned; those results are discarded. -- * Structured output is decoded from result.structured_json and validated --- against output.schema. Validation prefers the `jsonschema` rock and falls --- back to the small built-in subset validator below when it is absent -- --- that rock pulls in lrexlib-pcre, which needs a system PCRE and fails to --- build on stock macOS, and a failed rock install would otherwise take the --- whole extension down silently. A validation failure turns the result into --- status "failed"; it is never reported as a successful structured result. +-- against output.schema by the one validator below: the JSON Schema subset +-- a child's output tool actually uses, ignoring keywords it does not know. +-- There is deliberately no second, rock-dependent path -- `jsonschema` needs +-- lrexlib-pcre and a system PCRE that stock macOS lacks, so it is not a +-- declared dependency, and a validator picked by whether a rock happens to +-- be installed would make the same output pass here and fail there. A +-- validation failure turns the result into status "failed"; it is never +-- reported as a successful structured result. -- * The host seam is reached through `require("panto").ext` at call time, not -- aliased at load time, matching subagents/spawn.lua so a test can install a -- fake `panto` module before the first call rather than before the require. @@ -58,8 +60,6 @@ local M = {} local workflow_mt = { __name = "subagents.workflow" } -M.workflow_mt = workflow_mt - -- --------------------------------------------------------------------------- -- Host seam access -- --------------------------------------------------------------------------- @@ -117,16 +117,15 @@ local function json_encode(value) return tostring(value) end -M.json_decode = json_decode M.json_encode = json_encode -- --------------------------------------------------------------------------- -- Schema validation -- --------------------------------------------------------------------------- --- Built-in fallback validator: the JSON Schema subset that structured child --- output actually uses. Anything it does not understand is ignored rather than --- rejected, so an unrecognized keyword never fails a legitimate result. +-- The validator: the JSON Schema subset that structured child output actually +-- uses. Anything it does not understand is ignored rather than rejected, so an +-- unrecognized keyword never fails a legitimate result. local function is_array_like(value) local count = 0 for key in pairs(value) do @@ -259,23 +258,6 @@ local function check_schema(value, schema, path) return true end -local function validator_for(schema) - local ok, jsonschema = pcall(require, "jsonschema") - if ok and type(jsonschema) == "table" and jsonschema.generate_validator then - local generated_ok, generated = pcall(jsonschema.generate_validator, schema) - if generated_ok and type(generated) == "function" then - return generated - end - end - return function(value) - return check_schema(value, schema, "output") - end -end - -M.validate = function(value, schema) - return validator_for(schema)(value) -end - -- --------------------------------------------------------------------------- -- Result shaping -- --------------------------------------------------------------------------- @@ -312,8 +294,11 @@ local function shape_result(result, handle) return shaped end + -- An empty tool input is a real provider case (a chat-style provider + -- finalizes an argument-less call with ""), and it is not a validation + -- failure: nothing was produced to validate. local raw = shaped.structured_json - if type(raw) ~= "string" or raw == "" then + if raw == nil or raw == "" then return fail(shaped, "structured output missing: the child produced no structured result") end @@ -322,7 +307,7 @@ local function shape_result(result, handle) return fail(shaped, "structured output failed validation: " .. tostring(decoded)) end - local valid, message = validator_for(schema)(decoded) + local valid, message = check_schema(decoded, schema, "output") if not valid then return fail(shaped, "structured output failed validation: " .. tostring(message or "schema mismatch")) end |
