fix(responses): project collaboration through a plaintext shim - #273
fix(responses): project collaboration through a plaintext shim#273Menci wants to merge 49 commits into
Conversation
|
Holding this in draft: nothing has exercised it yet. The audit that shaped this PR established that outside the Everything here is therefore derived from the published contract rather than from observed behaviour, and it has never been driven end to end by a real client. That is the gap to close before this ships: point The contract-derived parts are the ones worth the most scrutiny in review: the per-action argument schemas (only |
Describe Codex encrypted function arguments and structured encrypted tool outputs in the Responses protocol. Reject encrypted output explicitly at translated target boundaries so opaque state cannot be flattened or dropped.
Authenticate collaboration arguments across their move into agent_message input and make encrypted inter-agent and tool-output state require its producing target. Centralize opaque Responses locations and keep streamed argument deltas, done events, item snapshots, and terminal resources coherent.
Accept the complete Responses tool-output union at the Messages translator boundary so encrypted content reaches its explicit unsupported-input guard.
Remove a refusal branch that the Responses function-output protocol cannot produce after the tool-output union gained its complete encrypted-content shape.
Keep opaque-location reconstruction type-safe across open agent content and structured tool outputs, adapt Copilot image compression to the complete output union, and narrow the round-trip fixture to a legal input status.
Widen the image-compression test accessor alongside the production Responses tool-output union.
Treat output items with encrypted collaboration arguments or structured encrypted output as carrier-capable first items, avoiding an unrelated synthetic prefix. Keep the plaintext collaboration fixture focused on its unchanged call.
Model mandatory upstream continuity separately from model-bound continuation state. Inter-agent and encrypted tool-output ciphertext can follow child model overrides within the producing upstream while rejecting every other upstream.
Document the complete opaque-location inventory, cross-shape Codex collaboration carrier, upstream-only requirements, coherent streaming rewrites, and explicit translation rejection for encrypted tool output. Align the architecture guide and candidate resolution contract.
Treat every absent, null, or non-empty encrypted_function_args marker as encrypted for collaboration calls; only the explicit empty list is plaintext. Cover the observed absent form and the declared non-empty form.
Make the opaque-location module the single owner of natural and synthetic Responses carrier domains so ingress and egress cannot drift.
Preserve global event order while buffering encrypted collaboration arguments, reject malformed encrypted calls, accept pre-deploy agent-message carrier domains, require a native Responses candidate on the producing upstream, and mark Messages-translated collaboration calls explicitly plaintext.
Align the affinity and translation contracts with review repairs: encrypted tool state stays on a native Responses model at its producing upstream, and ingress accepts the prior agent-message carrier domain during deployment.
Attach pinned Codex references to the vendor-defined action subset shared by affinity and Messages translation.
Resolve buffered collaboration arguments from done items or terminal snapshots, preserve globally interleaved event order, and suppress unresolved ciphertext deltas on failed, errored, or truncated streams.
Resolve terminal collaboration calls by output index and required call_id, and reject malformed authoritative arguments before any buffered ciphertext delta reaches the client.
Order local affinity imports before parent modules and remove the superseded Messages translator type import.
Replace inter-agent ciphertext affinity with a request-scoped ordinary namespace membrane. Native Responses upstreams receive plaintext collaboration schemas and history; Codex receives the reserved collaboration identity plus encrypted_function_args:[] so child messages use input_text. Remove encrypted agent-message handling and argument buffering from affinity and Copilot item IDs.
Model namespace tools through the hosted-tool shape and keep nullable request tool arrays from leaking into response resources.
Remove inter-agent ciphertext affinity suites and cover the plaintext collaboration namespace membrane across request schemas, history, streamed arguments, done items, terminal resources, echoed tools, translated targets, and duplicate namespaces.
Assert that gateway affinity and Copilot item-id handling leave legacy agent-message content opaque while plaintext collaboration owns all newly generated agent traffic.
Verify deferred tool inventories, schema decryption, response restoration, exact plaintext stream arguments, history replay through fresh aliases, HTTP integration, and the remaining structured encrypted tool-output affinity.
Make the HTTP integration's raw namespace schema assertion explicit at the open tool-union boundary.
Describe the plaintext namespace membrane, exact Codex plaintext marker, native and translated target behavior, history persistence, and the removal of agent-message affinity and item-id carriers.
Use a deterministic collision-safe namespace, restore shared invocation state between server-tool turns, cover deferred tool inventories and null snapshots, reject explicit encrypted markers, strip Messages schemas, and exclude Chat Completions targets that cannot represent namespace tools.
Assert the collaboration schema after narrowing the translated Messages tool union.
Select candidates after Stateful hydration, exclude translated targets for unrepresentable deferred or allowed-tool forms, honor namespace-qualified Messages choices, reject explicit encrypted history, preserve snapshot nulls, and keep alias projection scoped to each inner server-tool turn.
Import the Responses choice contract used by the plaintext namespace fixture.
Evaluate collaboration after Stateful hydration, route deferred inventories only to native Responses, exclude unrepresentable Messages choices, strip Messages schemas, validate explicit encrypted history, and document translated legacy behavior.
Read the open namespace extension through the JSON-record boundary after merging the latest protocol contracts.
Resolve the reserved namespace as collaboration_2, collaboration_3, and so on, matching ordinary client collision behavior without exposing a gateway-specific name on either wire.
Rewrite exact namespace-qualified function names in native tool choices and allowed-tool entries in both directions, including collision-suffixed aliases.
Rewrite collaboration-qualified names only for function choices while preserving unrelated dotted custom and namespace entries.
Centralize native and Messages namespace lowering, response restoration, target eligibility, tool-choice mapping, and payload lifecycle in a collaboration shim. Remove collaboration-specific behavior from the generic Messages translator and keep Chat candidates out when namespace semantics are not representable.
Keep plaintext markers and schema semantics exclusively in the collaboration shim. Generic Messages translation now flattens and restores namespaces without knowing collaboration actions.
Echo qualified and unrelated allowed-tool entries through the native snapshot fixture, and keep the Messages projection case on its representable automatic choice.
Activate the plaintext collaboration membrane for history-only function calls so target selection and marker validation cannot bypass it. Document Codex's provider-dependent replay normalization and cover the replay-only shape.
Project collaboration once around every upstream turn and preserve the interceptor chain's one-way context mutation invariant. Keep the plaintext alias stable as the server-tool loop accumulates input, then restore only the client-facing event stream.
74e22e7 to
3f546c5
Compare
# Conflicts: # AGENTS.md # docs/AFFINITY.md # docs/RESOLUTION.md # docs/TRANSLATION.md
Keep the plaintext collaboration shim independent from Copilot's existing agent-message item-ID carrier behavior. Restore the provider implementation and its tests exactly to main.
Make the collaboration shim a target-independent source projection. Move namespace lowering into shared translation code, add Chat Completions round-trip support, and keep native-only payload selection based on generic Responses features.
Keep candidate selection limited to endpoint availability. Let each translator reject unsupported Responses input and tool-choice shapes at its owning boundary, while preserving namespace-qualified function choices.
|
I am Claude Code (Opus 5), running for the maintainer. Flagging a defect found while
Two concrete consequences, both on carriers that are already sitting in client conversation
Both are exactly the impact #456 describes, arriving through our own change rather than The narrowing is the bug, and it is the second time this file's slot inventory has been
I am picking this up now. |
Extracting the opaque slot inventory dropped the agent message's content.N.encrypted_content carrier from every side at once: the ingress scan, the egress wrap, the synthetic-carrier append, and canCarryAffinity. The protocol still carries that content variant, so the slot did not stop existing — we stopped looking at it. Carriers already held in client conversation history therefore replayed unscanned, which meant unwrapped: a synthetic carrier of pure gateway ciphertext, and ordinary carriers still wearing our trailer, both bound for a third-party upstream, with the routing pin they encode lost on the way. Reported against this branch in issue #456. The inventory now enumerates each slot once, as a path, and reading, rewriting, growing and removing a carrier all derive from that single enumeration; egress no longer keeps its own item-type list, and a tool output stays a slot we may rewrite but never grow. The round-trip test walks every item type and slot, and asserts egress actually changed the value — without that the previous agent message round trip passed while nothing wrapped it at all, since an unwrapped value also survives a round trip unchanged.
|
Fixed in 9ff9714, pushed to this branch. The inventory now enumerates each slot once as a path, and reading, rewriting, growing and removing a carrier all derive from that single enumeration — Worth recording: the existing Verified: lint clean, typecheck clean, 5485 tests pass. |
Codex exposes a plaintext collaboration dispatch path to non-OpenAI providers, but Copilot reserves the exact
collaborationnamespace and requires its encrypted schema. Forwarding that client contract unchanged therefore makes Copilot produce opaque arguments that another upstream cannot consume.This PR makes collaboration a reversible Responses source-protocol membrane:
collaboration, encrypted message schemas, andencrypted_function_args: []on plaintext message actions.collaboration_2, then_3, …) whose message schemas omitencrypted: true.OpenAI.The collaboration shim wraps the complete server-tool loop, so every internal turn stays in one plaintext alias domain and the client stream is restored exactly once. Context mutation remains one-way, matching the interceptor contract.
Collaboration arguments and
agent_messagecontent are no longer affinity carriers. The gateway does not inspect or patch inter-agent ciphertext and does not require a subagent turn to land on the same upstream as its parent. Existing structured encrypted tool-output and reasoning carriers remain scoped to their native Responses contracts.The Copilot item-id membrane likewise treats plaintext agent messages as public items and no longer embeds provider-private affinity into their content.
Evidence
encrypted: truefrom the reservedcollaborationschema, while ordinarycollaboration_2/collaboration_3namespaces accept the same plaintext arguments and replay.collaborationand an explicit emptyencrypted_function_argslist.OpenAI; the ingress projection accepts this plaintext replay form while rejecting explicit null or non-empty encrypted markers.The previous hosted
multi_agentimplementation on this PR was useful design archaeology for action vocabulary and collision handling, but it was not the protocol authority. Its scheduler, checkpoint format, andresponse.injectserver implementation are not part of the resulting design.Verification
pnpm run typecheckpnpm run lintwindow.localStorage(getItem is not a function)