Add state output passthrough to node-editor nodes (#45) (#47)

* Add state output passthrough to node-editor nodes (#45)

Any node with a `state` input must expose a `state` output that passes
the input value through. Eleven nodes early in development neglected
this. Add the missing `state` output socket and pass
`get_input_value("state")` through in run() for:

- Counter (util)
- ToggleAgentAction, CallAgentFunctionConditional (agents)
- Sort, MakeDict, MakeList, UUID (data)
- EmitAgentMessage (event)
- ScopedAPIFunction (api)
- WaitForInput (input)
- ActedAsCharacter (raise) — follows the Stop-node precedent, setting
  the passthrough before the (always-raised) exception so the socket
  can be connected.
This commit is contained in:
veguAI
2026-07-02 15:23:02 +03:00
committed by GitHub
parent 380ec0f663
commit 46099086d7
7 changed files with 91 additions and 7 deletions

View File

@@ -156,12 +156,14 @@ class ToggleAgentAction(Node):
Inputs:
- state: The graph state
- agent: str,agent
- action_name: str
- enabled: bool
Outputs:
- state: The state input, passed through
- agent: agent
- action_name: str
- enabled: bool
@@ -201,6 +203,7 @@ class ToggleAgentAction(Node):
self.set_property("action_name", "")
self.set_property("enabled", True)
self.add_output("state")
self.add_output("agent", socket_type="agent")
self.add_output("action_name", socket_type="str")
self.add_output("enabled", socket_type="bool")
@@ -230,7 +233,12 @@ class ToggleAgentAction(Node):
agent.write_enabled(action_name, enabled)
self.set_output_values(
{"agent": agent, "action_name": action_name, "enabled": enabled}
{
"state": self.get_input_value("state"),
"agent": agent,
"action_name": action_name,
"enabled": enabled,
}
)
@@ -327,6 +335,7 @@ class CallAgentFunctionConditional(CallAgentFunction):
def setup(self):
self.add_input("state")
self.add_output("state")
super().setup()
async def run(self, state: GraphState):

View File

@@ -21,6 +21,17 @@ log = structlog.get_logger("talemate.game.engine.nodes.core.api")
class ScopedAPIFunction(Node):
"""
Executes python code inside the quarantined scoped environment.
Inputs:
- state: The graph state
- agent: The agent whose client the scoped context runs against
- arguments: Arguments made available to the executed code
Outputs:
- state: The state input, passed through
- result: The result dict populated by the executed code
"""
class Fields:
@@ -49,6 +60,7 @@ class ScopedAPIFunction(Node):
self.set_property("code", UNRESOLVED)
self.add_output("state")
self.add_output("result")
async def run(self, state: GraphState):
@@ -80,4 +92,9 @@ class ScopedAPIFunction(Node):
with OpenScopedContext(scene, agent.client):
_module()
self.set_output_values({"result": result})
self.set_output_values(
{
"state": self.get_input_value("state"),
"result": result,
}
)

View File

@@ -27,6 +27,7 @@ class Sort(Node):
Inputs:
- state: The graph state
- items: List of items to sort
- sort_keys: List of keys to sort by
- reverse: Reverse sort
@@ -38,6 +39,7 @@ class Sort(Node):
Outputs:
- state: The state input, passed through
- sorted_items: Sorted list of items
"""
@@ -67,6 +69,7 @@ class Sort(Node):
self.set_property("reverse", False)
self.set_property("sort_keys", UNRESOLVED)
self.add_output("state")
self.add_output("sorted_items", socket_type="list")
async def run(self, state: GraphState):
@@ -91,7 +94,12 @@ class Sort(Node):
else:
new_items.sort(reverse=reverse)
self.set_output_values({"sorted_items": new_items})
self.set_output_values(
{
"state": self.get_input_value("state"),
"sorted_items": new_items,
}
)
@register("data/JSON")
@@ -543,6 +551,7 @@ class MakeDict(Node):
Outputs:
- state: The state input, passed through
- dict: Dictionary
"""
@@ -562,6 +571,7 @@ class MakeDict(Node):
self.set_property("data", {})
self.add_output("state")
self.add_output("dict", socket_type="dict")
async def run(self, state: GraphState):
@@ -569,7 +579,12 @@ class MakeDict(Node):
# node's static `data` property across executions.
new_dict = copy.deepcopy(self.get_property("data"))
self.set_output_values({"dict": new_dict})
self.set_output_values(
{
"state": self.get_input_value("state"),
"dict": new_dict,
}
)
@register("data/Get")
@@ -760,6 +775,7 @@ class MakeList(Node):
Outputs:
- state: The state input, passed through
- list: List
"""
@@ -789,6 +805,7 @@ class MakeList(Node):
self.set_property("item_type", "any")
self.set_property("items", [])
self.add_output("state")
self.add_output("list", socket_type="list")
async def run(self, state: GraphState):
@@ -803,7 +820,12 @@ class MakeList(Node):
# node's static `items` property across executions.
new_list = copy.deepcopy(self.get_property("items"))
self.set_output_values({"list": new_list})
self.set_output_values(
{
"state": self.get_input_value("state"),
"list": new_list,
}
)
@register("data/ListAppend")
@@ -1361,12 +1383,18 @@ class UUID(Node):
"""
Generates a UUID string
Inputs:
- state: The graph state
- max_length: Maximum number of characters to return
Properties:
- max_length: Maximum number of characters to return (optional, if not set returns full UUID)
Outputs:
- state: The state input, passed through
- uuid: A UUID string (e.g., "550e8400-e29b-41d4-a716-446655440000")
"""
@@ -1385,6 +1413,7 @@ class UUID(Node):
self.add_input("state", optional=True)
self.add_input("max_length", socket_type="int", optional=True)
self.set_property("max_length", 36)
self.add_output("state")
self.add_output("uuid", socket_type="str")
async def run(self, state: GraphState):
@@ -1394,7 +1423,12 @@ class UUID(Node):
if max_length > 0:
uuid_string = uuid_string[:max_length]
self.set_output_values({"uuid": uuid_string})
self.set_output_values(
{
"state": self.get_input_value("state"),
"uuid": uuid_string,
}
)
@register("data/UpdateObject")

View File

@@ -512,6 +512,7 @@ class EmitAgentMessage(Node):
Outputs:
- state: The state input, passed through
- emitted: Whether the message was emitted (True) or not (False)
"""
@@ -573,6 +574,7 @@ class EmitAgentMessage(Node):
self.set_property("message_color", "grey")
self.set_property("meta", {})
self.add_output("state")
self.add_output("emitted", socket_type="bool")
async def run(self, state: GraphState):
@@ -604,6 +606,7 @@ class EmitAgentMessage(Node):
self.set_output_values(
{
"state": self.get_input_value("state"),
"emitted": True,
}
)

View File

@@ -37,6 +37,10 @@ class ActedAsCharacter(Node):
- state: The current graph state
- character_name: The name of the character the user acted as
Outputs:
- state: The state input, passed through
"""
def __init__(self, title="Acted As Character", **kwargs):
@@ -46,9 +50,15 @@ class ActedAsCharacter(Node):
self.add_input("state")
self.add_input("character_name", socket_type="str")
self.add_output("state")
async def run(self, state: GraphState):
character_name = self.get_input_value("character_name")
# this will never be reached, but it's here to make sure
# that Stage nodes can be connected to this node
self.set_output_values({"state": self.get_input_value("state")})
raise exceptions.ActedAsCharacter(character_name)

View File

@@ -799,6 +799,7 @@ class WaitForInput(Node):
Outputs:
- state: The state input, passed through
- input: The input message
- interaction_state: The interaction state
- character: The character object
@@ -846,6 +847,7 @@ class WaitForInput(Node):
self.set_property("prefix", "")
self.set_property("allow_commands", True)
self.add_output("state")
self.add_output("input", socket_type="str")
self.add_output("interaction_state", socket_type="interaction_state")
self.add_output("character", socket_type="character")
@@ -970,6 +972,7 @@ class WaitForInput(Node):
self.set_output_values(
{
"state": self.get_input_value("state"),
"input": text_message,
"interaction_state": interaction_state,
"character": player_character,

View File

@@ -30,6 +30,7 @@ class Counter(Node):
- reset: If true, the value will be reset to 0
Outputs:
- state: The state input, passed through
- value: The new value
- dict: The dict with the new value
"""
@@ -71,6 +72,7 @@ class Counter(Node):
self.set_property("key", "counter")
self.set_property("reset", False)
self.add_output("state")
self.add_output("value")
self.add_output("dict", socket_type="dict")
@@ -88,7 +90,13 @@ class Counter(Node):
else:
dict_[key] = dict_.get(key, 0) + increment
self.set_output_values({"value": dict_[key], "dict": dict_})
self.set_output_values(
{
"state": self.get_input_value("state"),
"value": dict_[key],
"dict": dict_,
}
)
@register("util/Diff")