Repository navigation
E.2: ToolCall -> Static/Dynamic enum via private wire (D25/D26; phase 1E; stacked on #25) - #26
Open
cunninghamcard-bit wants to merge 6 commits into
Open
cunninghamcard-bit wants to merge 6 commits into
cunninghamcard-bit wants to merge 6 commits into
Conversation
fixtures/v4/enum-state/: JSONL samples for ToolCall, ToolResult, RawToolCall and StreamPart/TextStreamPart tool-input-start (absent / explicit false / true, providerExecuted true/false/absent, invalid+error, D26 rejected inputs, RFC-0042:84-91 vectors as RawToolCall input), normalized/ per A7 D25, and baseline/ recorded at 8455db9. aimux-core/tests/enum_state_wire_test.rs compares serialize(deserialize(line)) byte for byte with the baseline and checks normalized/ is a round-trip fixed point. A7 copied verbatim into docs/amendments/.
New aimux_core::tool::RawArguments newtype, serde(transparent) and #[ts(as = "String")] on the field, so the wire and RawToolCall.ts are unchanged. Not an enum (arcships#200:2724). Provides new/as_str/into_string/push_str, From<String|&str>, Into<String>, Deref<str>, AsRef<str>, Display and PartialEq with str/String/serde_json::Value (parity with String). Call sites in core, provider-utils, providers and tests converted with .into() / .to_string(); no behaviour change. Enum-state samples still match the 8455db9 baseline byte for byte.
ToolCall = Static(StaticToolCall) | Dynamic(DynamicToolCall { validity:
Valid | Invalid { error } }), serialized through the private ToolCallWire
(the old struct) with serde(try_from/into) and #[ts(as = "ToolCallWire")];
ToolCall.ts is unchanged. D25: static writes no dynamic, dynamic writes
true, invalid only as true with its error, providerExecuted passed through.
D26: invalid without dynamic:true or without error fails conversion.
Accessors (tool_call_id/tool_name/input/provider_executed/provider_metadata/
is_dynamic/is_invalid/error); parsed_tool_call_arguments and
response_tool_call_input take &ToolCall and match. Consumers converted.
tool_call.jsonl gains the RFC-0042:84-93 core values (string "Tokyo", string
"{\"x\":1}" kept a string, number, bool, null, last-wins {"a":2}, 100.0)
and empty text / {"a": as invalid dynamic calls with an error (never {}).
tool_call_semantic.jsonl holds the non-canonical spellings (duplicate key,
1e2), compared by JSON semantics. check_normalized asserts line counts before
zipping; baseline_equals_samples is skipped in bless mode. Baseline re-blessed
at 8455db9 (existing lines unchanged; new lines appended).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1E unit E.2 (A7 row
ToolCall; D2, D25, D26). Stacked on #25 (E.1) and #24 (E.0), so this diff includes them until they merge. The E.2-only change is commit 55699c0; the merge commit after it only brings in the E.0 review fixes (684c8b9). It is independent of the 1R stack (#19–#23).Change (
aimux-core/src/tool.rs)pub enum ToolCall { Static(StaticToolCall), Dynamic(DynamicToolCall) }.DynamicToolCallhasvalidity: ToolCallValidity=Valid | Invalid { error: AiMuxError }, so an invalid call cannot exist without its error.StaticToolCallcannot be invalid at all.ToolCallWire.ToolCallserializes through it with#[serde(try_from = "ToolCallWire", into = "ToolCallWire")]and#[ts(export, as = "ToolCallWire")]. The container-levelasin ts-rs 12 keeps the TS nameToolCalland inlines the wire shape, soToolCall.tshas zero diff. The extended explanation is written as//comments, because the///line is the generated TS doc.parse-tool-call.ts:126-128,276,280-287): static calls write nodynamic, so an inputdynamic:falseis dropped. Dynamic calls writedynamic:true.invalidis written only astrue, together witherror.providerExecutedstaysOption<bool>and is passed through.try_fromreturns an error forinvalid:truewithoutdynamic:true, and forinvalid:truewithouterror.tool_call_id(),tool_name(),input()/input_mut(),provider_executed(),provider_metadata()/provider_metadata_mut(),is_dynamic(),is_invalid(),error().DynamicToolCall,StaticToolCallandToolCallValidityare re-exported.openai_output::parsed_tool_call_argumentsandresponse_messages::response_tool_call_inputnow take&ToolCalland match on it, as A7 specifies.parse_tool_callbuilds the variants directly..dynamic/.invalidin tests becameis_dynamic()/is_invalid()). No behaviour change beyond D25/D26.Tests (
aimux-core/tests/enum_state_wire_test.rs)tool_call_samples_match_normalized: everytool_call.jsonlsample serializes to itsnormalized/line byte for byte, and the normalized lines are a fixed point. This includes the RFC-0042 core-value rows from E.0: enum-state shared wire samples + 8455db9a baseline; add A7 (phase 1E) #24.tool_call_absent_and_false_are_the_same_variant: absent vsdynamic:false, absent vsinvalid:false, anddynamic:truevsdynamic:true, invalid:falsegive the same variant and the same JSON.tool_call_provider_executed_is_passed_through:providerExecutedtrue / false / absent round-trips byte for byte on static, dynamic and invalid calls.tool_call_rejected_samples_fail_conversion: all 3 D26 rows from E.0'stool_call_rejected.jsonlfail conversion.invalid_tool_call_carries_its_error.tool_call_semantic_samples_match_by_json_value(from E.0: enum-state shared wire samples + 8455db9a baseline; add A7 (phase 1E) #24) still passes on the enum.tool_callbaselines stay as the 8455db9 record. ToolCall is now compared withnormalized/, as A7 specifies.Shared acceptance
git diff --stat -- fixtures/ contract-tests/fixtures/ aimux-providers/tests/cassettes/against E.1 is empty.gen_ts_types.py --check: up to date, andbindings/has zero diff.untagged,flattenor tag field.grep -nE 'pub (dynamic|invalid|error):' aimux-core/src/tool.rshits onlyRawToolCall.dynamicandToolResult.dynamic; nothing on ToolCall (the wire struct is private).Results vs R.0 (local linux x64; test names confirmed in the log)
Go/Java/Kotlin/Swift/Flutter were not run locally.