Skip to content

feat(aws): all-inclusive fork on upstream v1.52.0 with IAM AssumeRole support#17

Closed
Shelnutt2 wants to merge 186 commits into
mainfrom
seth/aigov-492-all-inclusive-assume-role
Closed

feat(aws): all-inclusive fork on upstream v1.52.0 with IAM AssumeRole support#17
Shelnutt2 wants to merge 186 commits into
mainfrom
seth/aigov-492-all-inclusive-assume-role

Conversation

@Shelnutt2

Copy link
Copy Markdown

Summary

Re-baselines the Coder fork of anthropic-sdk-go onto upstream anthropics/anthropic-sdk-go v1.52.0 and re-applies the Coder customizations on top, then adds IAM AssumeRole (RoleARN + ExternalID) support to the aws gateway client (AIGOV-492).

Upstream v1.52.0 already ships the aws/internal/awsauth gateway packages (the AIGOV-491 work was upstreamed and extended with bearer-auth + per-request options), so this branch builds assume-role directly on the upstream package rather than porting PR #15.

Supersedes #16, which auto-closed shortly after creation following a branch rebase and could not be reopened ("branch was force-pushed or recreated"). Head is unchanged at bc058bf.

Review tip: the diff against main includes the full upstream v1.26.0 -> v1.52.0 advancement. To review only the Coder-specific commits, compare against the base tag:
v1.52.0...seth/aigov-492-all-inclusive-assume-role (4 commits).

Coder commits on top of v1.52.0

Commit Change
feat(aws) IAM AssumeRole: AWSRoleARN, AWSExternalID, AWSRoleSessionName on aws.ClientConfig + internal awsauth.ClientConfig; STS assume-role via stscreds.NewAssumeRoleProvider wrapped in aws.NewCredentialsCache; AWS_ROLE_ARN / AWS_ROLE_SESSION_NAME env parity; 8 unit tests (mock STS).
fix(bedrock) Strip X-Api-Key / anthropic-version before signing; set X-Amzn-Bedrock-Accept and drop HTTP Accept for streaming.
fix(vertex) Preserve/wrap caller HTTP client (nil-guarded), check body close error, reject unsupported method/path.
perf (DirectEncoder) DirectEncoder fast path (zero-copy nested encoding), regenerated for v1.52.0 by a committed generator (internal/cmd/gendirectencode).

AssumeRole behavior (AIGOV-492)

  • Auth precedence preserved: API key > explicit creds / role assumption > profile > default chain.
  • When AWSRoleARN is set, the resolved base identity (static keys, profile, or default chain) signs the STS AssumeRole call; the resulting temporary credentials SigV4-sign requests against service aws-external-anthropic.
  • AWSExternalID is threaded into AssumeRoleOptions; AWSRoleSessionName defaults to coder-aigateway (env: AWS_ROLE_SESSION_NAME).
  • Credentials are cached + auto-refreshed; the eager Credentials.Retrieve keeps fail-fast at setup.
  • BuildAWSConfig resolves uniformly via LoadDefaultConfig (injecting static keys via WithCredentialsProvider) so region, shared-config/profile, and standard endpoint resolution apply consistently and STS is testable.

DirectEncoder regeneration

The SDK's request/response types are Stainless-generated and cannot be regenerated in-repo, and the generated types moved substantially across v1.26 -> v1.52, so the original hand-edited per-type EncodeDirect methods could not be cherry-picked. This PR adds a committed generator, internal/cmd/gendirectencode, that re-derives all EncodeDirect methods from the generated source (re-run after each SDK upgrade):

  • object params (canonical 2-statement MarshalObject) -> shadow fast path
  • union params (canonical 1-statement MarshalUnion) -> single present member, presence resolved via param.IsOmitted to match the SDK's own asAny()
  • anything else (schema conversion, MarshalWithExtras, custom marshalers) -> safe return nil, false fallback to the real MarshalJSON

A statement-count guard keeps custom marshalers (e.g. BetaJSONOutputFormatParam, which rewrites Schema before marshaling) on their real path. 387 methods generated (379 fast-path, 8 fallback). Validated by ported coverage, byte-identical compat, and encoder machinery tests.

CI status

  • build / lint / test: green. scripts/test runs against the steady mock; the full suite passes locally under the same conditions.
  • detect-breaking-changes-vs-main: expected failure. This job overlays main's (v1.26.0) test files onto the v1.52.0 SDK and lints them; they reference upstream symbols renamed/removed across the 26-version jump (e.g. ModelClaudeOpus4_20250514). The failure reflects upstream's intentional API evolution, not a change in this PR, and resolves once main advances to v1.52.0.

Note: an earlier revision included dannykopping's appendCompact marshaler optimization. It was dropped because it removes the encoder's compaction of non-compact MarshalJSON output (e.g. via param.Override), which upstream's packages/param TestAppendCompact asserts. The DirectEncoder fast path already provides the primary perf win and preserves upstream behavior.

