Skip to content
Merged
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
4 changes: 4 additions & 0 deletions docs-site/src/content/docs/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ of the HTTP retry loop.

- Builds Kiro `conversationState`, maps Codex tools and tool results, and sends image blocks supported
by the Kiro wire.
- Treats a client `parallel_tool_calls: true` value as permission rather than a wire requirement.
Kiro remains serialized: the routed catalog advertises no parallel-tool capability and the
adapter sends no parallel-control field upstream, but ordinary Codex tool turns are not rejected
solely because the client permits parallel calls.
- Decodes `application/vnd.amazon.eventstream`, reconstructs text/thinking/tool events, detects
truncated tool JSON, and estimates usage because the upstream does not return token counts.
- Uses the configured `baseUrl` verbatim when it is custom. A canonical
Expand Down
3 changes: 0 additions & 3 deletions src/adapters/kiro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,6 @@ function validateKiroCapabilities(parsed: OcxParsedRequest): void {
if (choice !== undefined && choice !== "auto" && choice !== "none") {
throw new Error("Kiro supports only automatic tool choice or tool_choice:none");
}
if (parsed.options.parallelToolCalls === true) {
throw new Error("Kiro does not support parallel tool calls");
}
if (parsed.options.serviceTier !== undefined) {
throw new Error("Kiro does not support service tiers");
}
Expand Down
16 changes: 16 additions & 0 deletions structure/04_transports-and-sidecars.md
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,22 @@ Grounded in the open-sourced official client (xai-org/grok-build); unit + eviden
`fetchWithHeaderTimeout` takes an executor so provider fetch wrappers stay inside the
timeout race.

## Kiro client parallel-tool hint

Kiro's wire remains serialized even when an OpenAI Responses client sends
`parallel_tool_calls: true`. That request field is permissive: it allows parallel calls but does not
require the routed transport to expose a matching flag. The Kiro catalog therefore continues to
advertise `supports_parallel_tool_calls: false`, and the adapter emits no parallel-control field,
while accepting the client hint and translating the ordinary tool catalog normally.

[Decision Log]
- 목적과 의도: Keep current Codex clients usable with Kiro without claiming or inventing parallel execution on the CodeWhisperer wire.
- 기존 구현 및 제약 조건: Codex can send `parallel_tool_calls: true` even for catalog rows that advertise false; Kiro has no verified parallel-control request field and serializes tool execution.
- 검토한 주요 대안: Reject the client hint, rewrite it to false before routing, or accept it as permission while leaving the Kiro wire unchanged.
- 선택한 방식: Accept either request value, preserve the parsed client intent internally, and omit all parallel-control fields from the Kiro payload.
- 다른 대안 대신 이 방식을 선택한 이유: Rejection interprets permission as a requirement and blocks valid turns, while rewriting shared request state hides caller intent and can affect later policy or diagnostics.
- 장점, 단점 및 영향: Codex tool turns reach Kiro again and the adapter contract stays honest; Kiro still cannot produce true parallel tool batches through this transport.

## Kiro reasoning round-trip (`redactedContent`)

Kiro never returns plaintext reasoning for its **GPT-5.6 family** (`gpt-5.6-sol`, `-terra`,
Expand Down
44 changes: 43 additions & 1 deletion tests/kiro-adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { saveCredential } from "../src/oauth/store";
import { normalizeKiroModelId } from "../src/providers/kiro-models";
import { configuredReasoningEfforts, mapReasoningEffort } from "../src/reasoning-effort";
import { PROVIDER_REGISTRY } from "../src/providers/registry";
import { parseRequest } from "../src/responses/parser";
import type { OcxParsedRequest, OcxProviderConfig } from "../src/types";

const origHome = process.env.HOME;
Expand Down Expand Up @@ -835,7 +836,6 @@ describe("kiro adapter — buildRequest", () => {
for (const options of [
{ toolChoice: "required" },
{ toolChoice: { name: "bash" } },
{ parallelToolCalls: true },
{ serviceTier: "priority" },
]) {
await expect(createKiroAdapter(provider).buildRequest({
Expand All @@ -853,6 +853,48 @@ describe("kiro adapter — buildRequest", () => {
const current = JSON.parse((await createKiroAdapter(provider).buildRequest(none)).body).conversationState.currentMessage.userInputMessage;
expect(current.userInputMessageContext?.tools).toBeUndefined();
});

test("accepts Codex's permissive parallel-tool hint while keeping the Kiro wire serialized", async () => {
const parsed = parseRequest({
model: "kiro/claude-haiku-4.5",
input: "test",
stream: true,
parallel_tool_calls: true,
tools: [{
type: "function",
name: "bash",
description: "Run a shell command",
parameters: { type: "object" },
}],
});
expect(parsed.options.parallelToolCalls).toBe(true);

const payload = JSON.parse((await createKiroAdapter(provider).buildRequest(parsed)).body) as {
parallel_tool_calls?: boolean;
parallelToolCalls?: boolean;
conversationState: {
parallel_tool_calls?: boolean;
parallelToolCalls?: boolean;
currentMessage: {
userInputMessage: {
userInputMessageContext?: {
parallel_tool_calls?: boolean;
parallelToolCalls?: boolean;
tools?: Array<{ toolSpecification?: { name?: string } }>;
};
};
};
};
};
const context = payload.conversationState.currentMessage.userInputMessage.userInputMessageContext;
expect(context?.tools?.some(tool => tool.toolSpecification?.name === "bash")).toBe(true);
expect(payload.parallel_tool_calls).toBeUndefined();
expect(payload.parallelToolCalls).toBeUndefined();
expect(payload.conversationState.parallel_tool_calls).toBeUndefined();
expect(payload.conversationState.parallelToolCalls).toBeUndefined();
expect(context?.parallel_tool_calls).toBeUndefined();
expect(context?.parallelToolCalls).toBeUndefined();
});
});

describe("kiro adapter — native and emulated reasoning effort", () => {
Expand Down
Loading