Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/responses/code-mode-helper-compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ export function compileCodeModeHelperInput(
// is an apply_patch wrapper and is not an `exec` fallback field, and the recognizer already
// declines it under `exec`; reading it here would compile a body that recognition rejected,
// which is exactly the drift a second, looser unwrap introduces.
const bodyToolName = wireToolName ?? helperName;
const normalizedBodyToolName = bodyToolName.startsWith("default.")
? bodyToolName.slice("default.".length)
: bodyToolName;
Comment on lines +46 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update every structure owner for the changed Responses behavior

This changes the fallback-body grammar under src/responses/, but none of the six documents assigned to that area in structure/INDEX.md are updated. In particular, structure/runtime.md still says that only bare exec and apply_patch calls recover alternate body fields, which now contradicts the new default.apply_patch behavior. Update all mapped owners—or narrow the ownership map if some should not own this contract—so the documented transport behavior matches the implementation.

AGENTS.md reference: src/AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

const patch = normalizeApplyPatchDelimiters(
unwrapFreeformToolInput(argumentsText, wireToolName ?? helperName),
unwrapFreeformToolInput(argumentsText, normalizedBodyToolName),
);
return `const result = await tools.apply_patch(${JSON.stringify(patch)});\ntext(result);`;
}
Expand Down
2 changes: 1 addition & 1 deletion structure/providers/chat-compat.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ compatibility layer. Its endpoint profile and privacy boundary are specified in

Chat models sometimes return a freeform call body under a common alternate field or wrap the whole
body in a Markdown fence. Restoration in `src/responses/apply-patch-envelope.ts` is deliberately
narrow: only bare `exec` and `apply_patch` accept one recognized alternate field or one complete
narrow: only bare or `default.`-prefixed `exec` and `apply_patch` accept one recognized alternate field or one complete
outer fence, while ambiguous wrappers and provider-owned freeform grammars remain byte-exact.

Kiro groups only consecutive original-message tool results whose raw call ID exactly matches
Expand Down
2 changes: 1 addition & 1 deletion structure/providers/kiro.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ reserves the private completion tool. Meta Muse 64-character MCP aliases live in

Kiro shares the Responses freeform restoration boundary in
`src/responses/apply-patch-envelope.ts`: contractual `input` wrappers are unwrapped, while alternate
field and outer-fence recovery is limited to unambiguous bare `exec` and `apply_patch` bodies.
field and outer-fence recovery is limited to unambiguous bare or `default.`-prefixed `exec` and `apply_patch` bodies.

Kiro refuses structured output and tolerates every other Responses `text` member. `text.format`
of type `json_schema` or `json_object` is a contract the CodeWhisperer wire cannot honour, so the
Expand Down
2 changes: 1 addition & 1 deletion structure/providers/xai-grok.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Shared parsing and streaming follow the [request-copy](../transports/byte-accoun

Grok's Responses path shares `src/responses/apply-patch-envelope.ts` for freeform restoration.
The declared `input` field remains authoritative; alternate-field and outer-fence recovery is
limited to unambiguous bare `exec` and `apply_patch` calls and does not rewrite foreign grammars.
limited to unambiguous bare or `default.`-prefixed `exec` and `apply_patch` calls and does not rewrite foreign grammars.

Grounded in the open-sourced official client (xai-org/grok-build); unit + evidence:
`devlog/_fin/260716_grok_build_hardening/`.
Expand Down
3 changes: 2 additions & 1 deletion structure/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ On `error` / incomplete / stall / EOF — and when assembled non-freeform tool a
an open tool call is cancelled as `status: "incomplete"` without `function_call_arguments.done`, so
the client never sees a completed call ahead of `response.failed` / `response.incomplete`.
At the freeform boundary, `src/responses/apply-patch-envelope.ts` unwraps the contractual `input`
field for every tool. Only bare `exec` and `apply_patch` calls may recover one recognized alternate
field for every tool. Only bare or `default.`-prefixed `exec` and `apply_patch` calls may recover
one recognized alternate
body field or remove one complete outer Markdown fence; ambiguous alternate fields and every other
freeform grammar pass through unchanged.

Expand Down
2 changes: 1 addition & 1 deletion structure/transports/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ discarded to manufacture a bare name.

Function-call wrappers around freeform bodies are restored by
`src/responses/apply-patch-envelope.ts`. The declared `input` field is authoritative. For bare
`exec` and `apply_patch`, one tool-specific alternate field or one complete outer Markdown fence
`exec` and `apply_patch` (including their `default.`-prefixed provider aliases), one tool-specific alternate field or one complete outer Markdown fence
is recoverable because the wrapper is otherwise unusable; two alternate fields are ambiguous and
therefore remain untouched. Foreign freeform grammars never receive that compatibility rewrite.

Expand Down
4 changes: 4 additions & 0 deletions tests/adapters/openai/openai-chat-dangling-toolcalls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const provider: OcxProviderConfig = {
baseUrl: "https://example.test/v1",
apiKey: "sk-test",
authMode: "key",
// The wire role folds to `system` unless a destination is recorded as accepting
// `developer`; this suite is about tool-result repair ordering, so it declares the
// destination rather than asserting the default.
foldDeveloperRoleToSystem: false,
};

interface ChatMsg {
Expand Down
4 changes: 4 additions & 0 deletions tests/responses/chat-inline-document-bytes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const chatProvider: OcxProviderConfig = {
adapter: "openai-chat",
baseUrl: "https://gateway.example.internal/v1",
apiKey: "k",
// The wire role folds to `system` unless a destination is recorded as accepting
// `developer`; the document test asserts the role a turn keeps, so it declares the
// destination rather than asserting the default.
foldDeveloperRoleToSystem: false,
};
const anthropicProvider = {
adapter: "anthropic",
Expand Down
10 changes: 10 additions & 0 deletions tests/responses/responses-code-mode-patch-compile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ describe("code-mode apply_patch compiles the body recognition accepted", () => {
expect(compileAsBridge(JSON.stringify({ patch: PATCH }))).toBeUndefined();
});

test("a default.apply_patch alias keeps the native apply_patch vocabulary", () => {
for (const key of ["patch", "content"]) {
expect(compileCodeModeHelperInput(
JSON.stringify({ [key]: PATCH }),
"default.apply_patch",
"default.apply_patch",
)).toBe(EXPECTED);
}
});

test("a normal code-mode JavaScript body is left alone", () => {
for (const body of [
'const result = await tools.exec_command({ cmd: "ls" });\ntext(result);',
Expand Down
Loading