da-daken opened a new pull request, #1155:
URL: https://github.com/apache/flink-agents/pull/1155

   <!--
   * Thank you very much for contributing to Flink Agents.
   * Please add the relevant components in the PR title. E.g., [api], 
[runtime], [java], [python], [hotfix], etc.
   -->
   
   <!-- Please link the PR to the relevant issue(s). Hotfix doesn't need this. 
-->
   Linked issue: https://github.com/apache/flink-agents/issues/1016
   
   ### Purpose of change
   
   <!-- What is the purpose of this change? -->
   Simplify the recovery matching model for durable execution from the 
two-field` (functionId, argsDigest) `to a single `functionId `field, making the 
Java and Python APIs consistent. On the Python side, by embedding the args 
digest inside the functionId string (in the format `module.qualname::digest`), 
the automatic deduplication capability based on function + args is preserved, 
maintaining the language's own characteristics. At the same time, assign a 
unique durable ID `(tool-call:{llm_id}`) to each tool call of `ToolCallAction`, 
avoiding recovery matching confusion between multiple tool calls.
   
   ### Behavioral Semantics
   
   <!-- For a non-trivial code change whose implementation is largely 
AI-assisted: interaction decisions, behavioral contracts, and failure behavior. 
See `contribution-guides/ai-assisted-pr.md`. Remove this heading and this 
comment otherwise. -->
   **Recovery Matching Model Change:** Previously, `CallResult` used two 
independent fields, `functionId` and `argsDigest`, to match call sites during 
replay. Now, `functionId` itself carries the complete matching 
semantics—provided by `DurableCallable.getId()` on the Java side, and returned 
as a single string by `durable_identity_for_call()` on the Python side. This 
eliminates the complexity for callers of having to manage two identity fields 
separately.
   
   **Python's args digest preservation strategy:** When there is no explicit 
`durable_id`, `durable_identity_for_call()` returns a single string in the 
format `{function_id}::{args_digest}`. This means the behavioral semantics on 
the Python side are completely equivalent to before (the same function + 
different args will still generate different identities), but the interface is 
simplified to a single `str` return type.
   
   **ToolCallAction Uniqueness:** On the Java side, `TOOL_CALL_DURABLE_ID` is 
changed from the constant `"tool-call"` to `"tool-call:" + id`. On the Python 
side, all three `durable_execute` calls pass 
`durable_id=f"tool-call:{execution.id}"`. The durable log entries for each tool 
call are now independent of each other, and the recovery of different tools in 
parallel tool calls (parallel batch) will not interfere with each other.
   
   **Forward Compatibility:** Add `@JsonIgnoreProperties(ignoreUnknown = true)` 
to `CallResult` to ensure that serialized data containing the old `argsDigest` 
field will not throw an exception during deserialization.
   
   **Java-Python Bridge Layer:** The arrays returned by `getCallResultFieldsAt` 
/ `getCurrentCallResultFields` are reduced from a 5-tuple `[functionId, 
argsDigest, status, result, exception]` to a 4-tuple `[functionId, status, 
result, exception]`. On the Python side, `_PersistedCallResult` is 
synchronously unpacked into 4 elements.
   
   ### Tests
   
   <!-- How is this change verified? -->
   - Java: All 6 migration-related test classes passed (~95 test cases), 
including `ActionStateSerdeTest` (20), `ActionStateTest` (17), 
`DurableExecutionContextTest` (17), 
`JavaRunnerContextImplDurableExecuteAsyncTest` (19), 
`RunnerContextImplDurableExecuteTest` (17), and `ActionExecutionOperatorTest` 
(56).
   - Python: `test_flink_runner_context_reconcilable.py` (~50+) and 
`test_tool_call_action.py` (41) all passed. The Mock `_Context`'s 
`durable_execute` / `durable_execute_async` performs `kwargs.pop("durable_id", 
None)` filtering to ensure the newly added `durable_id` keyword argument is not 
passed through to the tool function under test.
   
   ### API
   
   <!-- Does this change touches any public APIs? -->
   no API
   
   ### Documentation
   
   <!-- Do not remove this section. Check the proper box only. -->
   
   - [ ] `doc-needed` <!-- Your PR changes impact docs -->
   - [x] `doc-not-needed` <!-- Your PR changes do not impact docs -->
   - [ ] `doc-included` <!-- Your PR already contains the necessary 
documentation updates -->
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   <!-- Do not remove this section. Check the proper box only. -->
   
   - [x] Yes
   - [ ] No
   
   Generated-by: cursor (deepseek-v4-pro)
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to