Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.7.6"
".": "0.7.14"
}
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ PUBLISH_DRY_RUN_TOKEN ?= wpy_ci_dry_run_0123456789abcdef0123456789abcdef
test: test-sqlite

test-sqlite: clean test-static
cd $(TEST_DIR) && $(WIPPY) run test --profile sqlite
cd $(TEST_DIR) && $(WIPPY) test --profile sqlite

test-postgres: test-static
cd $(TEST_DIR) && $(WIPPY) run test --profile postgres \
cd $(TEST_DIR) && $(WIPPY) test --profile postgres \
--set "vars.postgres_host=$(DATAFLOW_PG_HOST)" \
--set "vars.postgres_port=$(DATAFLOW_PG_PORT)" \
--set "vars.postgres_database=$(DATAFLOW_PG_DATABASE)" \
Expand Down
2 changes: 1 addition & 1 deletion src/_index.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "0.7.6" # x-release-please-version
version: "0.7.14" # x-release-please-version
namespace: userspace.dataflow

entries:
Expand Down
51 changes: 1 addition & 50 deletions src/api/_index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ entries:
meta:
comment: Cancel a running dataflow
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
source: file://cancel_dataflow.lua
modules:
Expand All @@ -27,10 +23,6 @@ entries:
meta:
comment: Cancel dataflow endpoint
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
method: POST
func: cancel_dataflow
Expand All @@ -42,10 +34,6 @@ entries:
meta:
comment: Deliver a signal to a waiting dataflow
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
source: file://signal_dataflow.lua
modules:
Expand All @@ -62,10 +50,6 @@ entries:
meta:
comment: Signal dataflow endpoint
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
method: POST
func: signal_dataflow
Expand All @@ -77,10 +61,6 @@ entries:
meta:
comment: Get complete dataflow details with nodes and data
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
source: file://get_dataflow.lua
modules:
Expand All @@ -98,10 +78,6 @@ entries:
meta:
comment: Get dataflow endpoint
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
method: GET
func: get_dataflow
Expand All @@ -113,10 +89,6 @@ entries:
meta:
comment: Get dataflow nodes only
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
source: file://get_dataflow_nodes.lua
modules:
Expand All @@ -133,10 +105,6 @@ entries:
meta:
comment: Get dataflow nodes endpoint
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
method: GET
func: get_dataflow_nodes
Expand All @@ -148,10 +116,6 @@ entries:
meta:
comment: List user's dataflows with filtering and pagination
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
source: file://list_dataflows.lua
modules:
Expand All @@ -167,10 +131,6 @@ entries:
meta:
comment: List dataflows endpoint
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
method: GET
func: list_dataflows
Expand All @@ -182,10 +142,6 @@ entries:
meta:
comment: Terminate a dataflow forcefully
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
source: file://terminate_dataflow.lua
modules:
Expand All @@ -194,19 +150,14 @@ entries:
imports:
client: userspace.dataflow:client
method: handler

# userspace.dataflow.api:terminate_dataflow.endpoint
- name: terminate_dataflow.endpoint
kind: http.endpoint
meta:
comment: Terminate dataflow endpoint
description: Dataflow management HTTP endpoints
depends_on:
- app:api
- ns:userspace.dataflow
- ns:userspace.dataflow.persist
router: app:api
method: POST
func: terminate_dataflow
path: /dataflows/{id}/terminate