Testing

  • go build ./..., go vet ./..., scripts/lint, and scripts/test (full suite vs steady mock) all pass.
  • New/ported: 8 assume-role tests, Bedrock strip/streaming tests, DirectEncoder coverage + compat + machinery tests.
Decision log & deferred items

Audit of each Coder customization vs v1.52.0. Already upstreamed (no action): the aws/awsauth gateway packages (with bearer auth + per-request options), Bedrock bearer-token + AWS_BEARER_TOKEN_BEDROCK env recognition, and the cache-token-preserving usage-accumulation guards.

Applied: assume-role (new), Bedrock header cleanup + streaming accept, Vertex fixes, DirectEncoder (regenerated).

Intentionally left out (stay on upstream behavior):

  1. appendCompact optimization — conflicts with upstream's tested compaction of non-compact MarshalJSON output (see note above).
  2. Bedrock bearer-vs-Credentials priority (charm 21d6f3d) — would reverse upstream's BearerAuthTokenProvider-first precedence.
  3. Usage-accumulation refinement (coder 1561b5e) — v1.52.0 already has the substantive cache-token fix; the refinement only changes present-but-null handling on a hot path.

Consumption: a companion coder/coder branch (seth/aigov-492-anthropic-sdk-single-replace, no PR) points the direct github.com/anthropics/anthropic-sdk-go dependency at this branch (v1.19.0 -> v1.52.0); full go build ./... and the aibridge/taskname tests pass. A literal single replace also requires converging coder/fantasy off the charmbracelet/... module path (separate repo) — tracked as follow-up.

Refs AIGOV-492, AIGOV-491, AIGOV-484.

Generated by Coder Agents on behalf of @Shelnutt2.

stainless-app Bot and others added 30 commits March 16, 2026 17:25
Streamline the README to essentials (Documentation, Installation, Getting
Started, Requirements, Contributing, License) and move detailed SDK
documentation to https://docs.anthropic.com/en/api/sdks/go.

Changes:
- Remove detailed inline docs (streaming, tool use, error handling,
  pagination, retries, middleware, Bedrock/Vertex, etc.) in favor of
  the centralized docs site
- Update getting started example to use Opus 4.6
- Replace "Anthropic API" with "Claude API" throughout
- Restore x-release-please-start-version directives in README
- Address PR review feedback

PR: #587
…licts

* chore(custom): remove unused dead code duplicating generated types

Removes three sets of hand-written declarations that are structurally
identical to (or strict subsets of) types already generated by codegen,
and are not referenced anywhere in the SDK:

- `MessageStopReason` + 4 consts: unused copy of generated `StopReason`
  (which has 6 variants); `Message.StopReason` uses the generated type
- `BetaMessageStopReason` + 4 consts: unused copy of generated
  `BetaStopReason` (which has 8 variants)
- `BetaBase64PDFBlockParam`, `BetaBase64PDFBlockSourceUnionParam`, all
  their methods and `init()` block: old names for the generated
  `BetaRequestDocumentBlockParam`/`BetaRequestDocumentBlockSourceUnionParam`
  before codegen renamed them; structurally identical and never used

Each of these was a latent merge conflict source on every codegen cycle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove relocated init() blocks that conflict with codegen

Delete custom init() clusters containing relocated RegisterUnion calls
from message.go and betamessage.go. These cause merge conflicts on every
codegen run and some are stale (missing new discriminators). Preserve the
2 custom RegisterCustomDecoder calls for string-to-TextBlock conversion.
Codegen will re-insert RegisterUnion calls at their natural positions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove models past their end-of-life date
- Remove legacy naming format aliases
- Add deprecation notice for claude-3-haiku-20240307
- Update descriptions for consistency across variants
- Reorder entries to group aliases with their dated versions
dtmeadows-ant and others added 26 commits June 5, 2026 19:16
…#10)

jsonschema v0.14.0 changed Schema.Properties from wk8/go-ordered-map/v2
to pb33f/ordered-map/v2. Go MVS picks the max version across the build
graph, so any consumer with v0.14.0 in its graph failed to compile
schemautil.go. Bump to v0.14.0 and switch the SDK's ordered-map import
(drop-in for the API surface used); raises the go directive to 1.24,
which v0.14.0 requires.

Co-authored-by: Dennis Zagiansky <dennis@brizz.ai>
claude-opus-4-1 and claude-opus-4-1-20250805 reach end-of-life on August 5, 2026. Adds deprecation markers across the SDKs and runtime warnings in TypeScript and Python.
- BetaManagedAgentsCustomToolInputSchema.type is now a required const
- agents/versions list responses now mark `data` required
- max_tokens on the advisor tool; model_not_found advisor error code
- error_message on tool-search result error params
…upport for server-side fallbacks on refusal

