Repository navigation
fix(py-agent): compile Event userMessage and nested action slots in Express - #3635
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the Express compiler and decompiler to support userMessage and context keyword arguments on Event(...) signatures, compiling them to v1.0 action fields, and correctly decompiling them back. It also introduces support for compiling nested function calls in action slots (e.g., inside list items or object properties) as functionCall actions by resolving sub-schemas. A review comment identifies two issues in the newly added resolve_subschema method: it prematurely returns additionalProperties fallback before checking combinators like allOf/oneOf/anyOf, and it fails to dereference local $refs of the resolved property schema, which can prevent proper action slot detection.
daefc3f to
6ddf7de
Compare
6ddf7de to
45a2f52
Compare
nan-yu
left a comment
There was a problem hiding this comment.
This is a faithful port of #3634: the same _ValueSlot threading, the same Event keyword handling, and the decompiler puts userMessage= in the same place. It also fixes Python so that a function call inside an event context stays a plain call, as in TS. The Express tests pass on the branch (169 passed).
One bug carried over from the TS PR and two smaller points, inline:
Must address
userMessagerejects function calls, which v1.0 allows (DynamicString), so a decompile and recompile round trip fails. This is the same bug as in #3634.
Should address
2. Python still treats a property named action or submitAction as an action slot whatever its schema says. TS doesn't.
3. The error for a bad userMessage shows a Python repr to the model.
45a2f52 to
ca736da
Compare
ca736da to
246fb39
Compare
246fb39 to
15cbf83
Compare
15cbf83 to
285fdf6
Compare
285fdf6 to
2365a32
Compare
2365a32 to
0b20162
Compare
…xpress
`Event("reply", userMessage="...")` silently dropped `userMessage`, and a
function call used as the action of a list item (for example
`Links([{label: "Docs", action: openUrl("...")}])`) compiled to a bare
`{"@call": ...}` that the processor rejects.
- `Event` now accepts `userMessage=` and `context=` keyword arguments.
`userMessage` compiles to the v1.0 `event.userMessage` field and raises
`ExpressValidationError` before v1.0; any other keyword on `Event` is
rejected rather than dropped.
- `_compile_value` carries the catalog schema at the current position, so an
`Action`-typed sub-schema inside array items or object properties wraps
function calls in `functionCall` like a top-level action slot does.
`CatalogSchemaHelper` gains `resolve_subschema` and the shared
`is_action_slot` helper to walk the schema.
- `ExpressDecompiler` writes `userMessage=` back so events round-trip.
Fixes points 1 and 2 of #3598 for the Python SDK.
The event's name, userMessage and context entries are DynamicValues, so a function call among them is a plain call. The action flag of the slot the event sits in no longer reaches them, which also matches the Dart compiler.
Action.event.userMessage is a DynamicString: a string, a data binding or a function call. The compiler accepted only the first two, so an event the decompiler wrote with a call did not compile back. The error for any other value now names what the model wrote instead of printing the node. Whether a property is an action slot now comes from its catalog schema alone, as in TypeScript; the fallback on the property names `action` and `submitAction` is gone, and the inline test catalogs that relied on it declare the common `Action` type.
resolve_subschema took the key "items" to mean the array items, so an object property named items was never looked up among the properties. It is now two methods, resolve_item_schema and resolve_property_schema, and the item slot is resolved once per list rather than once per element. Before v1.0 the decompiler writes an event carrying a userMessage as a map literal, since that version's compiler rejects userMessage= and the literal compiles back as written.
0b20162 to
92e225a
Compare
Python mirror of the
@a2ui/agentfix for points 1 and 2 of #3598; same contract, same error categories.Event(name, context?, userMessage=?, context=?):userMessage→ v1.0event.userMessage;ExpressValidationErrorbefore v1.0 and for a non-string/non-$pathvalue;ExpressInvalidParamErrorfor a keywordEventdoes not define;ExpressDuplicateParamErrorfor a context given twice.is_action_slot(schema)andCatalogSchemaHelper.resolve_subschema(schema, key)in_shared/schema_helper.py(items /properties[key]/additionalProperties, through common-type and in-document$refs andallOf/oneOf/anyOf, cycle-guarded)._compile_valuethreads a_ValueSlotthrough dict entries, list items and variables and ORsis_actionwith the slot. Top-level action detection is now schema-based first, with the pre-existingaction/submitActionname fallback kept so inline test catalogs that declare"action": {}keep working.ExpressDecompilerwritesuserMessage=back.Tests
11 compiler + 3 decompiler round-trip tests.
pytest python/a2ui_agent: all green (1557 passed); the new conformance cases from the last PR of this stack pass against this branch (157 passed, 3 xfailed).pyink --checkandmypyclean.Pre-launch Checklist
One time:
For this PR:
If you need help, consider asking for advice on the discussion board.
Stack created with GitHub Stacks CLI • Give Feedback 💬