47 changes: 45 additions & 2 deletions src/node/agent/node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,33 @@ local function configure_tool_wrappers(caller, agent_instance, n, agent_id, mode
end
end

local function exit_schema_violation(schema: any, arguments: any): string?
if type(schema) ~= "table" then return nil end
if type(arguments) ~= "table" then
return "the finish call carried " .. type(arguments)
.. " arguments where the exit schema requires an object"
end

local missing = {} :: { string }
local required = (schema :: any).required
if type(required) == "table" then
for _, key in ipairs(required :: { any }) do
if type(key) == "string" and (arguments :: any)[key] == nil then
table.insert(missing, key :: string)
end
end
end
if #missing > 0 then
return "the finish call is missing required fields: " .. table.concat(missing, ", ")
end

local properties = (schema :: any).properties
if next(arguments :: any) == nil and type(properties) == "table" and next(properties :: any) ~= nil then
return "the finish call carried no arguments where the exit schema declares properties"
end
return nil
end

local function process_tool_results(n, tool_results, iteration, exit_tool_name, agent_result: any, arena_config,
session_context, tool_call_to_node_id)
local control_responses = {}
Expand Down Expand Up @@ -1458,8 +1485,24 @@ local function process_tool_results(n, tool_results, iteration, exit_tool_name,
final_result = validated_result
end
else
task_complete = true
final_result = exit_arguments or { success = false, error = "Exit tool called without arguments" }
local violation = exit_schema_violation(arena_config.exit_schema, exit_arguments)
if violation then
n:data(agent_consts.DATA_TYPE.AGENT_OBSERVATION, violation, {
key = iteration .. "_exit_validation_failed",
content_type = consts.CONTENT_TYPE.TEXT,
node_id = n.node_id,
metadata = {
iteration = iteration,
is_error = true,
tool_call_id = original_tool_call.id,
tool_name = original_tool_call.name,
exit_validation = true
}
})
else
task_complete = true
final_result = exit_arguments
end
end
break
end
Expand Down
64 changes: 64 additions & 0 deletions src/node/agent/process_tool_results_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,70 @@ local function define_tests()
test.eq((final_result :: any).answer, "done", "final result carries the finish arguments")
test.eq(#recorded, 0, "success path does not record sibling tool observations")
end)

it("rejects a finish call that omits a required exit field", function()
local process_tool_results = agent_node._test.process_tool_results
local n, recorded = make_recording_node()
local agent_result = {
tool_calls = {
{ id = "call_finish", name = "finish", arguments = {} },
}
}

local _responses, _delegations, task_complete, final_result = process_tool_results(
n,
{},
1,
"finish",
agent_result,
{
exit_schema = {
type = "object",
properties = { answer = { type = "string" } },
required = { "answer" }
}
},
{},
{}
)

test.eq(task_complete, false, "invalid finish does not complete the task")
test.is_nil(final_result, "invalid finish has no final result")
local rejection = find_by_tool_call_id(recorded, "call_finish")
test.not_nil(rejection, "schema rejection is recorded")
test.contains(rejection.content, "answer", "rejection identifies the missing field")
end)

it("accepts a finish call that satisfies the exit schema", function()
local process_tool_results = agent_node._test.process_tool_results
local n, recorded = make_recording_node()
local agent_result = {
tool_calls = {
{ id = "call_finish", name = "finish", arguments = { answer = "done" } },
}
}

local _responses, _delegations, task_complete, final_result = process_tool_results(
n,
{},
1,
"finish",
agent_result,
{
exit_schema = {
type = "object",
properties = { answer = { type = "string" } },
required = { "answer" }
}
},
{},
{}
)

test.eq(task_complete, true, "valid finish completes the task")
test.eq((final_result :: any).answer, "done", "valid finish preserves its result")
test.eq(#recorded, 0, "valid finish records no rejection")
end)
end)
end

Expand Down
3 changes: 3 additions & 0 deletions test/.wippy.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
version: "1.0"
workspace:
replacements:
wippy/dataflow: ../src
vars:
sqlite_file: ./.wippy/test.db
postgres_host: 127.0.0.1
Expand Down
7 changes: 7 additions & 0 deletions test/_index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ entries:
- name: wippy.migration:app_db
value: app:db

- name: dep.wippy.security
kind: ns.dependency
meta:
description: Standard process policy groups required by framework services
component: wippy/security
version: ">=v0.4.2"

- name: dep.wippy.bootloader
kind: ns.dependency
meta:
Expand Down
38 changes: 19 additions & 19 deletions test/wippy.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@ directories:
src: .
modules:
- name: wippy/agent
version: 0.4.14
hash: ff47bf040857d520fbf9e576f1b2d8653516d36d340b82e7ecfa8ce1ed2fe9b4
version: 0.4.17
hash: f8b8ed9f8098e254f7b431ca9f5378672bb5deae33122b777d1714092bcca91a
- name: wippy/bootloader
version: 0.3.13
hash: 4f32d32b8a37a7c55b65e72242252eab2d53500591a83dca9787d742a65ff421
version: 0.3.14
hash: aa5e32807eba6a5ea0e5a224069a006288f58605c4542a444f5469caee862c58
- name: wippy/llm
version: 0.4.35
hash: 0fe840b50d9ec7d1f4082dca0027f6009cd539aff5f0fd9234c70673232f6905
version: 0.4.42
hash: 173caaf535bafec0c184c93de63eca75e6281d87dfcfa460ec59982020812ad8
- name: wippy/migration
version: 0.3.17
hash: 55834821cd2832f8582a52e98772810ba3bdfe91d4967262d3d69e6e9c2b2879
version: 0.3.18
hash: e00cad6706bb95f556aeab5318a04e55d3884c027b09f6340fc4e7d69c905a17
- name: wippy/security
version: 0.4.2
hash: 9020016afc9de612f5297d38ce99e8500c63a2986077e8b0e560d8636c506627
- name: wippy/session
version: 0.1.31
hash: 9d9b2aca94b6857fea5e47bae014ff582a558a283dae1df5e997fe4fa948e671
version: 0.4.2
hash: 651bd603d4102702372a4c199bc9f165087a38f6a4ae9579a45bca78710e9df8
- name: wippy/terminal
version: 0.4.4
hash: 11fcb6a64895364fa603000afd66e9889b5a711bc881f2b4fe5723cd9772df2a
version: 0.4.5
hash: 028180c6044cdd9bbe15330255a4926770e02a291511930264a615f6388824f0
- name: wippy/test
version: 0.4.13
hash: cfdbfc0a7cf05fa825d203b80ce92fbd24e03da00e2083efe21ff4266cb44608
version: 0.4.17
hash: 37a304cc20aa3005004255e9fda16835a94119db520c0c97e1db044c7844a229
- name: wippy/views
version: 0.5.6
hash: 334151b0a36d1f26482e05c4076aa8f39187871376ac5c86120a5eaf51e91fc3
replacements:
- from: wippy/dataflow
to: ../src
version: 0.5.10
hash: a25c35b260e8f9c161f372aa8f5e80624af4db233f2b9de4a36d9015342f01fe
2 changes: 1 addition & 1 deletion wippy.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
organization: wippy
module: dataflow
version: 0.7.6 # x-release-please-version
version: 0.7.14 # x-release-please-version
description: Workflow execution engine with visual flow designer support
license: Apache-2.0
keywords:
Expand Down