Compare commits

...

2 Commits

Author SHA1 Message Date
acp-release-bot[bot]
9258652169 chore(main): release 0.34.0 (#666)
🤖 I have created a release *beep* *boop*
---


##
[0.34.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.33.1...v0.34.0)
(2026-05-15)


### Features

* add bedrock gateway authentication
([#665](https://github.com/agentclientprotocol/claude-agent-acp/issues/665))
([002c63a](002c63a78b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
2026-05-15 20:24:14 +02:00
Aleksandr Suhinin
002c63a78b feat: add bedrock gateway authentication (#665) 2026-05-15 20:20:49 +02:00
6 changed files with 99 additions and 18 deletions

View File

@@ -1,3 +1,3 @@
{
".": "0.33.1"
".": "0.34.0"
}

View File

@@ -1,5 +1,12 @@
# Changelog
## [0.34.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.33.1...v0.34.0) (2026-05-15)
### Features
* add bedrock gateway authentication ([#665](https://github.com/agentclientprotocol/claude-agent-acp/issues/665)) ([002c63a](https://github.com/agentclientprotocol/claude-agent-acp/commit/002c63a78b844c168d3dfc744cf408362a6adf97))
## [0.33.1](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.33.0...v0.33.1) (2026-05-07)

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@agentclientprotocol/claude-agent-acp",
"version": "0.33.1",
"version": "0.34.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@agentclientprotocol/claude-agent-acp",
"version": "0.33.1",
"version": "0.34.0",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "0.21.0",

View File

@@ -3,7 +3,7 @@
"publishConfig": {
"access": "public"
},
"version": "0.33.1",
"version": "0.34.0",
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
"main": "dist/lib.js",
"types": "dist/lib.d.ts",

View File

@@ -232,6 +232,8 @@ type GatewayAuthMeta = {
};
};
type GatewayAuthRequest = AuthenticateRequest & { _meta?: GatewayAuthMeta };
/**
* Extra metadata that the agent provides for each tool_call / tool_update update.
*/
@@ -476,7 +478,7 @@ export class ClaudeAcpAgent implements Agent {
backgroundTerminals: { [key: string]: BackgroundTerminal } = {};
clientCapabilities?: ClientCapabilities;
logger: Logger;
gatewayAuthMeta?: GatewayAuthMeta;
gatewayAuthRequest?: GatewayAuthRequest;
constructor(client: AgentSideConnection, logger?: Logger) {
this.sessions = {};
@@ -503,6 +505,17 @@ export class ClaudeAcpAgent implements Agent {
},
};
const gatewayBedrockAuthMethod: AuthMethod = {
id: "gateway-bedrock",
name: "Custom model gateway",
description: "Use a custom gateway to authenticate and access models",
_meta: {
gateway: {
protocol: "bedrock",
},
},
};
const supportsTerminalAuth = request.clientCapabilities?.auth?.terminal === true;
const supportsMetaTerminalAuth = request.clientCapabilities?._meta?.["terminal-auth"] === true;
@@ -613,7 +626,10 @@ export class ClaudeAcpAgent implements Agent {
title: "Claude Agent",
version: packageJson.version,
},
authMethods: [...terminalAuthMethods, ...(supportsGatewayAuth ? [gatewayAuthMethod] : [])],
authMethods: [
...terminalAuthMethods,
...(supportsGatewayAuth ? [gatewayAuthMethod, gatewayBedrockAuthMethod] : []),
],
};
}
@@ -690,8 +706,8 @@ export class ClaudeAcpAgent implements Agent {
}
async authenticate(_params: AuthenticateRequest): Promise<void> {
if (_params.methodId === "gateway") {
this.gatewayAuthMeta = _params._meta as GatewayAuthMeta | undefined;
if (_params.methodId === "gateway" || _params.methodId === "gateway-bedrock") {
this.gatewayAuthRequest = _params as GatewayAuthRequest;
return;
}
throw new Error("Method not implemented.");
@@ -1864,7 +1880,7 @@ export class ClaudeAcpAgent implements Agent {
env: {
...process.env,
...userProvidedOptions?.env,
...createEnvForGateway(this.gatewayAuthMeta),
...createEnvForGateway(this.gatewayAuthRequest),
// Opt-in to session state events like when the agent is idle
CLAUDE_CODE_EMIT_SESSION_STATE_EVENTS: "1",
},
@@ -1948,7 +1964,7 @@ export class ClaudeAcpAgent implements Agent {
if (
shouldHideClaudeAuth() &&
initializationResult.account.subscriptionType &&
!this.gatewayAuthMeta
!this.gatewayAuthRequest
) {
throw RequestError.authRequired(
undefined,
@@ -2137,15 +2153,25 @@ function snapshotFromUsage(usage: {
};
}
function createEnvForGateway(gatewayMeta?: GatewayAuthMeta) {
if (!gatewayMeta) {
function createEnvForGateway(request?: GatewayAuthRequest) {
if (!request?._meta) {
return {};
}
const customHeaders = Object.entries(request._meta.gateway.headers)
.map(([key, value]) => `${key}: ${value}`)
.join("\n");
if (request.methodId === "gateway-bedrock") {
return {
CLAUDE_CODE_USE_BEDROCK: "1",
AWS_BEARER_TOKEN_BEDROCK: "",
ANTHROPIC_BEDROCK_BASE_URL: request._meta.gateway.baseUrl,
ANTHROPIC_CUSTOM_HEADERS: customHeaders,
};
}
return {
ANTHROPIC_BASE_URL: gatewayMeta.gateway.baseUrl,
ANTHROPIC_CUSTOM_HEADERS: Object.entries(gatewayMeta.gateway.headers)
.map(([key, value]) => `${key}: ${value}`)
.join("\n"),
ANTHROPIC_BASE_URL: request._meta.gateway.baseUrl,
ANTHROPIC_CUSTOM_HEADERS: customHeaders,
ANTHROPIC_AUTH_TOKEN: "", // Must be specified to bypass claude login requirement
};
}

View File

@@ -53,6 +53,9 @@ describe("authorization", () => {
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "gateway" }),
);
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "gateway-bedrock" }),
);
});
it("gateway auth offered when client advertises auth._meta.gateway capability", async () => {
@@ -65,11 +68,20 @@ describe("authorization", () => {
} as any,
});
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "gateway" }),
expect.objectContaining({
id: "gateway",
_meta: { gateway: { protocol: "anthropic" } },
}),
);
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({
id: "gateway-bedrock",
_meta: { gateway: { protocol: "bedrock" } },
}),
);
});
it("uses gateway env after gateway auth", async () => {
it("uses gateway env after anthropic gateway auth", async () => {
const [agent, mockQuery] = await createAgentMock();
const initializeResponse = await agent.initialize({
@@ -115,6 +127,42 @@ describe("authorization", () => {
);
});
it("uses gateway env after gateway auth", async () => {
const [agent, mockQuery] = await createAgentMock();
await agent.initialize({
protocolVersion: 1,
clientCapabilities: {
auth: { terminal: true, _meta: { gateway: true } },
} as any,
});
await agent.authenticate({
methodId: "gateway-bedrock",
_meta: {
gateway: { baseUrl: "https://gateway.example", headers: { "custom-header": "test" } },
},
});
await agent.newSession({
cwd: "testRoot",
mcpServers: [],
});
expect(mockQuery).toHaveBeenCalledWith(
expect.objectContaining({
options: expect.objectContaining({
env: expect.objectContaining({
CLAUDE_CODE_USE_BEDROCK: "1",
AWS_BEARER_TOKEN_BEDROCK: "",
ANTHROPIC_BEDROCK_BASE_URL: "https://gateway.example",
ANTHROPIC_CUSTOM_HEADERS: "custom-header: test",
}),
}),
}),
);
});
it("hide claude authentication without terminal-auth", async () => {
const [agent] = await createAgentMock();
vi.stubGlobal("process", { ...process, argv: ["--hide-claude-auth"] });