feat(client): adds client-side fallbacks middleware for API providers that do not support server-side fallbacks
… and tag the fallback middleware (anthropics#88)

* fix(helpers): single source of truth for x-stainless-helper + append semantics

internal/stainlesshelper carries the lowercase header key, the closed set of
tag values shared across SDKs, and With(Value) — a request option that
comma-appends to any existing tag (case-insensitive, deduped, single header
line) instead of clobbering it.

Consolidates the two duplicate const blocks (betasessiontoolrunner.go,
lib/environments/poller.go) and tags the BetaToolRunner's requests, which
previously sent no helper telemetry. Tag values are unchanged.

* feat(helpers): tag refusal-fallback middleware requests with fallback-refusal-middleware

BetaRefusalFallbackMiddleware now appends fallback-refusal-middleware to the
x-stainless-helper value of every applicable request — original and each hop —
via stainlesshelper.AppendHeaderValue (one call site; requestWithBody clones
req.Header so every hop inherits the tag). An existing tag is extended, never
replaced; pass-through requests are left untouched.

* review: stainlesshelper → stainlessheader; prepend the runner option

- rename package internal/stainlesshelper → internal/stainlessheader
- betatoolrunner: prepend the helper option as a default rather than the
  three-index-slice append, so caller opts run after (and may clear/override)
Add AWSRoleARN, AWSExternalID, and AWSRoleSessionName to aws.ClientConfig
and the internal awsauth.ClientConfig. When AWSRoleARN is set, the resolved
base identity (explicit static keys, AWSProfile, or the default AWS
credential chain) signs an STS AssumeRole call, and the resulting temporary
credentials sign requests via SigV4 against service aws-external-anthropic.

BuildAWSConfig now resolves the base config through LoadDefaultConfig
uniformly (injecting static keys via WithCredentialsProvider) so region,
shared-config/profile, and standard endpoint resolution apply consistently,
then wraps the assume-role provider in aws.NewCredentialsCache for automatic
caching and refresh. The eager Credentials.Retrieve preserves fail-fast at
setup. AWS_ROLE_ARN and AWS_ROLE_SESSION_NAME are honored when the
corresponding fields are unset.

Refs AIGOV-492.

Co-authored-by: Coder Agents <agents@coder.com>
Re-applies two Coder Bedrock fixes onto v1.52.0:
- Strip X-Api-Key and anthropic-version before signing so Anthropic public
  API headers neither reach Bedrock nor enter the SigV4 signed header set.
- For streaming, delete the HTTP Accept header and set X-Amzn-Bedrock-Accept
  to application/json, matching botocore's invoke-with-response-stream.

Cherry-picked-from: 3be8e19, 6751434, 47cab19 (coder/anthropic-sdk-go)
Co-authored-by: Coder Agents <agents@coder.com>
…nknown paths

Re-applies Coder/charm Vertex fixes onto v1.52.0:
- Build the OAuth-authorized client lazily and wrap a caller-provided custom
  transport instead of overriding it; guard against a nil HTTPClient.
- Check the request body Close error instead of ignoring it.
- Return an explicit error for unsupported method/path combinations.

Cherry-picked-from: a908e4b, ec14991, 3eb2f9e, 7b952cd (coder/anthropic-sdk-go)
Co-authored-by: Coder Agents <agents@coder.com>
…ocations

Re-applies the DirectEncoder optimization (coder a31d7d0) onto v1.52.0. Adds a
DirectEncoder interface to the shimmed encoding/json package: when a nested
value implements EncodeDirect() (any, bool), the encoder writes the underlying
value straight into the parent buffer, bypassing the MarshalJSON -> Marshal ->
[]byte copy round-trip.

Because the SDK's request/response types are Stainless-generated and cannot be
regenerated in-repo, the 387 EncodeDirect methods are produced by a committed
generator (internal/cmd/gendirectencode) re-run after SDK upgrades:
- object params (canonical 2-statement MarshalObject)  -> shadow fast path
- unions (canonical 1-statement MarshalUnion)          -> single present member
  (presence resolved via param.IsOmitted, matching the SDK's own asAny())
- any MarshalJSON with extra logic (schema conversion, MarshalWithExtras,
  custom marshalers)                                   -> safe MarshalJSON fallback

The statement-count guard keeps custom marshalers (e.g. BetaJSONOutputFormatParam,
which rewrites Schema before marshaling) on their real MarshalJSON path.

Tests: ported coverage (every MarshalJSON type has EncodeDirect), byte-identical
compat, and encoder machinery tests; full non-network suite passes.

Cherry-picked-from: a31d7d0 (coder/anthropic-sdk-go), regenerated for v1.52.0
Co-authored-by: Coder Agents <agents@coder.com>
@linear-code

linear-code Bot commented Jun 27, 2026

Copy link
Copy Markdown

AIGOV-492

AIGOV-491

AIGOV-484

Copy link
Copy Markdown
Author

Closing per request: consuming this fork directly from the branch (seth/aigov-492-all-inclusive-assume-role), no PR needed. Branch CI (lint/test) runs on push. Generated by Coder Agents on behalf of @Shelnutt2.

@Shelnutt2 Shelnutt2 closed this Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.