Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(deps): update dependency @anthropic-ai/sdk to v0.35.0 #235

Merged
merged 1 commit into from
Jan 29, 2025

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Jan 29, 2025

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
@anthropic-ai/sdk 0.33.1 -> 0.35.0 age adoption passing confidence

Release Notes

anthropics/anthropic-sdk-typescript (@​anthropic-ai/sdk)

v0.35.0

Full Changelog: sdk-v0.34.0...sdk-v0.35.0

Features
Bug Fixes
  • docs: correct results return type (#​657) (4e6d031)
  • examples: add token counting example (2498e2e)
  • send correct Accept header for certain endpoints (#​651) (17ffaeb)
  • vertex: add beta.messages.countTokens method (51d3f23)
Chores
Documentation

Configuration

📅 Schedule: Branch creation - "* 0-4 * * 3" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

Copy link

anthropic debug - [puLL-Merge] - anthropics/[email protected]

Diff
diff --git .release-please-manifest.json .release-please-manifest.json
index 2053c67b..cb210381 100644
--- .release-please-manifest.json
+++ .release-please-manifest.json
@@ -1,5 +1,5 @@
 {
-  ".": "0.33.1",
-  "packages/vertex-sdk": "0.6.1",
-  "packages/bedrock-sdk": "0.12.0"
+  ".": "0.35.0",
+  "packages/vertex-sdk": "0.6.3",
+  "packages/bedrock-sdk": "0.12.2"
 }
diff --git .stats.yml .stats.yml
index 19e9daeb..239e17b7 100644
--- .stats.yml
+++ .stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 19
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-be055148d227480fcacc9086c37ac8009dcb487731069ada51af35044f65bee4.yml
+configured_endpoints: 21
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-fd67aea6883f1ee9e46f31a42d3940f0acb1749e787055bd9b9f278b20fa53ec.yml
diff --git CHANGELOG.md CHANGELOG.md
index a1a57c52..499e576c 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -1,5 +1,63 @@
 # Changelog
 
+## 0.35.0 (2025-01-21)
+
+Full Changelog: [sdk-v0.34.0...sdk-v0.35.0](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.34.0...sdk-v0.35.0)
+
+### Features
+
+* add beta message streaming helpers ([#655](https://github.com/anthropics/anthropic-sdk-typescript/issues/655)) ([d7b5af1](https://github.com/anthropics/anthropic-sdk-typescript/commit/d7b5af1629dbcefdb7bfdca271ab497567830227))
+* **stream:** add `.withResponse()` ([#654](https://github.com/anthropics/anthropic-sdk-typescript/issues/654)) ([b54477f](https://github.com/anthropics/anthropic-sdk-typescript/commit/b54477f20c92db4c2c5ed89af5d46c36b035bf1e))
+* **streaming:** add `.request_id` getter ([4572478](https://github.com/anthropics/anthropic-sdk-typescript/commit/4572478266a67e12e32ffef69817cbc495943b1d))
+
+
+### Bug Fixes
+
+* **docs:** correct results return type ([#657](https://github.com/anthropics/anthropic-sdk-typescript/issues/657)) ([4e6d031](https://github.com/anthropics/anthropic-sdk-typescript/commit/4e6d031a41625ebf9c4311638e0c149179fcae0c))
+* **examples:** add token counting example ([2498e2e](https://github.com/anthropics/anthropic-sdk-typescript/commit/2498e2eaf49d66a664ed1fdcd7bbd331979cf5b2))
+* send correct Accept header for certain endpoints ([#651](https://github.com/anthropics/anthropic-sdk-typescript/issues/651)) ([17ffaeb](https://github.com/anthropics/anthropic-sdk-typescript/commit/17ffaeba5af48d13b08483973b82cfe1ae79347f))
+* **vertex:** add beta.messages.countTokens method ([51d3f23](https://github.com/anthropics/anthropic-sdk-typescript/commit/51d3f23a7cc1bea798cc8e4041e08114ebc3a4eb))
+
+
+### Chores
+
+* deprecate more models ([661f5f9](https://github.com/anthropics/anthropic-sdk-typescript/commit/661f5f9d9b24f3661df246dcf101dd9812b3e19e))
+* **internal:** add test ([#660](https://github.com/anthropics/anthropic-sdk-typescript/issues/660)) ([3ec7d1a](https://github.com/anthropics/anthropic-sdk-typescript/commit/3ec7d1a9eea30255b24cdb16c1a26705bdfea0ac))
+* **internal:** temporary revert commit ([#643](https://github.com/anthropics/anthropic-sdk-typescript/issues/643)) ([43dd43c](https://github.com/anthropics/anthropic-sdk-typescript/commit/43dd43c4c8ab69d5a60e59473af7dff5f7799048))
+* **internal:** update examples ([#649](https://github.com/anthropics/anthropic-sdk-typescript/issues/649)) ([036a239](https://github.com/anthropics/anthropic-sdk-typescript/commit/036a239800fec7e6cbc439f125101d5475eae5b3))
+* **types:** add `| undefined` to client options properties ([#656](https://github.com/anthropics/anthropic-sdk-typescript/issues/656)) ([d642298](https://github.com/anthropics/anthropic-sdk-typescript/commit/d642298334529ff95b9d7ac497d548a6b04dbcfb))
+
+
+### Documentation
+
+* **readme:** fix misplaced period ([#650](https://github.com/anthropics/anthropic-sdk-typescript/issues/650)) ([8754744](https://github.com/anthropics/anthropic-sdk-typescript/commit/87547448c8b4bf69a61756af1f12927f33b68680))
+* **readme:** fix Request IDs example ([#659](https://github.com/anthropics/anthropic-sdk-typescript/issues/659)) ([6d3162d](https://github.com/anthropics/anthropic-sdk-typescript/commit/6d3162da1ddb964b75e575376f278468ba1ed9f5))
+
+## 0.34.0 (2024-12-20)
+
+Full Changelog: [sdk-v0.33.1...sdk-v0.34.0](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.33.1...sdk-v0.34.0)
+
+### Features
+
+* **api:** add message batch delete endpoint ([#640](https://github.com/anthropics/anthropic-sdk-typescript/issues/640)) ([54f7e1f](https://github.com/anthropics/anthropic-sdk-typescript/commit/54f7e1ffb9a2956ee27a4a715b84717aa681eb7c))
+
+
+### Bug Fixes
+
+* **client:** normalize method ([#639](https://github.com/anthropics/anthropic-sdk-typescript/issues/639)) ([384bb04](https://github.com/anthropics/anthropic-sdk-typescript/commit/384bb042dd854ed753c6bd8e25f522d0e042bfbf))
+
+
+### Chores
+
+* bump testing data uri ([#637](https://github.com/anthropics/anthropic-sdk-typescript/issues/637)) ([3f23530](https://github.com/anthropics/anthropic-sdk-typescript/commit/3f23530fb55d9fec7278967ea02600e44e9f58e2))
+* **internal:** temporary revert commit ([#643](https://github.com/anthropics/anthropic-sdk-typescript/issues/643)) ([8057b1e](https://github.com/anthropics/anthropic-sdk-typescript/commit/8057b1eb67ccccee042a45f2efe53cccced15682))
+
+
+### Documentation
+
+* minor formatting changes ([#641](https://github.com/anthropics/anthropic-sdk-typescript/issues/641)) ([8b362ee](https://github.com/anthropics/anthropic-sdk-typescript/commit/8b362ee72954b31b4de920b35aed97255efa5e2e))
+* **readme:** add alpha callout ([#646](https://github.com/anthropics/anthropic-sdk-typescript/issues/646)) ([640304c](https://github.com/anthropics/anthropic-sdk-typescript/commit/640304c7c7e8bc67cbf799a646169736d89ad4c8))
+
 ## 0.33.1 (2024-12-17)
 
 Full Changelog: [sdk-v0.33.0...sdk-v0.33.1](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.33.0...sdk-v0.33.1)
diff --git CONTRIBUTING.md CONTRIBUTING.md
index 9a869b0f..7d94b319 100644
--- CONTRIBUTING.md
+++ CONTRIBUTING.md
@@ -1,6 +1,6 @@
 ## Setting up the environment
 
-This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable).
+This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install).
 Other package managers may work but are not officially supported for development.
 
 To set up the repository, run:
@@ -29,10 +29,10 @@ All files in the `examples/` directory are not modified by the generator and can
 …
 \`\`\`
 
-```
-chmod +x examples/<your-example>.ts
+```sh
+$ chmod +x examples/<your-example>.ts
 # run the example against your api
-yarn tsn -T examples/<your-example>.ts
+$ yarn tsn -T examples/<your-example>.ts

Using the repository from source

diff --git README.md README.md
index da3db48e..fac24b92 100644
--- README.md
+++ README.md
@@ -1,3 +1,9 @@
+> [!IMPORTANT]
+> We're actively working on a new alpha version that migrates from node-fetch to builtin fetch.
+>
+> Please try it out and let us know if you run into any issues!
+> anthropics/anthropic-sdk-typescript#645
+

Anthropic TypeScript API Library

NPM version npm bundle size
@@ -235,7 +241,7 @@ All object responses in the SDK provide a _request_id property which is added

const message = await client.messages.create({ max_tokens: 1024, messages: [{ role: 'user', content: 'Hello, Claude' }], model: 'claude-3-5-sonnet-latest' });
-console.log(completion._request_id) // req_018EeWyXxfu5pfWkrYcMdjWG
+console.log(message._request_id) // req_018EeWyXxfu5pfWkrYcMdjWG

@@ -486,7 +492,7 @@ await client.messages.create(
This package generally follows SemVer conventions, though certain backwards-incompatible changes may be released as minor versions:

  1. Changes that only affect static types, without breaking runtime behavior.
    -2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals).
    +2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals.)
  2. Changes that we do not expect to impact the vast majority of users in practice.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
diff --git api.md api.md
index 48d1c9a8..9aed2e92 100644
--- api.md
+++ api.md
@@ -70,6 +70,7 @@ Methods:

Types:

+- DeletedMessageBatch

  • MessageBatch
  • MessageBatchCanceledResult
  • MessageBatchErroredResult
    @@ -84,8 +85,9 @@ Methods:
  • client.messages.batches.create({ ...params }) -> MessageBatch
  • client.messages.batches.retrieve(messageBatchId) -> MessageBatch
  • client.messages.batches.list({ ...params }) -> MessageBatchesPage
    +- client.messages.batches.delete(messageBatchId) -> DeletedMessageBatch
  • client.messages.batches.cancel(messageBatchId) -> MessageBatch
    -- client.messages.batches.results(messageBatchId) -> Response
    +- client.messages.batches.results(messageBatchId) -> JSONLDecoder<MessageBatchIndividualResponse>

Models

@@ -175,6 +177,7 @@ Methods:

Types:

+- BetaDeletedMessageBatch

  • BetaMessageBatch
  • BetaMessageBatchCanceledResult
  • BetaMessageBatchErroredResult
    @@ -189,5 +192,6 @@ Methods:
  • client.beta.messages.batches.create({ ...params }) -> BetaMessageBatch
  • client.beta.messages.batches.retrieve(messageBatchId, { ...params }) -> BetaMessageBatch
  • client.beta.messages.batches.list({ ...params }) -> BetaMessageBatchesPage
    +- client.beta.messages.batches.delete(messageBatchId, { ...params }) -> BetaDeletedMessageBatch
  • client.beta.messages.batches.cancel(messageBatchId, { ...params }) -> BetaMessageBatch
    -- client.beta.messages.batches.results(messageBatchId, { ...params }) -> Response
    +- client.beta.messages.batches.results(messageBatchId, { ...params }) -> JSONLDecoder<MessageBatchIndividualResponse>
    diff --git examples/count-tokens.ts examples/count-tokens.ts
    index e69de29b..22fae1f1 100755
    --- examples/count-tokens.ts
    +++ examples/count-tokens.ts
    @@ -0,0 +1,20 @@
    +#!/usr/bin/env -S npm run tsn -T

+import Anthropic from '@anthropic-ai/sdk';
+
+const client = new Anthropic(); // gets API Key from environment variable ANTHROPIC_API_KEY
+
+async function main() {

  • const result = await client.messages.countTokens({
  • messages: [
  •  {
    
  •    role: 'user',
    
  •    content: 'Hey Claude!?',
    
  •  },
    
  • ],
  • model: 'claude-3-5-sonnet-latest',
  • });
  • console.dir(result);
    +}

+main();
diff --git package.json package.json
index d8f88f57..aa23123e 100644
--- package.json
+++ package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/sdk",

  • "version": "0.33.1",
  • "version": "0.35.0",
    "description": "The official TypeScript library for the Anthropic API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/bedrock-sdk/CHANGELOG.md packages/bedrock-sdk/CHANGELOG.md
    index 837af37e..12fec54c 100644
    --- packages/bedrock-sdk/CHANGELOG.md
    +++ packages/bedrock-sdk/CHANGELOG.md
    @@ -1,5 +1,21 @@

Changelog

+## 0.12.2 (2025-01-21)
+
+Full Changelog: bedrock-sdk-v0.12.1...bedrock-sdk-v0.12.2
+
+### Chores
+
+* internal: temporary revert commit (#643) (43dd43c)
+
+## 0.12.1 (2024-12-20)
+
+Full Changelog: bedrock-sdk-v0.12.0...bedrock-sdk-v0.12.1
+
+### Chores
+
+* internal: temporary revert commit (#643) (8057b1e)
+

0.12.0 (2024-12-17)

Full Changelog: bedrock-sdk-v0.11.2...bedrock-sdk-v0.12.0
diff --git packages/bedrock-sdk/package.json packages/bedrock-sdk/package.json
index 352931a5..8e7a906d 100644
--- packages/bedrock-sdk/package.json
+++ packages/bedrock-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/bedrock-sdk",

  • "version": "0.12.0",
  • "version": "0.12.2",
    "description": "The official TypeScript library for the Anthropic Bedrock API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/vertex-sdk/CHANGELOG.md packages/vertex-sdk/CHANGELOG.md
    index 94191164..e01d1d71 100644
    --- packages/vertex-sdk/CHANGELOG.md
    +++ packages/vertex-sdk/CHANGELOG.md
    @@ -1,5 +1,26 @@

Changelog

+## 0.6.3 (2025-01-21)
+
+Full Changelog: vertex-sdk-v0.6.2...vertex-sdk-v0.6.3
+
+### Bug Fixes
+
+* vertex: add beta.messages.countTokens method (51d3f23)
+
+
+### Chores
+
+* internal: temporary revert commit (#643) (43dd43c)
+
+## 0.6.2 (2024-12-20)
+
+Full Changelog: vertex-sdk-v0.6.1...vertex-sdk-v0.6.2
+
+### Chores
+
+* internal: temporary revert commit (#643) (8057b1e)
+

0.6.1 (2024-12-17)

Full Changelog: vertex-sdk-v0.6.0...vertex-sdk-v0.6.1
diff --git packages/vertex-sdk/package.json packages/vertex-sdk/package.json
index 43fc356d..ae4cf6f9 100644
--- packages/vertex-sdk/package.json
+++ packages/vertex-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/vertex-sdk",

  • "version": "0.6.1",
  • "version": "0.6.3",
    "description": "The official TypeScript library for the Anthropic Vertex API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/vertex-sdk/src/client.ts packages/vertex-sdk/src/client.ts
    index f1046455..0f8a1626 100644
    --- packages/vertex-sdk/src/client.ts
    +++ packages/vertex-sdk/src/client.ts
    @@ -179,23 +179,17 @@ function makeMessagesResource(client: AnthropicVertex): MessagesResource {
    }

/**

    • The Vertex API does not currently support prompt caching, token counting or the Batch API.
    • The Vertex API does not currently support the Batch API.
      */
      -type BetaResource = Omit<Resources.Beta, 'promptCaching' | 'messages'> & {
  • messages: Omit<Resources.Beta['messages'], 'batches' | 'countTokens'>;
    +type BetaResource = Omit<Resources.Beta, 'messages'> & {
  • messages: Omit<Resources.Beta['messages'], 'batches'>;
    };

function makeBetaResource(client: AnthropicVertex): BetaResource {
const resource = new Resources.Beta(client);

  • // @ts-expect-error we're deleting non-optional properties

  • delete resource.promptCaching;

  • // @ts-expect-error we're deleting non-optional properties
    delete resource.messages.batches;

  • // @ts-expect-error we're deleting non-optional properties

  • delete resource.messages.countTokens;

  • return resource;
    }
    diff --git src/core.ts src/core.ts
    index ea8d8dca..344bf6ac 100644
    --- src/core.ts
    +++ src/core.ts
    @@ -556,9 +556,19 @@ export abstract class APIClient {

    const timeout = setTimeout(() => controller.abort(), ms);

  • const fetchOptions = {
  •  signal: controller.signal as any,
    
  •  ...options,
    
  • };
  • if (fetchOptions.method) {
  •  // Custom methods like 'patch' need to be uppercased
    
  •  // See https://github.com/nodejs/undici/issues/2294
    
  •  fetchOptions.method = fetchOptions.method.toUpperCase();
    
  • }
  • return (
    // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
  •  this.fetch.call(undefined, url, { signal: controller.signal as any, ...options }).finally(() => {
    
  •  this.fetch.call(undefined, url, fetchOptions).finally(() => {
       clearTimeout(timeout);
     })
    
    );
    diff --git src/index.ts src/index.ts
    index bfca4fc8..44f6bc2d 100644
    --- src/index.ts
    +++ src/index.ts
    @@ -103,7 +103,7 @@ export interface ClientOptions {
    • Note that request timeouts are retried by default, so in a worst-case scenario you may wait
    • much longer than this timeout before the promise succeeds or fails.
      */
  • timeout?: number;
  • timeout?: number | undefined;

    /**

    • An HTTP agent used to manage HTTP(S) connections.
      @@ -111,7 +111,7 @@ export interface ClientOptions {
    • If not provided, an agent will be constructed by default in the Node.js environment,
    • otherwise no agent is used.
      */
  • httpAgent?: Agent;
  • httpAgent?: Agent | undefined;

    /**

    • Specify a custom fetch function implementation.
      @@ -127,7 +127,7 @@ export interface ClientOptions {
    • @default 2
      */
  • maxRetries?: number;
  • maxRetries?: number | undefined;

    /**

    • Default headers to include with every request to the API.
      @@ -135,7 +135,7 @@ export interface ClientOptions {
    • These can be removed in individual requests by explicitly setting the
    • header to undefined or null in request options.
      */
  • defaultHeaders?: Core.Headers;
  • defaultHeaders?: Core.Headers | undefined;

    /**

    • Default query parameters to include with every request to the API.
      @@ -143,13 +143,13 @@ export interface ClientOptions {
    • These can be removed in individual requests by explicitly setting the
    • param to undefined in request options.
      */
  • defaultQuery?: Core.DefaultQuery;
  • defaultQuery?: Core.DefaultQuery | undefined;

    /**

    • By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
    • Only set this option to true if you understand the risks and have appropriate mitigations in place.
      */
  • dangerouslyAllowBrowser?: boolean;
  • dangerouslyAllowBrowser?: boolean | undefined;
    }

/**
diff --git a/src/lib/BetaMessageStream.ts b/src/lib/BetaMessageStream.ts
new file mode 100644
index 00000000..06fbc46a
--- /dev/null
+++ src/lib/BetaMessageStream.ts
@@ -0,0 +1,593 @@
+import * as Core from '@anthropic-ai/sdk/core';
+import { AnthropicError, APIUserAbortError } from '@anthropic-ai/sdk/error';
+import {

  • type BetaContentBlock,
  • Messages as BetaMessages,
  • type BetaMessage,
  • type BetaRawMessageStreamEvent as BetaMessageStreamEvent,
  • type BetaMessageParam,
  • type MessageCreateParams as BetaMessageCreateParams,
  • type MessageCreateParamsBase as BetaMessageCreateParamsBase,
  • type BetaTextBlock,
    +} from '@anthropic-ai/sdk/resources/beta/messages/messages';
    +import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index';
    +import { Stream } from '@anthropic-ai/sdk/streaming';
    +import { partialParse } from '../_vendor/partial-json-parser/parser';

+export interface MessageStreamEvents {

  • connect: () => void;
  • streamEvent: (event: BetaMessageStreamEvent, snapshot: BetaMessage) => void;
  • text: (textDelta: string, textSnapshot: string) => void;
  • inputJson: (partialJson: string, jsonSnapshot: unknown) => void;
  • message: (message: BetaMessage) => void;
  • contentBlock: (content: BetaContentBlock) => void;
  • finalMessage: (message: BetaMessage) => void;
  • error: (error: AnthropicError) => void;
  • abort: (error: APIUserAbortError) => void;
  • end: () => void;
    +}

+type MessageStreamEventListeners = {

  • listener: MessageStreamEvents[Event];
  • once?: boolean;
    +}[];

+const JSON_BUF_PROPERTY = '__json_buf';
+
+export class BetaMessageStream implements AsyncIterable {

  • messages: BetaMessageParam[] = [];
  • receivedMessages: BetaMessage[] = [];
  • #currentMessageSnapshot: BetaMessage | undefined;
  • controller: AbortController = new AbortController();
  • #connectedPromise: Promise<Response | null>;
  • #resolveConnectedPromise: (response: Response | null) => void = () => {};
  • #rejectConnectedPromise: (error: AnthropicError) => void = () => {};
  • #endPromise: Promise;
  • #resolveEndPromise: () => void = () => {};
  • #rejectEndPromise: (error: AnthropicError) => void = () => {};
  • #listeners: { [Event in keyof MessageStreamEvents]?: MessageStreamEventListeners } = {};
  • #ended = false;
  • #errored = false;
  • #aborted = false;
  • #catchingPromiseCreated = false;
  • #request_id: string | null | undefined;
  • constructor() {
  • this.#connectedPromise = new Promise<Response | null>((resolve, reject) => {
  •  this.#resolveConnectedPromise = resolve;
    
  •  this.#rejectConnectedPromise = reject;
    
  • });
  • this.#endPromise = new Promise((resolve, reject) => {
  •  this.#resolveEndPromise = resolve;
    
  •  this.#rejectEndPromise = reject;
    
  • });
  • // Don't let these promises cause unhandled rejection errors.
  • // we will manually cause an unhandled rejection error later
  • // if the user hasn't registered any error listener or called
  • // any promise-returning method.
  • this.#connectedPromise.catch(() => {});
  • this.#endPromise.catch(() => {});
  • }
  • get request_id(): string | null | undefined {
  • return this.#request_id;
  • }
  • /**
    • Returns the MessageStream data, the raw Response instance and the ID of the request,
    • returned vie the request-id header which is useful for debugging requests and resporting
    • issues to Anthropic.
    • This is the same as the APIPromise.withResponse() method.
    • This method will raise an error if you created the stream using MessageStream.fromReadableStream
    • as no Response is available.
  • */
  • async withResponse(): Promise<{
  • data: BetaMessageStream;
  • response: Response;
  • request_id: string | null | undefined;
  • }> {
  • const response = await this.#connectedPromise;
  • if (!response) {
  •  throw new Error('Could not resolve a `Response` object');
    
  • }
  • return {
  •  data: this,
    
  •  response,
    
  •  request_id: response.headers.get('request-id'),
    
  • };
  • }
  • /**
    • Intended for use on the frontend, consuming a stream produced with
    • .toReadableStream() on the backend.
    • Note that messages sent to the model do not appear in .on('message')
    • in this context.
  • */
  • static fromReadableStream(stream: ReadableStream): BetaMessageStream {
  • const runner = new BetaMessageStream();
  • runner._run(() => runner._fromReadableStream(stream));
  • return runner;
  • }
  • static createMessage(
  • messages: BetaMessages,
  • params: BetaMessageCreateParamsBase,
  • options?: Core.RequestOptions,
  • ): BetaMessageStream {
  • const runner = new BetaMessageStream();
  • for (const message of params.messages) {
  •  runner._addMessageParam(message);
    
  • }
  • runner._run(() =>
  •  runner._createMessage(
    
  •    messages,
    
  •    { ...params, stream: true },
    
  •    { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } },
    
  •  ),
    
  • );
  • return runner;
  • }
  • protected _run(executor: () => Promise) {
  • executor().then(() => {
  •  this._emitFinal();
    
  •  this._emit('end');
    
  • }, this.#handleError);
  • }
  • protected _addMessageParam(message: BetaMessageParam) {
  • this.messages.push(message);
  • }
  • protected _addMessage(message: BetaMessage, emit = true) {
  • this.receivedMessages.push(message);
  • if (emit) {
  •  this._emit('message', message);
    
  • }
  • }
  • protected async _createMessage(
  • messages: BetaMessages,
  • params: BetaMessageCreateParams,
  • options?: Core.RequestOptions,
  • ): Promise {
  • const signal = options?.signal;
  • if (signal) {
  •  if (signal.aborted) this.controller.abort();
    
  •  signal.addEventListener('abort', () => this.controller.abort());
    
  • }
  • this.#beginRequest();
  • const { response, data: stream } = await messages
  •  .create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
    
  •  .withResponse();
    
  • this._connected(response);
  • for await (const event of stream) {
  •  this.#addStreamEvent(event);
    
  • }
  • if (stream.controller.signal?.aborted) {
  •  throw new APIUserAbortError();
    
  • }
  • this.#endRequest();
  • }
  • protected _connected(response: Response | null) {
  • if (this.ended) return;
  • this.#request_id = response?.headers.get('request-id');
  • this.#resolveConnectedPromise(response);
  • this._emit('connect');
  • }
  • get ended(): boolean {
  • return this.#ended;
  • }
  • get errored(): boolean {
  • return this.#errored;
  • }
  • get aborted(): boolean {
  • return this.#aborted;
  • }
  • abort() {
  • this.controller.abort();
  • }
  • /**
    • Adds the listener function to the end of the listeners array for the event.
    • No checks are made to see if the listener has already been added. Multiple calls passing
    • the same combination of event and listener will result in the listener being added, and
    • called, multiple times.
    • @returns this MessageStream, so that calls can be chained
  • */
  • on(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners: MessageStreamEventListeners =
  •  this.#listeners[event] || (this.#listeners[event] = []);
    
  • listeners.push({ listener });
  • return this;
  • }
  • /**
    • Removes the specified listener from the listener array for the event.
    • off() will remove, at most, one instance of a listener from the listener array. If any single
    • listener has been added multiple times to the listener array for the specified event, then
    • off() must be called multiple times to remove each instance.
    • @returns this MessageStream, so that calls can be chained
  • */
  • off(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners = this.#listeners[event];
  • if (!listeners) return this;
  • const index = listeners.findIndex((l) => l.listener === listener);
  • if (index >= 0) listeners.splice(index, 1);
  • return this;
  • }
  • /**
    • Adds a one-time listener function for the event. The next time the event is triggered,
    • this listener is removed and then invoked.
    • @returns this MessageStream, so that calls can be chained
  • */
  • once(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners: MessageStreamEventListeners =
  •  this.#listeners[event] || (this.#listeners[event] = []);
    
  • listeners.push({ listener, once: true });
  • return this;
  • }
  • /**
    • This is similar to .once(), but returns a Promise that resolves the next time
    • the event is triggered, instead of calling a listener callback.
    • @returns a Promise that resolves the next time given event is triggered,
    • or rejects if an error is emitted. (If you request the 'error' event,
    • returns a promise that resolves with the error).
    • Example:
    • const message = await stream.emitted('message') // rejects if the stream errors
  • */
  • emitted(
  • event: Event,
  • ): Promise<
  • Parameters<MessageStreamEvents[Event]> extends [infer Param] ? Param
  • : Parameters<MessageStreamEvents[Event]> extends [] ? void
  • : Parameters<MessageStreamEvents[Event]>
  • {

  • return new Promise((resolve, reject) => {
  •  this.#catchingPromiseCreated = true;
    
  •  if (event !== 'error') this.once('error', reject);
    
  •  this.once(event, resolve as any);
    
  • });
  • }
  • async done(): Promise {
  • this.#catchingPromiseCreated = true;
  • await this.#endPromise;
  • }
  • get currentMessage(): BetaMessage | undefined {
  • return this.#currentMessageSnapshot;
  • }
  • #getFinalMessage(): BetaMessage {
  • if (this.receivedMessages.length === 0) {
  •  throw new AnthropicError('stream ended without producing a Message with role=assistant');
    
  • }
  • return this.receivedMessages.at(-1)!;
  • }
  • /**
    • @returns a promise that resolves with the the final assistant Message response,
    • or rejects if an error occurred or the stream ended prematurely without producing a Message.
  • */
  • async finalMessage(): Promise {
  • await this.done();
  • return this.#getFinalMessage();
  • }
  • #getFinalText(): string {
  • if (this.receivedMessages.length === 0) {
  •  throw new AnthropicError('stream ended without producing a Message with role=assistant');
    
  • }
  • const textBlocks = this.receivedMessages
  •  .at(-1)!
    
  •  .content.filter((block): block is BetaTextBlock => block.type === 'text')
    
  •  .map((block) => block.text);
    
  • if (textBlocks.length === 0) {
  •  throw new AnthropicError('stream ended without producing a content block with type=text');
    
  • }
  • return textBlocks.join(' ');
  • }
  • /**
    • @returns a promise that resolves with the the final assistant Message's text response, concatenated
    • together if there are more than one text blocks.
    • Rejects if an error occurred or the stream ended prematurely without producing a Message.
  • */
  • async finalText(): Promise {
  • await this.done();
  • return this.#getFinalText();
  • }
  • #handleError = (error: unknown) => {
  • this.#errored = true;
  • if (error instanceof Error && error.name === 'AbortError') {
  •  error = new APIUserAbortError();
    
  • }
  • if (error instanceof APIUserAbortError) {
  •  this.#aborted = true;
    
  •  return this._emit('abort', error);
    
  • }
  • if (error instanceof AnthropicError) {
  •  return this._emit('error', error);
    
  • }
  • if (error instanceof Error) {
  •  const anthropicError: AnthropicError = new AnthropicError(error.message);
    
  •  // @ts-ignore
    
  •  anthropicError.cause = error;
    
  •  return this._emit('error', anthropicError);
    
  • }
  • return this._emit('error', new AnthropicError(String(error)));
  • };
  • protected _emit(
  • event: Event,
  • ...args: Parameters<MessageStreamEvents[Event]>
  • ) {
  • // make sure we don't emit any MessageStreamEvents after end
  • if (this.#ended) return;
  • if (event === 'end') {
  •  this.#ended = true;
    
  •  this.#resolveEndPromise();
    
  • }
  • const listeners: MessageStreamEventListeners | undefined = this.#listeners[event];
  • if (listeners) {
  •  this.#listeners[event] = listeners.filter((l) => !l.once) as any;
    
  •  listeners.forEach(({ listener }: any) => listener(...args));
    
  • }
  • if (event === 'abort') {
  •  const error = args[0] as APIUserAbortError;
    
  •  if (!this.#catchingPromiseCreated && !listeners?.length) {
    
  •    Promise.reject(error);
    
  •  }
    
  •  this.#rejectConnectedPromise(error);
    
  •  this.#rejectEndPromise(error);
    
  •  this._emit('end');
    
  •  return;
    
  • }
  • if (event === 'error') {
  •  // NOTE: _emit('error', error) should only be called from #handleError().
    
  •  const error = args[0] as AnthropicError;
    
  •  if (!this.#catchingPromiseCreated && !listeners?.length) {
    
  •    // Trigger an unhandled rejection if the user hasn't registered any error handlers.
    
  •    // If you are seeing stack traces here, make sure to handle errors via either:
    
  •    // - runner.on('error', () => ...)
    
  •    // - await runner.done()
    
  •    // - await runner.final...()
    
  •    // - etc.
    
  •    Promise.reject(error);
    
  •  }
    
  •  this.#rejectConnectedPromise(error);
    
  •  this.#rejectEndPromise(error);
    
  •  this._emit('end');
    
  • }
  • }
  • protected _emitFinal() {
  • const finalMessage = this.receivedMessages.at(-1);
  • if (finalMessage) {
  •  this._emit('finalMessage', this.#getFinalMessage());
    
  • }
  • }
  • #beginRequest() {
  • if (this.ended) return;
  • this.#currentMessageSnapshot = undefined;
  • }
  • #addStreamEvent(event: BetaMessageStreamEvent) {
  • if (this.ended) return;
  • const messageSnapshot = this.#accumulateMessage(event);
  • this._emit('streamEvent', event, messageSnapshot);
  • switch (event.type) {
  •  case 'content_block_delta': {
    
  •    const content = messageSnapshot.content.at(-1)!;
    
  •    if (event.delta.type === 'text_delta' && content.type === 'text') {
    
  •      this._emit('text', event.delta.text, content.text || '');
    
  •    } else if (event.delta.type === 'input_json_delta' && content.type === 'tool_use') {
    
  •      if (content.input) {
    
  •        this._emit('inputJson', event.delta.partial_json, content.input);
    
  •      }
    
  •    }
    
  •    break;
    
  •  }
    
  •  case 'message_stop': {
    
  •    this._addMessageParam(messageSnapshot);
    
  •    this._addMessage(messageSnapshot, true);
    
  •    break;
    
  •  }
    
  •  case 'content_block_stop': {
    
  •    this._emit('contentBlock', messageSnapshot.content.at(-1)!);
    
  •    break;
    
  •  }
    
  •  case 'message_start': {
    
  •    this.#currentMessageSnapshot = messageSnapshot;
    
  •    break;
    
  •  }
    
  •  case 'content_block_start':
    
  •  case 'message_delta':
    
  •    break;
    
  • }
  • }
  • #endRequest(): BetaMessage {
  • if (this.ended) {
  •  throw new AnthropicError(`stream has ended, this shouldn't happen`);
    
  • }
  • const snapshot = this.#currentMessageSnapshot;
  • if (!snapshot) {
  •  throw new AnthropicError(`request ended without sending any chunks`);
    
  • }
  • this.#currentMessageSnapshot = undefined;
  • return snapshot;
  • }
  • protected async _fromReadableStream(
  • readableStream: ReadableStream,
  • options?: Core.RequestOptions,
  • ): Promise {
  • const signal = options?.signal;
  • if (signal) {
  •  if (signal.aborted) this.controller.abort();
    
  •  signal.addEventListener('abort', () => this.controller.abort());
    
  • }
  • this.#beginRequest();
  • this._connected(null);
  • const stream = Stream.fromReadableStream(readableStream, this.controller);
  • for await (const event of stream) {
  •  this.#addStreamEvent(event);
    
  • }
  • if (stream.controller.signal?.aborted) {
  •  throw new APIUserAbortError();
    
  • }
  • this.#endRequest();
  • }
  • /**
    • Mutates this.#currentMessage with the current event. Handling the accumulation of multiple messages
    • will be needed to be handled by the caller, this method will throw if you try to accumulate for multiple
    • messages.
  • */
  • #accumulateMessage(event: BetaMessageStreamEvent): BetaMessage {
  • let snapshot = this.#currentMessageSnapshot;
  • if (event.type === 'message_start') {
  •  if (snapshot) {
    
  •    throw new AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
    
  •  }
    
  •  return event.message;
    
  • }
  • if (!snapshot) {
  •  throw new AnthropicError(`Unexpected event order, got ${event.type} before "message_start"`);
    
  • }
  • switch (event.type) {
  •  case 'message_stop':
    
  •    return snapshot;
    
  •  case 'message_delta':
    
  •    snapshot.stop_reason = event.delta.stop_reason;
    
  •    snapshot.stop_sequence = event.delta.stop_sequence;
    
  •    snapshot.usage.output_tokens = event.usage.output_tokens;
    
  •    return snapshot;
    
  •  case 'content_block_start':
    
  •    snapshot.content.push(event.content_block);
    
  •    return snapshot;
    
  •  case 'content_block_delta': {
    
  •    const snapshotContent = snapshot.content.at(event.index);
    
  •    if (snapshotContent?.type === 'text' && event.delta.type === 'text_delta') {
    
  •      snapshotContent.text += event.delta.text;
    
  •    } else if (snapshotContent?.type === 'tool_use' && event.delta.type === 'input_json_delta') {
    
  •      // we need to keep track of the raw JSON string as well so that we can
    
  •      // re-parse it for each delta, for now we just store it as an untyped
    
  •      // non-enumerable property on the snapshot
    
  •      let jsonBuf = (snapshotContent as any)[JSON_BUF_PROPERTY] || '';
    
  •      jsonBuf += event.delta.partial_json;
    
  •      Object.defineProperty(snapshotContent, JSON_BUF_PROPERTY, {
    
  •        value: jsonBuf,
    
  •        enumerable: false,
    
  •        writable: true,
    
  •      });
    
  •      if (jsonBuf) {
    
  •        snapshotContent.input = partialParse(jsonBuf);
    
  •      }
    
  •    }
    
  •    return snapshot;
    
  •  }
    
  •  case 'content_block_stop':
    
  •    return snapshot;
    
  • }
  • }
  • Symbol.asyncIterator: AsyncIterator {
  • const pushQueue: BetaMessageStreamEvent[] = [];
  • const readQueue: {
  •  resolve: (chunk: BetaMessageStreamEvent | undefined) => void;
    
  •  reject: (error: unknown) => void;
    
  • }[] = [];
  • let done = false;
  • this.on('streamEvent', (event) => {
  •  const reader = readQueue.shift();
    
  •  if (reader) {
    
  •    reader.resolve(event);
    
  •  } else {
    
  •    pushQueue.push(event);
    
  •  }
    
  • });
  • this.on('end', () => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.resolve(undefined);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • this.on('abort', (err) => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.reject(err);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • this.on('error', (err) => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.reject(err);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • return {
  •  next: async (): Promise<IteratorResult<BetaMessageStreamEvent>> => {
    
  •    if (!pushQueue.length) {
    
  •      if (done) {
    
  •        return { value: undefined, done: true };
    
  •      }
    
  •      return new Promise<BetaMessageStreamEvent | undefined>((resolve, reject) =>
    
  •        readQueue.push({ resolve, reject }),
    
  •      ).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true }));
    
  •    }
    
  •    const chunk = pushQueue.shift()!;
    
  •    return { value: chunk, done: false };
    
  •  },
    
  •  return: async () => {
    
  •    this.abort();
    
  •    return { value: undefined, done: true };
    
  •  },
    
  • };
  • }
  • toReadableStream(): ReadableStream {
  • const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
  • return stream.toReadableStream();
  • }
    +}
    diff --git src/lib/MessageStream.ts src/lib/MessageStream.ts
    index dea739f1..65e84b29 100644
    --- src/lib/MessageStream.ts
    +++ src/lib/MessageStream.ts
    @@ -10,7 +10,7 @@ import {
    type MessageCreateParamsBase,
    type TextBlock,
    } from '@anthropic-ai/sdk/resources/messages';
    -import { type ReadableStream } from '@anthropic-ai/sdk/_shims/index';
    +import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index';
    import { Stream } from '@anthropic-ai/sdk/streaming';
    import { partialParse } from '../_vendor/partial-json-parser/parser';

@@ -41,8 +41,8 @@ export class MessageStream implements AsyncIterable {

controller: AbortController = new AbortController();

  • #connectedPromise: Promise;
  • #resolveConnectedPromise: () => void = () => {};
  • #connectedPromise: Promise<Response | null>;

  • #resolveConnectedPromise: (response: Response | null) => void = () => {};
    #rejectConnectedPromise: (error: AnthropicError) => void = () => {};

    #endPromise: Promise;
    @@ -55,9 +55,10 @@ export class MessageStream implements AsyncIterable {
    #errored = false;
    #aborted = false;
    #catchingPromiseCreated = false;

  • #request_id: string | null | undefined;

    constructor() {

  • this.#connectedPromise = new Promise((resolve, reject) => {
  • this.#connectedPromise = new Promise<Response | null>((resolve, reject) => {
    this.#resolveConnectedPromise = resolve;
    this.#rejectConnectedPromise = reject;
    });
    @@ -75,6 +76,37 @@ export class MessageStream implements AsyncIterable {
    this.#endPromise.catch(() => {});
    }

  • get request_id(): string | null | undefined {

  • return this.#request_id;

  • }

  • /**

    • Returns the MessageStream data, the raw Response instance and the ID of the request,
    • returned vie the request-id header which is useful for debugging requests and resporting
    • issues to Anthropic.
    • This is the same as the APIPromise.withResponse() method.
    • This method will raise an error if you created the stream using MessageStream.fromReadableStream
    • as no Response is available.
  • */

  • async withResponse(): Promise<{

  • data: MessageStream;

  • response: Response;

  • request_id: string | null | undefined;

  • }> {

  • const response = await this.#connectedPromise;

  • if (!response) {

  •  throw new Error('Could not resolve a `Response` object');
    
  • }

  • return {

  •  data: this,
    
  •  response,
    
  •  request_id: response.headers.get('request-id'),
    
  • };

  • }

  • /**

    • Intended for use on the frontend, consuming a stream produced with
    • .toReadableStream() on the backend.
      @@ -136,11 +168,10 @@ export class MessageStream implements AsyncIterable {
      signal.addEventListener('abort', () => this.controller.abort());
      }
      this.#beginRequest();
  • const stream = await messages.create(
  •  { ...params, stream: true },
    
  •  { ...options, signal: this.controller.signal },
    
  • );
  • this._connected();
  • const { response, data: stream } = await messages
  •  .create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
    
  •  .withResponse();
    
  • this._connected(response);
    for await (const event of stream) {
    this.#addStreamEvent(event);
    }
    @@ -150,9 +181,10 @@ export class MessageStream implements AsyncIterable {
    this.#endRequest();
    }
  • protected _connected() {
  • protected _connected(response: Response | null) {
    if (this.ended) return;
  • this.#resolveConnectedPromise();
  • this.#request_id = response?.headers.get('request-id');
  • this.#resolveConnectedPromise(response);
    this._emit('connect');
    }

@@ -424,7 +456,7 @@ export class MessageStream implements AsyncIterable {
signal.addEventListener('abort', () => this.controller.abort());
}
this.#beginRequest();

  • this._connected();
  • this._connected(null);
    const stream = Stream.fromReadableStream(readableStream, this.controller);
    for await (const event of stream) {
    this.#addStreamEvent(event);
    diff --git src/resources/beta/messages/batches.ts src/resources/beta/messages/batches.ts
    index 0a863e64..74f4e53b 100644
    --- src/resources/beta/messages/batches.ts
    +++ src/resources/beta/messages/batches.ts
    @@ -85,6 +85,35 @@ export class Batches extends APIResource {
    });
    }

  • /**

    • This endpoint is idempotent and can be used to poll for Message Batch
    • completion. To access the results of a Message Batch, make a request to the
    • results_url field in the response.
  • */

  • delete(

  • messageBatchId: string,

  • params?: BatchDeleteParams,

  • options?: Core.RequestOptions,

  • ): Core.APIPromise;

  • delete(messageBatchId: string, options?: Core.RequestOptions): Core.APIPromise;

  • delete(

  • messageBatchId: string,

  • params: BatchDeleteParams | Core.RequestOptions = {},

  • options?: Core.RequestOptions,

  • ): Core.APIPromise {

  • if (isRequestOptions(params)) {

  •  return this.delete(messageBatchId, {}, params);
    
  • }

  • const { betas } = params;

  • return this._client.delete(/v1/messages/batches/${messageBatchId}?beta=true, {

  •  ...options,
    
  •  headers: {
    
  •    'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
    
  •    ...options?.headers,
    
  •  },
    
  • });

  • }

  • /**

    • Batches may be canceled any time before processing ends. Once cancellation is
    • initiated, the batch enters a canceling state, at which time the system may
      @@ -158,6 +187,7 @@ export class Batches extends APIResource {
      ...options,
      headers: {
      'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
  •      Accept: 'application/binary',
         ...options?.headers,
       },
       __binaryResponse: true,
    

@@ -168,6 +198,20 @@ export class Batches extends APIResource {

export class BetaMessageBatchesPage extends Page {}

+export interface BetaDeletedMessageBatch {

  • /**
    • ID of the Message Batch.
  • */
  • id: string;
  • /**
    • Deleted object type.
    • For Message Batches, this is always "message_batch_deleted".
  • */
  • type: 'message_batch_deleted';
    +}

export interface BetaMessageBatch {
/**
* Unique object identifier.
@@ -374,6 +418,13 @@ export interface BatchListParams extends PageParams {
betas?: Array<BetaAPI.AnthropicBeta>;
}

+export interface BatchDeleteParams {

  • /**
    • Optional header to specify the beta version(s) you want to use.
  • */
  • betas?: Array<BetaAPI.AnthropicBeta>;
    +}

export interface BatchCancelParams {
/**
* Optional header to specify the beta version(s) you want to use.
@@ -392,6 +443,7 @@ Batches.BetaMessageBatchesPage = BetaMessageBatchesPage;

export declare namespace Batches {
export {

  • type BetaDeletedMessageBatch as BetaDeletedMessageBatch,
    type BetaMessageBatch as BetaMessageBatch,
    type BetaMessageBatchCanceledResult as BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult as BetaMessageBatchErroredResult,
    @@ -404,6 +456,7 @@ export declare namespace Batches {
    type BatchCreateParams as BatchCreateParams,
    type BatchRetrieveParams as BatchRetrieveParams,
    type BatchListParams as BatchListParams,
  • type BatchDeleteParams as BatchDeleteParams,
    type BatchCancelParams as BatchCancelParams,
    type BatchResultsParams as BatchResultsParams,
    };
    diff --git src/resources/beta/messages/index.ts src/resources/beta/messages/index.ts
    index 2cf85964..eac5d34f 100644
    --- src/resources/beta/messages/index.ts
    +++ src/resources/beta/messages/index.ts
    @@ -3,6 +3,7 @@
    export {
    BetaMessageBatchesPage,
    Batches,
  • type BetaDeletedMessageBatch,
    type BetaMessageBatch,
    type BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult,
    @@ -14,6 +15,7 @@ export {
    type BatchCreateParams,
    type BatchRetrieveParams,
    type BatchListParams,
  • type BatchDeleteParams,
    type BatchCancelParams,
    type BatchResultsParams,
    } from './batches';
    @@ -58,4 +60,5 @@ export {
    type MessageCreateParamsNonStreaming,
    type MessageCreateParamsStreaming,
    type MessageCountTokensParams,
  • type BetaMessageStreamParams,
    } from './messages';
    diff --git src/resources/beta/messages/messages.ts src/resources/beta/messages/messages.ts
    index 186a6c36..ecb1d79f 100644
    --- src/resources/beta/messages/messages.ts
    +++ src/resources/beta/messages/messages.ts
    @@ -10,10 +10,12 @@ import * as BatchesAPI from './batches';
    import {
    BatchCancelParams,
    BatchCreateParams,
  • BatchDeleteParams,
    BatchListParams,
    BatchResultsParams,
    BatchRetrieveParams,
    Batches,
  • BetaDeletedMessageBatch,
    BetaMessageBatch,
    BetaMessageBatchCanceledResult,
    BetaMessageBatchErroredResult,
    @@ -25,6 +27,21 @@ import {
    BetaMessageBatchesPage,
    } from './batches';
    import { Stream } from '../../../streaming';
    +import { BetaMessageStream } from '../../../lib/BetaMessageStream';
    +import type { Model } from '../../messages/messages';

+const DEPRECATED_MODELS: {

  • [K in Model]?: string;
    +} = {
  • 'claude-1.3': 'November 6th, 2024',
  • 'claude-1.3-100k': 'November 6th, 2024',
  • 'claude-instant-1.1': 'November 6th, 2024',
  • 'claude-instant-1.1-100k': 'November 6th, 2024',
  • 'claude-instant-1.2': 'November 6th, 2024',
  • 'claude-3-sonnet-20240229': 'July 21st, 2025',
  • 'claude-2.1': 'July 21st, 2025',
  • 'claude-2.0': 'July 21st, 2025',
    +};

export class Messages extends APIResource {
batches: BatchesAPI.Batches = new BatchesAPI.Batches(this._client);
@@ -50,6 +67,15 @@ export class Messages extends APIResource {
options?: Core.RequestOptions,
): APIPromise | APIPromise<Stream> {
const { betas, ...body } = params;
+

  • if (body.model in DEPRECATED_MODELS) {

  •  console.warn(
    
  •    `The model '${body.model}' is deprecated and will reach end-of-life on ${
    
  •      DEPRECATED_MODELS[body.model]
    
  •    }\nPlease migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resources/model-deprecations for more information.`,
    
  •  );
    
  • }

  • return this._client.post('/v1/messages?beta=true', {
    body,
    timeout: (this._client as any)._options.timeout ?? 600000,
    @@ -62,6 +88,13 @@ export class Messages extends APIResource {
    }) as APIPromise | APIPromise<Stream>;
    }

  • /**

    • Create a Message stream
  • */

  • stream(body: BetaMessageStreamParams, options?: Core.RequestOptions): BetaMessageStream {

  • return BetaMessageStream.createMessage(this, body, options);

  • }

  • /**

    • Count the number of tokens in a Message.

@@ -84,6 +117,8 @@ export class Messages extends APIResource {
}
}

+export type BetaMessageStreamParams = MessageCreateParamsBase;
+
export interface BetaBase64PDFBlock {
source: BetaBase64PDFSource;

@@ -1115,6 +1150,7 @@ export declare namespace Messages {

export {
Batches as Batches,

  • type BetaDeletedMessageBatch as BetaDeletedMessageBatch,
    type BetaMessageBatch as BetaMessageBatch,
    type BetaMessageBatchCanceledResult as BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult as BetaMessageBatchErroredResult,
    @@ -1127,6 +1163,7 @@ export declare namespace Messages {
    type BatchCreateParams as BatchCreateParams,
    type BatchRetrieveParams as BatchRetrieveParams,
    type BatchListParams as BatchListParams,

  • type BatchDeleteParams as BatchDeleteParams,
    type BatchCancelParams as BatchCancelParams,
    type BatchResultsParams as BatchResultsParams,
    };
    diff --git src/resources/messages/batches.ts src/resources/messages/batches.ts
    index b4fd45e8..a6b328e2 100644
    --- src/resources/messages/batches.ts
    +++ src/resources/messages/batches.ts
    @@ -49,6 +49,15 @@ export class Batches extends APIResource {
    return this._client.getAPIList('/v1/messages/batches', MessageBatchesPage, { query, ...options });
    }

  • /**

    • This endpoint is idempotent and can be used to poll for Message Batch
    • completion. To access the results of a Message Batch, make a request to the
    • results_url field in the response.
  • */

  • delete(messageBatchId: string, options?: Core.RequestOptions): Core.APIPromise {

  • return this._client.delete(/v1/messages/batches/${messageBatchId}, options);

  • }

  • /**

    • Batches may be canceled any time before processing ends. Once cancellation is
    • initiated, the batch enters a canceling state, at which time the system may
      @@ -83,13 +92,34 @@ export class Batches extends APIResource {
      }

    return this._client

  •  .get(batch.results_url, { ...options, __binaryResponse: true })
    
  •  .get(batch.results_url, {
    
  •    ...options,
    
  •    headers: {
    
  •      Accept: 'application/binary',
    
  •      ...options?.headers,
    
  •    },
    
  •    __binaryResponse: true,
    
  •  })
     ._thenUnwrap((_, props) => JSONLDecoder.fromResponse(props.response, props.controller));
    
    }
    }

export class MessageBatchesPage extends Page {}

+export interface DeletedMessageBatch {

  • /**
    • ID of the Message Batch.
  • */
  • id: string;
  • /**
    • Deleted object type.
    • For Message Batches, this is always "message_batch_deleted".
  • */
  • type: 'message_batch_deleted';
    +}

export interface MessageBatch {
/**
* Unique object identifier.
@@ -283,6 +313,7 @@ Batches.MessageBatchesPage = MessageBatchesPage;

export declare namespace Batches {
export {

  • type DeletedMessageBatch as DeletedMessageBatch,
    type MessageBatch as MessageBatch,
    type MessageBatchCanceledResult as MessageBatchCanceledResult,
    type MessageBatchErroredResult as MessageBatchErroredResult,
    diff --git src/resources/messages/index.ts src/resources/messages/index.ts
    index 10308d2a..1c9178ad 100644
    --- src/resources/messages/index.ts
    +++ src/resources/messages/index.ts
    @@ -3,6 +3,7 @@
    export {
    MessageBatchesPage,
    Batches,
  • type DeletedMessageBatch,
    type MessageBatch,
    type MessageBatchCanceledResult,
    type MessageBatchErroredResult,
    diff --git src/resources/messages/messages.ts src/resources/messages/messages.ts
    index a1affbf5..12cc9b83 100644
    --- src/resources/messages/messages.ts
    +++ src/resources/messages/messages.ts
    @@ -9,6 +9,7 @@ import {
    BatchCreateParams,
    BatchListParams,
    Batches,
  • DeletedMessageBatch,
    MessageBatch,
    MessageBatchCanceledResult,
    MessageBatchErroredResult,
    @@ -308,16 +309,17 @@ export type Model =
    | 'claude-2.1'
    | 'claude-2.0';

-type DeprecatedModelsType = {
+const DEPRECATED_MODELS: {
[K in Model]?: string;
-};

-const DEPRECATED_MODELS: DeprecatedModelsType = {
+} = {
'claude-1.3': 'November 6th, 2024',
'claude-1.3-100k': 'November 6th, 2024',
'claude-instant-1.1': 'November 6th, 2024',
'claude-instant-1.1-100k': 'November 6th, 2024',
'claude-instant-1.2': 'November 6th, 2024',

  • 'claude-3-sonnet-20240229': 'July 21st, 2025',
  • 'claude-2.1': 'July 21st, 2025',
  • 'claude-2.0': 'July 21st, 2025',
    };

export interface RawContentBlockDeltaEvent {
@@ -1114,6 +1116,7 @@ export declare namespace Messages {

export {
Batches as Batches,

  • type DeletedMessageBatch as DeletedMessageBatch,
    type MessageBatch as MessageBatch,
    type MessageBatchCanceledResult as MessageBatchCanceledResult,
    type MessageBatchErroredResult as MessageBatchErroredResult,
    diff --git src/version.ts src/version.ts
    index 4a46c186..3f1d4329 100644
    --- src/version.ts
    +++ src/version.ts
    @@ -1 +1 @@
    -export const VERSION = '0.33.1'; // x-release-please-version
    +export const VERSION = '0.35.0'; // x-release-please-version
    diff --git tests/api-resources/beta/messages/batches.test.ts tests/api-resources/beta/messages/batches.test.ts
    index e395910a..98d39506 100644
    --- tests/api-resources/beta/messages/batches.test.ts
    +++ tests/api-resources/beta/messages/batches.test.ts
    @@ -60,7 +60,7 @@ describe('resource batches', () => {
    },
    },
    },
  •            name: 'x',
    
  •            name: 'name',
               cache_control: { type: 'ephemeral' },
               description: 'Get the current weather in a given location',
               type: 'custom',
    

@@ -132,6 +132,35 @@ describe('resource batches', () => {
).rejects.toThrow(Anthropic.NotFoundError);
});

  • test('delete', async () => {
  • const responsePromise = client.beta.messages.batches.delete('message_batch_id');
  • const rawResponse = await responsePromise.asResponse();
  • expect(rawResponse).toBeInstanceOf(Response);
  • const response = await responsePromise;
  • expect(response).not.toBeInstanceOf(Response);
  • const dataAndResponse = await responsePromise.withResponse();
  • expect(dataAndResponse.data).toBe(response);
  • expect(dataAndResponse.response).toBe(rawResponse);
  • });
  • test('delete: request options instead of params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.beta.messages.batches.delete('message_batch_id', { path: '/_stainless_unknown_path' }),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('delete: request options and params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.beta.messages.batches.delete(
    
  •    'message_batch_id',
    
  •    { betas: ['string'] },
    
  •    { path: '/_stainless_unknown_path' },
    
  •  ),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('cancel', async () => {
    const responsePromise = client.beta.messages.batches.cancel('message_batch_id');
    const rawResponse = await responsePromise.asResponse();
    diff --git tests/api-resources/beta/messages/messages.test.ts tests/api-resources/beta/messages/messages.test.ts
    index ec73d9c0..493de962 100644
    --- tests/api-resources/beta/messages/messages.test.ts
    +++ tests/api-resources/beta/messages/messages.test.ts
    @@ -44,7 +44,7 @@ describe('resource messages', () => {
    unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
    },
    },
  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
         type: 'custom',
    

@@ -85,7 +85,7 @@ describe('resource messages', () => {
unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
},
},

  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
         type: 'custom',
    

diff --git tests/api-resources/messages/batches.test.ts tests/api-resources/messages/batches.test.ts
index 26efdbc8..4137fa31 100644
--- tests/api-resources/messages/batches.test.ts
+++ tests/api-resources/messages/batches.test.ts
@@ -59,7 +59,7 @@ describe('resource batches', () => {
},
},
},

  •            name: 'x',
    
  •            name: 'name',
               cache_control: { type: 'ephemeral' },
               description: 'Get the current weather in a given location',
             },
    

@@ -118,6 +118,24 @@ describe('resource batches', () => {
).rejects.toThrow(Anthropic.NotFoundError);
});

  • test('delete', async () => {
  • const responsePromise = client.messages.batches.delete('message_batch_id');
  • const rawResponse = await responsePromise.asResponse();
  • expect(rawResponse).toBeInstanceOf(Response);
  • const response = await responsePromise;
  • expect(response).not.toBeInstanceOf(Response);
  • const dataAndResponse = await responsePromise.withResponse();
  • expect(dataAndResponse.data).toBe(response);
  • expect(dataAndResponse.response).toBe(rawResponse);
  • });
  • test('delete: request options instead of params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.messages.batches.delete('message_batch_id', { path: '/_stainless_unknown_path' }),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('cancel', async () => {
    const responsePromise = client.messages.batches.cancel('message_batch_id');
    const rawResponse = await responsePromise.asResponse();
    diff --git tests/api-resources/messages/messages.test.ts tests/api-resources/messages/messages.test.ts
    index 3ae41d32..7b9d6f96 100644
    --- tests/api-resources/messages/messages.test.ts
    +++ tests/api-resources/messages/messages.test.ts
    @@ -44,7 +44,7 @@ describe('resource messages', () => {
    unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
    },
    },
  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
       },
    

@@ -83,7 +83,7 @@ describe('resource messages', () => {
unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
},
},

  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
       },
    

diff --git tests/index.test.ts tests/index.test.ts
index b6398085..bc0c1645 100644
--- tests/index.test.ts
+++ tests/index.test.ts
@@ -96,6 +96,15 @@ describe('instantiate client', () => {
expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true });
});

  • test('explicit global fetch', async () => {

  • // make sure the global fetch type is assignable to our Fetch type

  • const client = new Anthropic({

  •  baseURL: 'http://localhost:5000/',
    
  •  apiKey: 'my-anthropic-api-key',
    
  •  fetch: defaultFetch,
    
  • });

  • });

  • test('custom signal', async () => {
    const client = new Anthropic({
    baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
    @@ -122,6 +131,23 @@ describe('instantiate client', () => {
    expect(spy).toHaveBeenCalledTimes(1);
    });

  • test('normalized method', async () => {

  • let capturedRequest: RequestInit | undefined;

  • const testFetch = async (url: RequestInfo, init: RequestInit = {}): Promise => {

  •  capturedRequest = init;
    
  •  return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } });
    
  • };

  • const client = new Anthropic({

  •  baseURL: 'http://localhost:5000/',
    
  •  apiKey: 'my-anthropic-api-key',
    
  •  fetch: testFetch,
    
  • });

  • await client.patch('/foo');

  • expect(capturedRequest?.method).toEqual('PATCH');

  • });

  • describe('baseUrl', () => {
    test('trailing slash', () => {
    const client = new Anthropic({


</details>

### Description
This PR includes several significant updates to the Anthropic TypeScript SDK, including API enhancements, bug fixes, and new functionality. The main changes include adding beta message streaming helpers, request ID support, new message batch endpoints, and model deprecation notices.

<details>
<summary><i>Changes</i></summary>

### Changes
By filename:

1. `src/lib/BetaMessageStream.ts` (New file):
- Added new beta message streaming implementation
- Includes support for event handling and message accumulation
- Provides better TypeScript typings for streaming responses

2. `src/lib/MessageStream.ts`:
- Added request ID support
- Added `withResponse()` method for accessing raw response data
- Improved stream handling and error management

3. `src/resources/messages/batches.ts`:
- Added new delete endpoint for message batches
- Added proper Accept header for binary responses
- Added new `DeletedMessageBatch` type

4. `src/resources/messages/messages.ts`:
- Added deprecation notices for older Claude models
- Updated model types and interfaces
- Improved error handling and type definitions

5. Documentation updates:
- Added alpha version callout in README
- Updated examples and fixed typos
- Improved API documentation

```mermaid
sequenceDiagram
    participant Client
    participant MessageStream
    participant APIClient
    participant AnthropicAPI

    Client->>MessageStream: create(messages, params)
    MessageStream->>APIClient: POST /v1/messages
    APIClient->>AnthropicAPI: HTTP Request
    AnthropicAPI-->>APIClient: Stream Response
    
    loop For each chunk
        APIClient-->>MessageStream: Process Stream Event
        MessageStream-->>Client: Emit Event
    end
    
    MessageStream->>Client: Final Message

Security Hotspots

  1. Token Management: The changes include new token counting functionality - ensure proper validation is in place to prevent token manipulation attacks.
  2. Stream Processing: New streaming functionality should be monitored for potential memory leaks or DOS vectors when handling large streams.

Possible Issues

  1. Backward Compatibility: The deprecation of several Claude models may impact existing implementations.
  2. Stream Memory Usage: The new streaming implementation should be tested with large datasets to ensure proper memory management.

Copy link

bedrock debug - [puLL-Merge] - anthropics/[email protected]

Diff
diff --git .release-please-manifest.json .release-please-manifest.json
index 2053c67b..cb210381 100644
--- .release-please-manifest.json
+++ .release-please-manifest.json
@@ -1,5 +1,5 @@
 {
-  ".": "0.33.1",
-  "packages/vertex-sdk": "0.6.1",
-  "packages/bedrock-sdk": "0.12.0"
+  ".": "0.35.0",
+  "packages/vertex-sdk": "0.6.3",
+  "packages/bedrock-sdk": "0.12.2"
 }
diff --git .stats.yml .stats.yml
index 19e9daeb..239e17b7 100644
--- .stats.yml
+++ .stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 19
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-be055148d227480fcacc9086c37ac8009dcb487731069ada51af35044f65bee4.yml
+configured_endpoints: 21
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-fd67aea6883f1ee9e46f31a42d3940f0acb1749e787055bd9b9f278b20fa53ec.yml
diff --git CHANGELOG.md CHANGELOG.md
index a1a57c52..499e576c 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -1,5 +1,63 @@
 # Changelog
 
+## 0.35.0 (2025-01-21)
+
+Full Changelog: [sdk-v0.34.0...sdk-v0.35.0](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.34.0...sdk-v0.35.0)
+
+### Features
+
+* add beta message streaming helpers ([#655](https://github.com/anthropics/anthropic-sdk-typescript/issues/655)) ([d7b5af1](https://github.com/anthropics/anthropic-sdk-typescript/commit/d7b5af1629dbcefdb7bfdca271ab497567830227))
+* **stream:** add `.withResponse()` ([#654](https://github.com/anthropics/anthropic-sdk-typescript/issues/654)) ([b54477f](https://github.com/anthropics/anthropic-sdk-typescript/commit/b54477f20c92db4c2c5ed89af5d46c36b035bf1e))
+* **streaming:** add `.request_id` getter ([4572478](https://github.com/anthropics/anthropic-sdk-typescript/commit/4572478266a67e12e32ffef69817cbc495943b1d))
+
+
+### Bug Fixes
+
+* **docs:** correct results return type ([#657](https://github.com/anthropics/anthropic-sdk-typescript/issues/657)) ([4e6d031](https://github.com/anthropics/anthropic-sdk-typescript/commit/4e6d031a41625ebf9c4311638e0c149179fcae0c))
+* **examples:** add token counting example ([2498e2e](https://github.com/anthropics/anthropic-sdk-typescript/commit/2498e2eaf49d66a664ed1fdcd7bbd331979cf5b2))
+* send correct Accept header for certain endpoints ([#651](https://github.com/anthropics/anthropic-sdk-typescript/issues/651)) ([17ffaeb](https://github.com/anthropics/anthropic-sdk-typescript/commit/17ffaeba5af48d13b08483973b82cfe1ae79347f))
+* **vertex:** add beta.messages.countTokens method ([51d3f23](https://github.com/anthropics/anthropic-sdk-typescript/commit/51d3f23a7cc1bea798cc8e4041e08114ebc3a4eb))
+
+
+### Chores
+
+* deprecate more models ([661f5f9](https://github.com/anthropics/anthropic-sdk-typescript/commit/661f5f9d9b24f3661df246dcf101dd9812b3e19e))
+* **internal:** add test ([#660](https://github.com/anthropics/anthropic-sdk-typescript/issues/660)) ([3ec7d1a](https://github.com/anthropics/anthropic-sdk-typescript/commit/3ec7d1a9eea30255b24cdb16c1a26705bdfea0ac))
+* **internal:** temporary revert commit ([#643](https://github.com/anthropics/anthropic-sdk-typescript/issues/643)) ([43dd43c](https://github.com/anthropics/anthropic-sdk-typescript/commit/43dd43c4c8ab69d5a60e59473af7dff5f7799048))
+* **internal:** update examples ([#649](https://github.com/anthropics/anthropic-sdk-typescript/issues/649)) ([036a239](https://github.com/anthropics/anthropic-sdk-typescript/commit/036a239800fec7e6cbc439f125101d5475eae5b3))
+* **types:** add `| undefined` to client options properties ([#656](https://github.com/anthropics/anthropic-sdk-typescript/issues/656)) ([d642298](https://github.com/anthropics/anthropic-sdk-typescript/commit/d642298334529ff95b9d7ac497d548a6b04dbcfb))
+
+
+### Documentation
+
+* **readme:** fix misplaced period ([#650](https://github.com/anthropics/anthropic-sdk-typescript/issues/650)) ([8754744](https://github.com/anthropics/anthropic-sdk-typescript/commit/87547448c8b4bf69a61756af1f12927f33b68680))
+* **readme:** fix Request IDs example ([#659](https://github.com/anthropics/anthropic-sdk-typescript/issues/659)) ([6d3162d](https://github.com/anthropics/anthropic-sdk-typescript/commit/6d3162da1ddb964b75e575376f278468ba1ed9f5))
+
+## 0.34.0 (2024-12-20)
+
+Full Changelog: [sdk-v0.33.1...sdk-v0.34.0](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.33.1...sdk-v0.34.0)
+
+### Features
+
+* **api:** add message batch delete endpoint ([#640](https://github.com/anthropics/anthropic-sdk-typescript/issues/640)) ([54f7e1f](https://github.com/anthropics/anthropic-sdk-typescript/commit/54f7e1ffb9a2956ee27a4a715b84717aa681eb7c))
+
+
+### Bug Fixes
+
+* **client:** normalize method ([#639](https://github.com/anthropics/anthropic-sdk-typescript/issues/639)) ([384bb04](https://github.com/anthropics/anthropic-sdk-typescript/commit/384bb042dd854ed753c6bd8e25f522d0e042bfbf))
+
+
+### Chores
+
+* bump testing data uri ([#637](https://github.com/anthropics/anthropic-sdk-typescript/issues/637)) ([3f23530](https://github.com/anthropics/anthropic-sdk-typescript/commit/3f23530fb55d9fec7278967ea02600e44e9f58e2))
+* **internal:** temporary revert commit ([#643](https://github.com/anthropics/anthropic-sdk-typescript/issues/643)) ([8057b1e](https://github.com/anthropics/anthropic-sdk-typescript/commit/8057b1eb67ccccee042a45f2efe53cccced15682))
+
+
+### Documentation
+
+* minor formatting changes ([#641](https://github.com/anthropics/anthropic-sdk-typescript/issues/641)) ([8b362ee](https://github.com/anthropics/anthropic-sdk-typescript/commit/8b362ee72954b31b4de920b35aed97255efa5e2e))
+* **readme:** add alpha callout ([#646](https://github.com/anthropics/anthropic-sdk-typescript/issues/646)) ([640304c](https://github.com/anthropics/anthropic-sdk-typescript/commit/640304c7c7e8bc67cbf799a646169736d89ad4c8))
+
 ## 0.33.1 (2024-12-17)
 
 Full Changelog: [sdk-v0.33.0...sdk-v0.33.1](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.33.0...sdk-v0.33.1)
diff --git CONTRIBUTING.md CONTRIBUTING.md
index 9a869b0f..7d94b319 100644
--- CONTRIBUTING.md
+++ CONTRIBUTING.md
@@ -1,6 +1,6 @@
 ## Setting up the environment
 
-This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable).
+This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install).
 Other package managers may work but are not officially supported for development.
 
 To set up the repository, run:
@@ -29,10 +29,10 @@ All files in the `examples/` directory are not modified by the generator and can
 …
 \`\`\`
 
-```
-chmod +x examples/<your-example>.ts
+```sh
+$ chmod +x examples/<your-example>.ts
 # run the example against your api
-yarn tsn -T examples/<your-example>.ts
+$ yarn tsn -T examples/<your-example>.ts

Using the repository from source

diff --git README.md README.md
index da3db48e..fac24b92 100644
--- README.md
+++ README.md
@@ -1,3 +1,9 @@
+> [!IMPORTANT]
+> We're actively working on a new alpha version that migrates from node-fetch to builtin fetch.
+>
+> Please try it out and let us know if you run into any issues!
+> anthropics/anthropic-sdk-typescript#645
+

Anthropic TypeScript API Library

NPM version npm bundle size
@@ -235,7 +241,7 @@ All object responses in the SDK provide a _request_id property which is added

const message = await client.messages.create({ max_tokens: 1024, messages: [{ role: 'user', content: 'Hello, Claude' }], model: 'claude-3-5-sonnet-latest' });
-console.log(completion._request_id) // req_018EeWyXxfu5pfWkrYcMdjWG
+console.log(message._request_id) // req_018EeWyXxfu5pfWkrYcMdjWG

@@ -486,7 +492,7 @@ await client.messages.create(
This package generally follows SemVer conventions, though certain backwards-incompatible changes may be released as minor versions:

  1. Changes that only affect static types, without breaking runtime behavior.
    -2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals).
    +2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals.)
  2. Changes that we do not expect to impact the vast majority of users in practice.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
diff --git api.md api.md
index 48d1c9a8..9aed2e92 100644
--- api.md
+++ api.md
@@ -70,6 +70,7 @@ Methods:

Types:

+- DeletedMessageBatch

  • MessageBatch
  • MessageBatchCanceledResult
  • MessageBatchErroredResult
    @@ -84,8 +85,9 @@ Methods:
  • client.messages.batches.create({ ...params }) -> MessageBatch
  • client.messages.batches.retrieve(messageBatchId) -> MessageBatch
  • client.messages.batches.list({ ...params }) -> MessageBatchesPage
    +- client.messages.batches.delete(messageBatchId) -> DeletedMessageBatch
  • client.messages.batches.cancel(messageBatchId) -> MessageBatch
    -- client.messages.batches.results(messageBatchId) -> Response
    +- client.messages.batches.results(messageBatchId) -> JSONLDecoder<MessageBatchIndividualResponse>

Models

@@ -175,6 +177,7 @@ Methods:

Types:

+- BetaDeletedMessageBatch

  • BetaMessageBatch
  • BetaMessageBatchCanceledResult
  • BetaMessageBatchErroredResult
    @@ -189,5 +192,6 @@ Methods:
  • client.beta.messages.batches.create({ ...params }) -> BetaMessageBatch
  • client.beta.messages.batches.retrieve(messageBatchId, { ...params }) -> BetaMessageBatch
  • client.beta.messages.batches.list({ ...params }) -> BetaMessageBatchesPage
    +- client.beta.messages.batches.delete(messageBatchId, { ...params }) -> BetaDeletedMessageBatch
  • client.beta.messages.batches.cancel(messageBatchId, { ...params }) -> BetaMessageBatch
    -- client.beta.messages.batches.results(messageBatchId, { ...params }) -> Response
    +- client.beta.messages.batches.results(messageBatchId, { ...params }) -> JSONLDecoder<MessageBatchIndividualResponse>
    diff --git examples/count-tokens.ts examples/count-tokens.ts
    index e69de29b..22fae1f1 100755
    --- examples/count-tokens.ts
    +++ examples/count-tokens.ts
    @@ -0,0 +1,20 @@
    +#!/usr/bin/env -S npm run tsn -T

+import Anthropic from '@anthropic-ai/sdk';
+
+const client = new Anthropic(); // gets API Key from environment variable ANTHROPIC_API_KEY
+
+async function main() {

  • const result = await client.messages.countTokens({
  • messages: [
  •  {
    
  •    role: 'user',
    
  •    content: 'Hey Claude!?',
    
  •  },
    
  • ],
  • model: 'claude-3-5-sonnet-latest',
  • });
  • console.dir(result);
    +}

+main();
diff --git package.json package.json
index d8f88f57..aa23123e 100644
--- package.json
+++ package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/sdk",

  • "version": "0.33.1",
  • "version": "0.35.0",
    "description": "The official TypeScript library for the Anthropic API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/bedrock-sdk/CHANGELOG.md packages/bedrock-sdk/CHANGELOG.md
    index 837af37e..12fec54c 100644
    --- packages/bedrock-sdk/CHANGELOG.md
    +++ packages/bedrock-sdk/CHANGELOG.md
    @@ -1,5 +1,21 @@

Changelog

+## 0.12.2 (2025-01-21)
+
+Full Changelog: bedrock-sdk-v0.12.1...bedrock-sdk-v0.12.2
+
+### Chores
+
+* internal: temporary revert commit (#643) (43dd43c)
+
+## 0.12.1 (2024-12-20)
+
+Full Changelog: bedrock-sdk-v0.12.0...bedrock-sdk-v0.12.1
+
+### Chores
+
+* internal: temporary revert commit (#643) (8057b1e)
+

0.12.0 (2024-12-17)

Full Changelog: bedrock-sdk-v0.11.2...bedrock-sdk-v0.12.0
diff --git packages/bedrock-sdk/package.json packages/bedrock-sdk/package.json
index 352931a5..8e7a906d 100644
--- packages/bedrock-sdk/package.json
+++ packages/bedrock-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/bedrock-sdk",

  • "version": "0.12.0",
  • "version": "0.12.2",
    "description": "The official TypeScript library for the Anthropic Bedrock API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/vertex-sdk/CHANGELOG.md packages/vertex-sdk/CHANGELOG.md
    index 94191164..e01d1d71 100644
    --- packages/vertex-sdk/CHANGELOG.md
    +++ packages/vertex-sdk/CHANGELOG.md
    @@ -1,5 +1,26 @@

Changelog

+## 0.6.3 (2025-01-21)
+
+Full Changelog: vertex-sdk-v0.6.2...vertex-sdk-v0.6.3
+
+### Bug Fixes
+
+* vertex: add beta.messages.countTokens method (51d3f23)
+
+
+### Chores
+
+* internal: temporary revert commit (#643) (43dd43c)
+
+## 0.6.2 (2024-12-20)
+
+Full Changelog: vertex-sdk-v0.6.1...vertex-sdk-v0.6.2
+
+### Chores
+
+* internal: temporary revert commit (#643) (8057b1e)
+

0.6.1 (2024-12-17)

Full Changelog: vertex-sdk-v0.6.0...vertex-sdk-v0.6.1
diff --git packages/vertex-sdk/package.json packages/vertex-sdk/package.json
index 43fc356d..ae4cf6f9 100644
--- packages/vertex-sdk/package.json
+++ packages/vertex-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/vertex-sdk",

  • "version": "0.6.1",
  • "version": "0.6.3",
    "description": "The official TypeScript library for the Anthropic Vertex API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/vertex-sdk/src/client.ts packages/vertex-sdk/src/client.ts
    index f1046455..0f8a1626 100644
    --- packages/vertex-sdk/src/client.ts
    +++ packages/vertex-sdk/src/client.ts
    @@ -179,23 +179,17 @@ function makeMessagesResource(client: AnthropicVertex): MessagesResource {
    }

/**

    • The Vertex API does not currently support prompt caching, token counting or the Batch API.
    • The Vertex API does not currently support the Batch API.
      */
      -type BetaResource = Omit<Resources.Beta, 'promptCaching' | 'messages'> & {
  • messages: Omit<Resources.Beta['messages'], 'batches' | 'countTokens'>;
    +type BetaResource = Omit<Resources.Beta, 'messages'> & {
  • messages: Omit<Resources.Beta['messages'], 'batches'>;
    };

function makeBetaResource(client: AnthropicVertex): BetaResource {
const resource = new Resources.Beta(client);

  • // @ts-expect-error we're deleting non-optional properties

  • delete resource.promptCaching;

  • // @ts-expect-error we're deleting non-optional properties
    delete resource.messages.batches;

  • // @ts-expect-error we're deleting non-optional properties

  • delete resource.messages.countTokens;

  • return resource;
    }
    diff --git src/core.ts src/core.ts
    index ea8d8dca..344bf6ac 100644
    --- src/core.ts
    +++ src/core.ts
    @@ -556,9 +556,19 @@ export abstract class APIClient {

    const timeout = setTimeout(() => controller.abort(), ms);

  • const fetchOptions = {
  •  signal: controller.signal as any,
    
  •  ...options,
    
  • };
  • if (fetchOptions.method) {
  •  // Custom methods like 'patch' need to be uppercased
    
  •  // See https://github.com/nodejs/undici/issues/2294
    
  •  fetchOptions.method = fetchOptions.method.toUpperCase();
    
  • }
  • return (
    // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
  •  this.fetch.call(undefined, url, { signal: controller.signal as any, ...options }).finally(() => {
    
  •  this.fetch.call(undefined, url, fetchOptions).finally(() => {
       clearTimeout(timeout);
     })
    
    );
    diff --git src/index.ts src/index.ts
    index bfca4fc8..44f6bc2d 100644
    --- src/index.ts
    +++ src/index.ts
    @@ -103,7 +103,7 @@ export interface ClientOptions {
    • Note that request timeouts are retried by default, so in a worst-case scenario you may wait
    • much longer than this timeout before the promise succeeds or fails.
      */
  • timeout?: number;
  • timeout?: number | undefined;

    /**

    • An HTTP agent used to manage HTTP(S) connections.
      @@ -111,7 +111,7 @@ export interface ClientOptions {
    • If not provided, an agent will be constructed by default in the Node.js environment,
    • otherwise no agent is used.
      */
  • httpAgent?: Agent;
  • httpAgent?: Agent | undefined;

    /**

    • Specify a custom fetch function implementation.
      @@ -127,7 +127,7 @@ export interface ClientOptions {
    • @default 2
      */
  • maxRetries?: number;
  • maxRetries?: number | undefined;

    /**

    • Default headers to include with every request to the API.
      @@ -135,7 +135,7 @@ export interface ClientOptions {
    • These can be removed in individual requests by explicitly setting the
    • header to undefined or null in request options.
      */
  • defaultHeaders?: Core.Headers;
  • defaultHeaders?: Core.Headers | undefined;

    /**

    • Default query parameters to include with every request to the API.
      @@ -143,13 +143,13 @@ export interface ClientOptions {
    • These can be removed in individual requests by explicitly setting the
    • param to undefined in request options.
      */
  • defaultQuery?: Core.DefaultQuery;
  • defaultQuery?: Core.DefaultQuery | undefined;

    /**

    • By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
    • Only set this option to true if you understand the risks and have appropriate mitigations in place.
      */
  • dangerouslyAllowBrowser?: boolean;
  • dangerouslyAllowBrowser?: boolean | undefined;
    }

/**
diff --git a/src/lib/BetaMessageStream.ts b/src/lib/BetaMessageStream.ts
new file mode 100644
index 00000000..06fbc46a
--- /dev/null
+++ src/lib/BetaMessageStream.ts
@@ -0,0 +1,593 @@
+import * as Core from '@anthropic-ai/sdk/core';
+import { AnthropicError, APIUserAbortError } from '@anthropic-ai/sdk/error';
+import {

  • type BetaContentBlock,
  • Messages as BetaMessages,
  • type BetaMessage,
  • type BetaRawMessageStreamEvent as BetaMessageStreamEvent,
  • type BetaMessageParam,
  • type MessageCreateParams as BetaMessageCreateParams,
  • type MessageCreateParamsBase as BetaMessageCreateParamsBase,
  • type BetaTextBlock,
    +} from '@anthropic-ai/sdk/resources/beta/messages/messages';
    +import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index';
    +import { Stream } from '@anthropic-ai/sdk/streaming';
    +import { partialParse } from '../_vendor/partial-json-parser/parser';

+export interface MessageStreamEvents {

  • connect: () => void;
  • streamEvent: (event: BetaMessageStreamEvent, snapshot: BetaMessage) => void;
  • text: (textDelta: string, textSnapshot: string) => void;
  • inputJson: (partialJson: string, jsonSnapshot: unknown) => void;
  • message: (message: BetaMessage) => void;
  • contentBlock: (content: BetaContentBlock) => void;
  • finalMessage: (message: BetaMessage) => void;
  • error: (error: AnthropicError) => void;
  • abort: (error: APIUserAbortError) => void;
  • end: () => void;
    +}

+type MessageStreamEventListeners = {

  • listener: MessageStreamEvents[Event];
  • once?: boolean;
    +}[];

+const JSON_BUF_PROPERTY = '__json_buf';
+
+export class BetaMessageStream implements AsyncIterable {

  • messages: BetaMessageParam[] = [];
  • receivedMessages: BetaMessage[] = [];
  • #currentMessageSnapshot: BetaMessage | undefined;
  • controller: AbortController = new AbortController();
  • #connectedPromise: Promise<Response | null>;
  • #resolveConnectedPromise: (response: Response | null) => void = () => {};
  • #rejectConnectedPromise: (error: AnthropicError) => void = () => {};
  • #endPromise: Promise;
  • #resolveEndPromise: () => void = () => {};
  • #rejectEndPromise: (error: AnthropicError) => void = () => {};
  • #listeners: { [Event in keyof MessageStreamEvents]?: MessageStreamEventListeners } = {};
  • #ended = false;
  • #errored = false;
  • #aborted = false;
  • #catchingPromiseCreated = false;
  • #request_id: string | null | undefined;
  • constructor() {
  • this.#connectedPromise = new Promise<Response | null>((resolve, reject) => {
  •  this.#resolveConnectedPromise = resolve;
    
  •  this.#rejectConnectedPromise = reject;
    
  • });
  • this.#endPromise = new Promise((resolve, reject) => {
  •  this.#resolveEndPromise = resolve;
    
  •  this.#rejectEndPromise = reject;
    
  • });
  • // Don't let these promises cause unhandled rejection errors.
  • // we will manually cause an unhandled rejection error later
  • // if the user hasn't registered any error listener or called
  • // any promise-returning method.
  • this.#connectedPromise.catch(() => {});
  • this.#endPromise.catch(() => {});
  • }
  • get request_id(): string | null | undefined {
  • return this.#request_id;
  • }
  • /**
    • Returns the MessageStream data, the raw Response instance and the ID of the request,
    • returned vie the request-id header which is useful for debugging requests and resporting
    • issues to Anthropic.
    • This is the same as the APIPromise.withResponse() method.
    • This method will raise an error if you created the stream using MessageStream.fromReadableStream
    • as no Response is available.
  • */
  • async withResponse(): Promise<{
  • data: BetaMessageStream;
  • response: Response;
  • request_id: string | null | undefined;
  • }> {
  • const response = await this.#connectedPromise;
  • if (!response) {
  •  throw new Error('Could not resolve a `Response` object');
    
  • }
  • return {
  •  data: this,
    
  •  response,
    
  •  request_id: response.headers.get('request-id'),
    
  • };
  • }
  • /**
    • Intended for use on the frontend, consuming a stream produced with
    • .toReadableStream() on the backend.
    • Note that messages sent to the model do not appear in .on('message')
    • in this context.
  • */
  • static fromReadableStream(stream: ReadableStream): BetaMessageStream {
  • const runner = new BetaMessageStream();
  • runner._run(() => runner._fromReadableStream(stream));
  • return runner;
  • }
  • static createMessage(
  • messages: BetaMessages,
  • params: BetaMessageCreateParamsBase,
  • options?: Core.RequestOptions,
  • ): BetaMessageStream {
  • const runner = new BetaMessageStream();
  • for (const message of params.messages) {
  •  runner._addMessageParam(message);
    
  • }
  • runner._run(() =>
  •  runner._createMessage(
    
  •    messages,
    
  •    { ...params, stream: true },
    
  •    { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } },
    
  •  ),
    
  • );
  • return runner;
  • }
  • protected _run(executor: () => Promise) {
  • executor().then(() => {
  •  this._emitFinal();
    
  •  this._emit('end');
    
  • }, this.#handleError);
  • }
  • protected _addMessageParam(message: BetaMessageParam) {
  • this.messages.push(message);
  • }
  • protected _addMessage(message: BetaMessage, emit = true) {
  • this.receivedMessages.push(message);
  • if (emit) {
  •  this._emit('message', message);
    
  • }
  • }
  • protected async _createMessage(
  • messages: BetaMessages,
  • params: BetaMessageCreateParams,
  • options?: Core.RequestOptions,
  • ): Promise {
  • const signal = options?.signal;
  • if (signal) {
  •  if (signal.aborted) this.controller.abort();
    
  •  signal.addEventListener('abort', () => this.controller.abort());
    
  • }
  • this.#beginRequest();
  • const { response, data: stream } = await messages
  •  .create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
    
  •  .withResponse();
    
  • this._connected(response);
  • for await (const event of stream) {
  •  this.#addStreamEvent(event);
    
  • }
  • if (stream.controller.signal?.aborted) {
  •  throw new APIUserAbortError();
    
  • }
  • this.#endRequest();
  • }
  • protected _connected(response: Response | null) {
  • if (this.ended) return;
  • this.#request_id = response?.headers.get('request-id');
  • this.#resolveConnectedPromise(response);
  • this._emit('connect');
  • }
  • get ended(): boolean {
  • return this.#ended;
  • }
  • get errored(): boolean {
  • return this.#errored;
  • }
  • get aborted(): boolean {
  • return this.#aborted;
  • }
  • abort() {
  • this.controller.abort();
  • }
  • /**
    • Adds the listener function to the end of the listeners array for the event.
    • No checks are made to see if the listener has already been added. Multiple calls passing
    • the same combination of event and listener will result in the listener being added, and
    • called, multiple times.
    • @returns this MessageStream, so that calls can be chained
  • */
  • on(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners: MessageStreamEventListeners =
  •  this.#listeners[event] || (this.#listeners[event] = []);
    
  • listeners.push({ listener });
  • return this;
  • }
  • /**
    • Removes the specified listener from the listener array for the event.
    • off() will remove, at most, one instance of a listener from the listener array. If any single
    • listener has been added multiple times to the listener array for the specified event, then
    • off() must be called multiple times to remove each instance.
    • @returns this MessageStream, so that calls can be chained
  • */
  • off(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners = this.#listeners[event];
  • if (!listeners) return this;
  • const index = listeners.findIndex((l) => l.listener === listener);
  • if (index >= 0) listeners.splice(index, 1);
  • return this;
  • }
  • /**
    • Adds a one-time listener function for the event. The next time the event is triggered,
    • this listener is removed and then invoked.
    • @returns this MessageStream, so that calls can be chained
  • */
  • once(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners: MessageStreamEventListeners =
  •  this.#listeners[event] || (this.#listeners[event] = []);
    
  • listeners.push({ listener, once: true });
  • return this;
  • }
  • /**
    • This is similar to .once(), but returns a Promise that resolves the next time
    • the event is triggered, instead of calling a listener callback.
    • @returns a Promise that resolves the next time given event is triggered,
    • or rejects if an error is emitted. (If you request the 'error' event,
    • returns a promise that resolves with the error).
    • Example:
    • const message = await stream.emitted('message') // rejects if the stream errors
  • */
  • emitted(
  • event: Event,
  • ): Promise<
  • Parameters<MessageStreamEvents[Event]> extends [infer Param] ? Param
  • : Parameters<MessageStreamEvents[Event]> extends [] ? void
  • : Parameters<MessageStreamEvents[Event]>
  • {

  • return new Promise((resolve, reject) => {
  •  this.#catchingPromiseCreated = true;
    
  •  if (event !== 'error') this.once('error', reject);
    
  •  this.once(event, resolve as any);
    
  • });
  • }
  • async done(): Promise {
  • this.#catchingPromiseCreated = true;
  • await this.#endPromise;
  • }
  • get currentMessage(): BetaMessage | undefined {
  • return this.#currentMessageSnapshot;
  • }
  • #getFinalMessage(): BetaMessage {
  • if (this.receivedMessages.length === 0) {
  •  throw new AnthropicError('stream ended without producing a Message with role=assistant');
    
  • }
  • return this.receivedMessages.at(-1)!;
  • }
  • /**
    • @returns a promise that resolves with the the final assistant Message response,
    • or rejects if an error occurred or the stream ended prematurely without producing a Message.
  • */
  • async finalMessage(): Promise {
  • await this.done();
  • return this.#getFinalMessage();
  • }
  • #getFinalText(): string {
  • if (this.receivedMessages.length === 0) {
  •  throw new AnthropicError('stream ended without producing a Message with role=assistant');
    
  • }
  • const textBlocks = this.receivedMessages
  •  .at(-1)!
    
  •  .content.filter((block): block is BetaTextBlock => block.type === 'text')
    
  •  .map((block) => block.text);
    
  • if (textBlocks.length === 0) {
  •  throw new AnthropicError('stream ended without producing a content block with type=text');
    
  • }
  • return textBlocks.join(' ');
  • }
  • /**
    • @returns a promise that resolves with the the final assistant Message's text response, concatenated
    • together if there are more than one text blocks.
    • Rejects if an error occurred or the stream ended prematurely without producing a Message.
  • */
  • async finalText(): Promise {
  • await this.done();
  • return this.#getFinalText();
  • }
  • #handleError = (error: unknown) => {
  • this.#errored = true;
  • if (error instanceof Error && error.name === 'AbortError') {
  •  error = new APIUserAbortError();
    
  • }
  • if (error instanceof APIUserAbortError) {
  •  this.#aborted = true;
    
  •  return this._emit('abort', error);
    
  • }
  • if (error instanceof AnthropicError) {
  •  return this._emit('error', error);
    
  • }
  • if (error instanceof Error) {
  •  const anthropicError: AnthropicError = new AnthropicError(error.message);
    
  •  // @ts-ignore
    
  •  anthropicError.cause = error;
    
  •  return this._emit('error', anthropicError);
    
  • }
  • return this._emit('error', new AnthropicError(String(error)));
  • };
  • protected _emit(
  • event: Event,
  • ...args: Parameters<MessageStreamEvents[Event]>
  • ) {
  • // make sure we don't emit any MessageStreamEvents after end
  • if (this.#ended) return;
  • if (event === 'end') {
  •  this.#ended = true;
    
  •  this.#resolveEndPromise();
    
  • }
  • const listeners: MessageStreamEventListeners | undefined = this.#listeners[event];
  • if (listeners) {
  •  this.#listeners[event] = listeners.filter((l) => !l.once) as any;
    
  •  listeners.forEach(({ listener }: any) => listener(...args));
    
  • }
  • if (event === 'abort') {
  •  const error = args[0] as APIUserAbortError;
    
  •  if (!this.#catchingPromiseCreated && !listeners?.length) {
    
  •    Promise.reject(error);
    
  •  }
    
  •  this.#rejectConnectedPromise(error);
    
  •  this.#rejectEndPromise(error);
    
  •  this._emit('end');
    
  •  return;
    
  • }
  • if (event === 'error') {
  •  // NOTE: _emit('error', error) should only be called from #handleError().
    
  •  const error = args[0] as AnthropicError;
    
  •  if (!this.#catchingPromiseCreated && !listeners?.length) {
    
  •    // Trigger an unhandled rejection if the user hasn't registered any error handlers.
    
  •    // If you are seeing stack traces here, make sure to handle errors via either:
    
  •    // - runner.on('error', () => ...)
    
  •    // - await runner.done()
    
  •    // - await runner.final...()
    
  •    // - etc.
    
  •    Promise.reject(error);
    
  •  }
    
  •  this.#rejectConnectedPromise(error);
    
  •  this.#rejectEndPromise(error);
    
  •  this._emit('end');
    
  • }
  • }
  • protected _emitFinal() {
  • const finalMessage = this.receivedMessages.at(-1);
  • if (finalMessage) {
  •  this._emit('finalMessage', this.#getFinalMessage());
    
  • }
  • }
  • #beginRequest() {
  • if (this.ended) return;
  • this.#currentMessageSnapshot = undefined;
  • }
  • #addStreamEvent(event: BetaMessageStreamEvent) {
  • if (this.ended) return;
  • const messageSnapshot = this.#accumulateMessage(event);
  • this._emit('streamEvent', event, messageSnapshot);
  • switch (event.type) {
  •  case 'content_block_delta': {
    
  •    const content = messageSnapshot.content.at(-1)!;
    
  •    if (event.delta.type === 'text_delta' && content.type === 'text') {
    
  •      this._emit('text', event.delta.text, content.text || '');
    
  •    } else if (event.delta.type === 'input_json_delta' && content.type === 'tool_use') {
    
  •      if (content.input) {
    
  •        this._emit('inputJson', event.delta.partial_json, content.input);
    
  •      }
    
  •    }
    
  •    break;
    
  •  }
    
  •  case 'message_stop': {
    
  •    this._addMessageParam(messageSnapshot);
    
  •    this._addMessage(messageSnapshot, true);
    
  •    break;
    
  •  }
    
  •  case 'content_block_stop': {
    
  •    this._emit('contentBlock', messageSnapshot.content.at(-1)!);
    
  •    break;
    
  •  }
    
  •  case 'message_start': {
    
  •    this.#currentMessageSnapshot = messageSnapshot;
    
  •    break;
    
  •  }
    
  •  case 'content_block_start':
    
  •  case 'message_delta':
    
  •    break;
    
  • }
  • }
  • #endRequest(): BetaMessage {
  • if (this.ended) {
  •  throw new AnthropicError(`stream has ended, this shouldn't happen`);
    
  • }
  • const snapshot = this.#currentMessageSnapshot;
  • if (!snapshot) {
  •  throw new AnthropicError(`request ended without sending any chunks`);
    
  • }
  • this.#currentMessageSnapshot = undefined;
  • return snapshot;
  • }
  • protected async _fromReadableStream(
  • readableStream: ReadableStream,
  • options?: Core.RequestOptions,
  • ): Promise {
  • const signal = options?.signal;
  • if (signal) {
  •  if (signal.aborted) this.controller.abort();
    
  •  signal.addEventListener('abort', () => this.controller.abort());
    
  • }
  • this.#beginRequest();
  • this._connected(null);
  • const stream = Stream.fromReadableStream(readableStream, this.controller);
  • for await (const event of stream) {
  •  this.#addStreamEvent(event);
    
  • }
  • if (stream.controller.signal?.aborted) {
  •  throw new APIUserAbortError();
    
  • }
  • this.#endRequest();
  • }
  • /**
    • Mutates this.#currentMessage with the current event. Handling the accumulation of multiple messages
    • will be needed to be handled by the caller, this method will throw if you try to accumulate for multiple
    • messages.
  • */
  • #accumulateMessage(event: BetaMessageStreamEvent): BetaMessage {
  • let snapshot = this.#currentMessageSnapshot;
  • if (event.type === 'message_start') {
  •  if (snapshot) {
    
  •    throw new AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
    
  •  }
    
  •  return event.message;
    
  • }
  • if (!snapshot) {
  •  throw new AnthropicError(`Unexpected event order, got ${event.type} before "message_start"`);
    
  • }
  • switch (event.type) {
  •  case 'message_stop':
    
  •    return snapshot;
    
  •  case 'message_delta':
    
  •    snapshot.stop_reason = event.delta.stop_reason;
    
  •    snapshot.stop_sequence = event.delta.stop_sequence;
    
  •    snapshot.usage.output_tokens = event.usage.output_tokens;
    
  •    return snapshot;
    
  •  case 'content_block_start':
    
  •    snapshot.content.push(event.content_block);
    
  •    return snapshot;
    
  •  case 'content_block_delta': {
    
  •    const snapshotContent = snapshot.content.at(event.index);
    
  •    if (snapshotContent?.type === 'text' && event.delta.type === 'text_delta') {
    
  •      snapshotContent.text += event.delta.text;
    
  •    } else if (snapshotContent?.type === 'tool_use' && event.delta.type === 'input_json_delta') {
    
  •      // we need to keep track of the raw JSON string as well so that we can
    
  •      // re-parse it for each delta, for now we just store it as an untyped
    
  •      // non-enumerable property on the snapshot
    
  •      let jsonBuf = (snapshotContent as any)[JSON_BUF_PROPERTY] || '';
    
  •      jsonBuf += event.delta.partial_json;
    
  •      Object.defineProperty(snapshotContent, JSON_BUF_PROPERTY, {
    
  •        value: jsonBuf,
    
  •        enumerable: false,
    
  •        writable: true,
    
  •      });
    
  •      if (jsonBuf) {
    
  •        snapshotContent.input = partialParse(jsonBuf);
    
  •      }
    
  •    }
    
  •    return snapshot;
    
  •  }
    
  •  case 'content_block_stop':
    
  •    return snapshot;
    
  • }
  • }
  • Symbol.asyncIterator: AsyncIterator {
  • const pushQueue: BetaMessageStreamEvent[] = [];
  • const readQueue: {
  •  resolve: (chunk: BetaMessageStreamEvent | undefined) => void;
    
  •  reject: (error: unknown) => void;
    
  • }[] = [];
  • let done = false;
  • this.on('streamEvent', (event) => {
  •  const reader = readQueue.shift();
    
  •  if (reader) {
    
  •    reader.resolve(event);
    
  •  } else {
    
  •    pushQueue.push(event);
    
  •  }
    
  • });
  • this.on('end', () => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.resolve(undefined);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • this.on('abort', (err) => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.reject(err);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • this.on('error', (err) => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.reject(err);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • return {
  •  next: async (): Promise<IteratorResult<BetaMessageStreamEvent>> => {
    
  •    if (!pushQueue.length) {
    
  •      if (done) {
    
  •        return { value: undefined, done: true };
    
  •      }
    
  •      return new Promise<BetaMessageStreamEvent | undefined>((resolve, reject) =>
    
  •        readQueue.push({ resolve, reject }),
    
  •      ).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true }));
    
  •    }
    
  •    const chunk = pushQueue.shift()!;
    
  •    return { value: chunk, done: false };
    
  •  },
    
  •  return: async () => {
    
  •    this.abort();
    
  •    return { value: undefined, done: true };
    
  •  },
    
  • };
  • }
  • toReadableStream(): ReadableStream {
  • const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
  • return stream.toReadableStream();
  • }
    +}
    diff --git src/lib/MessageStream.ts src/lib/MessageStream.ts
    index dea739f1..65e84b29 100644
    --- src/lib/MessageStream.ts
    +++ src/lib/MessageStream.ts
    @@ -10,7 +10,7 @@ import {
    type MessageCreateParamsBase,
    type TextBlock,
    } from '@anthropic-ai/sdk/resources/messages';
    -import { type ReadableStream } from '@anthropic-ai/sdk/_shims/index';
    +import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index';
    import { Stream } from '@anthropic-ai/sdk/streaming';
    import { partialParse } from '../_vendor/partial-json-parser/parser';

@@ -41,8 +41,8 @@ export class MessageStream implements AsyncIterable {

controller: AbortController = new AbortController();

  • #connectedPromise: Promise;
  • #resolveConnectedPromise: () => void = () => {};
  • #connectedPromise: Promise<Response | null>;

  • #resolveConnectedPromise: (response: Response | null) => void = () => {};
    #rejectConnectedPromise: (error: AnthropicError) => void = () => {};

    #endPromise: Promise;
    @@ -55,9 +55,10 @@ export class MessageStream implements AsyncIterable {
    #errored = false;
    #aborted = false;
    #catchingPromiseCreated = false;

  • #request_id: string | null | undefined;

    constructor() {

  • this.#connectedPromise = new Promise((resolve, reject) => {
  • this.#connectedPromise = new Promise<Response | null>((resolve, reject) => {
    this.#resolveConnectedPromise = resolve;
    this.#rejectConnectedPromise = reject;
    });
    @@ -75,6 +76,37 @@ export class MessageStream implements AsyncIterable {
    this.#endPromise.catch(() => {});
    }

  • get request_id(): string | null | undefined {

  • return this.#request_id;

  • }

  • /**

    • Returns the MessageStream data, the raw Response instance and the ID of the request,
    • returned vie the request-id header which is useful for debugging requests and resporting
    • issues to Anthropic.
    • This is the same as the APIPromise.withResponse() method.
    • This method will raise an error if you created the stream using MessageStream.fromReadableStream
    • as no Response is available.
  • */

  • async withResponse(): Promise<{

  • data: MessageStream;

  • response: Response;

  • request_id: string | null | undefined;

  • }> {

  • const response = await this.#connectedPromise;

  • if (!response) {

  •  throw new Error('Could not resolve a `Response` object');
    
  • }

  • return {

  •  data: this,
    
  •  response,
    
  •  request_id: response.headers.get('request-id'),
    
  • };

  • }

  • /**

    • Intended for use on the frontend, consuming a stream produced with
    • .toReadableStream() on the backend.
      @@ -136,11 +168,10 @@ export class MessageStream implements AsyncIterable {
      signal.addEventListener('abort', () => this.controller.abort());
      }
      this.#beginRequest();
  • const stream = await messages.create(
  •  { ...params, stream: true },
    
  •  { ...options, signal: this.controller.signal },
    
  • );
  • this._connected();
  • const { response, data: stream } = await messages
  •  .create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
    
  •  .withResponse();
    
  • this._connected(response);
    for await (const event of stream) {
    this.#addStreamEvent(event);
    }
    @@ -150,9 +181,10 @@ export class MessageStream implements AsyncIterable {
    this.#endRequest();
    }
  • protected _connected() {
  • protected _connected(response: Response | null) {
    if (this.ended) return;
  • this.#resolveConnectedPromise();
  • this.#request_id = response?.headers.get('request-id');
  • this.#resolveConnectedPromise(response);
    this._emit('connect');
    }

@@ -424,7 +456,7 @@ export class MessageStream implements AsyncIterable {
signal.addEventListener('abort', () => this.controller.abort());
}
this.#beginRequest();

  • this._connected();
  • this._connected(null);
    const stream = Stream.fromReadableStream(readableStream, this.controller);
    for await (const event of stream) {
    this.#addStreamEvent(event);
    diff --git src/resources/beta/messages/batches.ts src/resources/beta/messages/batches.ts
    index 0a863e64..74f4e53b 100644
    --- src/resources/beta/messages/batches.ts
    +++ src/resources/beta/messages/batches.ts
    @@ -85,6 +85,35 @@ export class Batches extends APIResource {
    });
    }

  • /**

    • This endpoint is idempotent and can be used to poll for Message Batch
    • completion. To access the results of a Message Batch, make a request to the
    • results_url field in the response.
  • */

  • delete(

  • messageBatchId: string,

  • params?: BatchDeleteParams,

  • options?: Core.RequestOptions,

  • ): Core.APIPromise;

  • delete(messageBatchId: string, options?: Core.RequestOptions): Core.APIPromise;

  • delete(

  • messageBatchId: string,

  • params: BatchDeleteParams | Core.RequestOptions = {},

  • options?: Core.RequestOptions,

  • ): Core.APIPromise {

  • if (isRequestOptions(params)) {

  •  return this.delete(messageBatchId, {}, params);
    
  • }

  • const { betas } = params;

  • return this._client.delete(/v1/messages/batches/${messageBatchId}?beta=true, {

  •  ...options,
    
  •  headers: {
    
  •    'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
    
  •    ...options?.headers,
    
  •  },
    
  • });

  • }

  • /**

    • Batches may be canceled any time before processing ends. Once cancellation is
    • initiated, the batch enters a canceling state, at which time the system may
      @@ -158,6 +187,7 @@ export class Batches extends APIResource {
      ...options,
      headers: {
      'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
  •      Accept: 'application/binary',
         ...options?.headers,
       },
       __binaryResponse: true,
    

@@ -168,6 +198,20 @@ export class Batches extends APIResource {

export class BetaMessageBatchesPage extends Page {}

+export interface BetaDeletedMessageBatch {

  • /**
    • ID of the Message Batch.
  • */
  • id: string;
  • /**
    • Deleted object type.
    • For Message Batches, this is always "message_batch_deleted".
  • */
  • type: 'message_batch_deleted';
    +}

export interface BetaMessageBatch {
/**
* Unique object identifier.
@@ -374,6 +418,13 @@ export interface BatchListParams extends PageParams {
betas?: Array<BetaAPI.AnthropicBeta>;
}

+export interface BatchDeleteParams {

  • /**
    • Optional header to specify the beta version(s) you want to use.
  • */
  • betas?: Array<BetaAPI.AnthropicBeta>;
    +}

export interface BatchCancelParams {
/**
* Optional header to specify the beta version(s) you want to use.
@@ -392,6 +443,7 @@ Batches.BetaMessageBatchesPage = BetaMessageBatchesPage;

export declare namespace Batches {
export {

  • type BetaDeletedMessageBatch as BetaDeletedMessageBatch,
    type BetaMessageBatch as BetaMessageBatch,
    type BetaMessageBatchCanceledResult as BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult as BetaMessageBatchErroredResult,
    @@ -404,6 +456,7 @@ export declare namespace Batches {
    type BatchCreateParams as BatchCreateParams,
    type BatchRetrieveParams as BatchRetrieveParams,
    type BatchListParams as BatchListParams,
  • type BatchDeleteParams as BatchDeleteParams,
    type BatchCancelParams as BatchCancelParams,
    type BatchResultsParams as BatchResultsParams,
    };
    diff --git src/resources/beta/messages/index.ts src/resources/beta/messages/index.ts
    index 2cf85964..eac5d34f 100644
    --- src/resources/beta/messages/index.ts
    +++ src/resources/beta/messages/index.ts
    @@ -3,6 +3,7 @@
    export {
    BetaMessageBatchesPage,
    Batches,
  • type BetaDeletedMessageBatch,
    type BetaMessageBatch,
    type BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult,
    @@ -14,6 +15,7 @@ export {
    type BatchCreateParams,
    type BatchRetrieveParams,
    type BatchListParams,
  • type BatchDeleteParams,
    type BatchCancelParams,
    type BatchResultsParams,
    } from './batches';
    @@ -58,4 +60,5 @@ export {
    type MessageCreateParamsNonStreaming,
    type MessageCreateParamsStreaming,
    type MessageCountTokensParams,
  • type BetaMessageStreamParams,
    } from './messages';
    diff --git src/resources/beta/messages/messages.ts src/resources/beta/messages/messages.ts
    index 186a6c36..ecb1d79f 100644
    --- src/resources/beta/messages/messages.ts
    +++ src/resources/beta/messages/messages.ts
    @@ -10,10 +10,12 @@ import * as BatchesAPI from './batches';
    import {
    BatchCancelParams,
    BatchCreateParams,
  • BatchDeleteParams,
    BatchListParams,
    BatchResultsParams,
    BatchRetrieveParams,
    Batches,
  • BetaDeletedMessageBatch,
    BetaMessageBatch,
    BetaMessageBatchCanceledResult,
    BetaMessageBatchErroredResult,
    @@ -25,6 +27,21 @@ import {
    BetaMessageBatchesPage,
    } from './batches';
    import { Stream } from '../../../streaming';
    +import { BetaMessageStream } from '../../../lib/BetaMessageStream';
    +import type { Model } from '../../messages/messages';

+const DEPRECATED_MODELS: {

  • [K in Model]?: string;
    +} = {
  • 'claude-1.3': 'November 6th, 2024',
  • 'claude-1.3-100k': 'November 6th, 2024',
  • 'claude-instant-1.1': 'November 6th, 2024',
  • 'claude-instant-1.1-100k': 'November 6th, 2024',
  • 'claude-instant-1.2': 'November 6th, 2024',
  • 'claude-3-sonnet-20240229': 'July 21st, 2025',
  • 'claude-2.1': 'July 21st, 2025',
  • 'claude-2.0': 'July 21st, 2025',
    +};

export class Messages extends APIResource {
batches: BatchesAPI.Batches = new BatchesAPI.Batches(this._client);
@@ -50,6 +67,15 @@ export class Messages extends APIResource {
options?: Core.RequestOptions,
): APIPromise | APIPromise<Stream> {
const { betas, ...body } = params;
+

  • if (body.model in DEPRECATED_MODELS) {

  •  console.warn(
    
  •    `The model '${body.model}' is deprecated and will reach end-of-life on ${
    
  •      DEPRECATED_MODELS[body.model]
    
  •    }\nPlease migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resources/model-deprecations for more information.`,
    
  •  );
    
  • }

  • return this._client.post('/v1/messages?beta=true', {
    body,
    timeout: (this._client as any)._options.timeout ?? 600000,
    @@ -62,6 +88,13 @@ export class Messages extends APIResource {
    }) as APIPromise | APIPromise<Stream>;
    }

  • /**

    • Create a Message stream
  • */

  • stream(body: BetaMessageStreamParams, options?: Core.RequestOptions): BetaMessageStream {

  • return BetaMessageStream.createMessage(this, body, options);

  • }

  • /**

    • Count the number of tokens in a Message.

@@ -84,6 +117,8 @@ export class Messages extends APIResource {
}
}

+export type BetaMessageStreamParams = MessageCreateParamsBase;
+
export interface BetaBase64PDFBlock {
source: BetaBase64PDFSource;

@@ -1115,6 +1150,7 @@ export declare namespace Messages {

export {
Batches as Batches,

  • type BetaDeletedMessageBatch as BetaDeletedMessageBatch,
    type BetaMessageBatch as BetaMessageBatch,
    type BetaMessageBatchCanceledResult as BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult as BetaMessageBatchErroredResult,
    @@ -1127,6 +1163,7 @@ export declare namespace Messages {
    type BatchCreateParams as BatchCreateParams,
    type BatchRetrieveParams as BatchRetrieveParams,
    type BatchListParams as BatchListParams,

  • type BatchDeleteParams as BatchDeleteParams,
    type BatchCancelParams as BatchCancelParams,
    type BatchResultsParams as BatchResultsParams,
    };
    diff --git src/resources/messages/batches.ts src/resources/messages/batches.ts
    index b4fd45e8..a6b328e2 100644
    --- src/resources/messages/batches.ts
    +++ src/resources/messages/batches.ts
    @@ -49,6 +49,15 @@ export class Batches extends APIResource {
    return this._client.getAPIList('/v1/messages/batches', MessageBatchesPage, { query, ...options });
    }

  • /**

    • This endpoint is idempotent and can be used to poll for Message Batch
    • completion. To access the results of a Message Batch, make a request to the
    • results_url field in the response.
  • */

  • delete(messageBatchId: string, options?: Core.RequestOptions): Core.APIPromise {

  • return this._client.delete(/v1/messages/batches/${messageBatchId}, options);

  • }

  • /**

    • Batches may be canceled any time before processing ends. Once cancellation is
    • initiated, the batch enters a canceling state, at which time the system may
      @@ -83,13 +92,34 @@ export class Batches extends APIResource {
      }

    return this._client

  •  .get(batch.results_url, { ...options, __binaryResponse: true })
    
  •  .get(batch.results_url, {
    
  •    ...options,
    
  •    headers: {
    
  •      Accept: 'application/binary',
    
  •      ...options?.headers,
    
  •    },
    
  •    __binaryResponse: true,
    
  •  })
     ._thenUnwrap((_, props) => JSONLDecoder.fromResponse(props.response, props.controller));
    
    }
    }

export class MessageBatchesPage extends Page {}

+export interface DeletedMessageBatch {

  • /**
    • ID of the Message Batch.
  • */
  • id: string;
  • /**
    • Deleted object type.
    • For Message Batches, this is always "message_batch_deleted".
  • */
  • type: 'message_batch_deleted';
    +}

export interface MessageBatch {
/**
* Unique object identifier.
@@ -283,6 +313,7 @@ Batches.MessageBatchesPage = MessageBatchesPage;

export declare namespace Batches {
export {

  • type DeletedMessageBatch as DeletedMessageBatch,
    type MessageBatch as MessageBatch,
    type MessageBatchCanceledResult as MessageBatchCanceledResult,
    type MessageBatchErroredResult as MessageBatchErroredResult,
    diff --git src/resources/messages/index.ts src/resources/messages/index.ts
    index 10308d2a..1c9178ad 100644
    --- src/resources/messages/index.ts
    +++ src/resources/messages/index.ts
    @@ -3,6 +3,7 @@
    export {
    MessageBatchesPage,
    Batches,
  • type DeletedMessageBatch,
    type MessageBatch,
    type MessageBatchCanceledResult,
    type MessageBatchErroredResult,
    diff --git src/resources/messages/messages.ts src/resources/messages/messages.ts
    index a1affbf5..12cc9b83 100644
    --- src/resources/messages/messages.ts
    +++ src/resources/messages/messages.ts
    @@ -9,6 +9,7 @@ import {
    BatchCreateParams,
    BatchListParams,
    Batches,
  • DeletedMessageBatch,
    MessageBatch,
    MessageBatchCanceledResult,
    MessageBatchErroredResult,
    @@ -308,16 +309,17 @@ export type Model =
    | 'claude-2.1'
    | 'claude-2.0';

-type DeprecatedModelsType = {
+const DEPRECATED_MODELS: {
[K in Model]?: string;
-};

-const DEPRECATED_MODELS: DeprecatedModelsType = {
+} = {
'claude-1.3': 'November 6th, 2024',
'claude-1.3-100k': 'November 6th, 2024',
'claude-instant-1.1': 'November 6th, 2024',
'claude-instant-1.1-100k': 'November 6th, 2024',
'claude-instant-1.2': 'November 6th, 2024',

  • 'claude-3-sonnet-20240229': 'July 21st, 2025',
  • 'claude-2.1': 'July 21st, 2025',
  • 'claude-2.0': 'July 21st, 2025',
    };

export interface RawContentBlockDeltaEvent {
@@ -1114,6 +1116,7 @@ export declare namespace Messages {

export {
Batches as Batches,

  • type DeletedMessageBatch as DeletedMessageBatch,
    type MessageBatch as MessageBatch,
    type MessageBatchCanceledResult as MessageBatchCanceledResult,
    type MessageBatchErroredResult as MessageBatchErroredResult,
    diff --git src/version.ts src/version.ts
    index 4a46c186..3f1d4329 100644
    --- src/version.ts
    +++ src/version.ts
    @@ -1 +1 @@
    -export const VERSION = '0.33.1'; // x-release-please-version
    +export const VERSION = '0.35.0'; // x-release-please-version
    diff --git tests/api-resources/beta/messages/batches.test.ts tests/api-resources/beta/messages/batches.test.ts
    index e395910a..98d39506 100644
    --- tests/api-resources/beta/messages/batches.test.ts
    +++ tests/api-resources/beta/messages/batches.test.ts
    @@ -60,7 +60,7 @@ describe('resource batches', () => {
    },
    },
    },
  •            name: 'x',
    
  •            name: 'name',
               cache_control: { type: 'ephemeral' },
               description: 'Get the current weather in a given location',
               type: 'custom',
    

@@ -132,6 +132,35 @@ describe('resource batches', () => {
).rejects.toThrow(Anthropic.NotFoundError);
});

  • test('delete', async () => {
  • const responsePromise = client.beta.messages.batches.delete('message_batch_id');
  • const rawResponse = await responsePromise.asResponse();
  • expect(rawResponse).toBeInstanceOf(Response);
  • const response = await responsePromise;
  • expect(response).not.toBeInstanceOf(Response);
  • const dataAndResponse = await responsePromise.withResponse();
  • expect(dataAndResponse.data).toBe(response);
  • expect(dataAndResponse.response).toBe(rawResponse);
  • });
  • test('delete: request options instead of params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.beta.messages.batches.delete('message_batch_id', { path: '/_stainless_unknown_path' }),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('delete: request options and params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.beta.messages.batches.delete(
    
  •    'message_batch_id',
    
  •    { betas: ['string'] },
    
  •    { path: '/_stainless_unknown_path' },
    
  •  ),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('cancel', async () => {
    const responsePromise = client.beta.messages.batches.cancel('message_batch_id');
    const rawResponse = await responsePromise.asResponse();
    diff --git tests/api-resources/beta/messages/messages.test.ts tests/api-resources/beta/messages/messages.test.ts
    index ec73d9c0..493de962 100644
    --- tests/api-resources/beta/messages/messages.test.ts
    +++ tests/api-resources/beta/messages/messages.test.ts
    @@ -44,7 +44,7 @@ describe('resource messages', () => {
    unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
    },
    },
  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
         type: 'custom',
    

@@ -85,7 +85,7 @@ describe('resource messages', () => {
unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
},
},

  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
         type: 'custom',
    

diff --git tests/api-resources/messages/batches.test.ts tests/api-resources/messages/batches.test.ts
index 26efdbc8..4137fa31 100644
--- tests/api-resources/messages/batches.test.ts
+++ tests/api-resources/messages/batches.test.ts
@@ -59,7 +59,7 @@ describe('resource batches', () => {
},
},
},

  •            name: 'x',
    
  •            name: 'name',
               cache_control: { type: 'ephemeral' },
               description: 'Get the current weather in a given location',
             },
    

@@ -118,6 +118,24 @@ describe('resource batches', () => {
).rejects.toThrow(Anthropic.NotFoundError);
});

  • test('delete', async () => {
  • const responsePromise = client.messages.batches.delete('message_batch_id');
  • const rawResponse = await responsePromise.asResponse();
  • expect(rawResponse).toBeInstanceOf(Response);
  • const response = await responsePromise;
  • expect(response).not.toBeInstanceOf(Response);
  • const dataAndResponse = await responsePromise.withResponse();
  • expect(dataAndResponse.data).toBe(response);
  • expect(dataAndResponse.response).toBe(rawResponse);
  • });
  • test('delete: request options instead of params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.messages.batches.delete('message_batch_id', { path: '/_stainless_unknown_path' }),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('cancel', async () => {
    const responsePromise = client.messages.batches.cancel('message_batch_id');
    const rawResponse = await responsePromise.asResponse();
    diff --git tests/api-resources/messages/messages.test.ts tests/api-resources/messages/messages.test.ts
    index 3ae41d32..7b9d6f96 100644
    --- tests/api-resources/messages/messages.test.ts
    +++ tests/api-resources/messages/messages.test.ts
    @@ -44,7 +44,7 @@ describe('resource messages', () => {
    unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
    },
    },
  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
       },
    

@@ -83,7 +83,7 @@ describe('resource messages', () => {
unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
},
},

  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
       },
    

diff --git tests/index.test.ts tests/index.test.ts
index b6398085..bc0c1645 100644
--- tests/index.test.ts
+++ tests/index.test.ts
@@ -96,6 +96,15 @@ describe('instantiate client', () => {
expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true });
});

  • test('explicit global fetch', async () => {

  • // make sure the global fetch type is assignable to our Fetch type

  • const client = new Anthropic({

  •  baseURL: 'http://localhost:5000/',
    
  •  apiKey: 'my-anthropic-api-key',
    
  •  fetch: defaultFetch,
    
  • });

  • });

  • test('custom signal', async () => {
    const client = new Anthropic({
    baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
    @@ -122,6 +131,23 @@ describe('instantiate client', () => {
    expect(spy).toHaveBeenCalledTimes(1);
    });

  • test('normalized method', async () => {

  • let capturedRequest: RequestInit | undefined;

  • const testFetch = async (url: RequestInfo, init: RequestInit = {}): Promise => {

  •  capturedRequest = init;
    
  •  return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } });
    
  • };

  • const client = new Anthropic({

  •  baseURL: 'http://localhost:5000/',
    
  •  apiKey: 'my-anthropic-api-key',
    
  •  fetch: testFetch,
    
  • });

  • await client.patch('/foo');

  • expect(capturedRequest?.method).toEqual('PATCH');

  • });

  • describe('baseUrl', () => {
    test('trailing slash', () => {
    const client = new Anthropic({


</details>

### Description
This PR introduces several significant updates to the Anthropic TypeScript SDK, including:
1. Addition of beta message streaming helpers
2. Enhanced request ID handling and response tracking
3. New endpoint for message batch deletion
4. Deprecation notices for older models
5. Various bug fixes and documentation improvements

<details>
<summary><i>Changes</i></summary>

### Changes

By filename:

**API and Version Updates:**
- `.release-please-manifest.json`: Version bumps for main SDK and sub-packages 
- `CHANGELOG.md`: Added entries for versions 0.34.0 and 0.35.0 with detailed changes
- `package.json`: Version bump to 0.35.0

**Core Functionality:**
- `src/lib/BetaMessageStream.ts`: New file adding beta message streaming functionality
- `src/lib/MessageStream.ts`: Enhanced with request ID tracking and response handling
- `src/core.ts`: Improved HTTP method handling for custom methods
- `src/index.ts`: Added undefined type annotations to client options

**Resources:**
- `src/resources/messages/batches.ts`: Added delete endpoint for message batches
- `src/resources/beta/messages/batches.ts`: Added beta version of delete endpoint
- `src/resources/messages/messages.ts`: Added model deprecation warnings

**Documentation:**
- `README.md`: Added alpha version callout and fixed examples
- `CONTRIBUTING.md`: Improved formatting and clarity
- `api.md`: Updated API documentation with new endpoints

**Examples:**
- Added `examples/count-tokens.ts` with token counting functionality

```mermaid
sequenceDiagram
    participant Client
    participant MessageStream
    participant API
    participant Response

    Client->>MessageStream: create()
    MessageStream->>API: POST /v1/messages
    API-->>MessageStream: Stream Response
    MessageStream->>MessageStream: Process Events
    MessageStream-->>Client: Stream Events
    
    alt Delete Batch
        Client->>API: DELETE /v1/messages/batches/{id}
        API-->>Client: DeletedMessageBatch
    end

Security Hotspots

  • None identified

This sequence diagram shows the main interactions added/modified in this PR, focusing on the message streaming and new batch deletion functionality.

Copy link

openai debug - [puLL-Merge] - anthropics/[email protected]

Diff
diff --git .release-please-manifest.json .release-please-manifest.json
index 2053c67b..cb210381 100644
--- .release-please-manifest.json
+++ .release-please-manifest.json
@@ -1,5 +1,5 @@
 {
-  ".": "0.33.1",
-  "packages/vertex-sdk": "0.6.1",
-  "packages/bedrock-sdk": "0.12.0"
+  ".": "0.35.0",
+  "packages/vertex-sdk": "0.6.3",
+  "packages/bedrock-sdk": "0.12.2"
 }
diff --git .stats.yml .stats.yml
index 19e9daeb..239e17b7 100644
--- .stats.yml
+++ .stats.yml
@@ -1,2 +1,2 @@
-configured_endpoints: 19
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-be055148d227480fcacc9086c37ac8009dcb487731069ada51af35044f65bee4.yml
+configured_endpoints: 21
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-fd67aea6883f1ee9e46f31a42d3940f0acb1749e787055bd9b9f278b20fa53ec.yml
diff --git CHANGELOG.md CHANGELOG.md
index a1a57c52..499e576c 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -1,5 +1,63 @@
 # Changelog
 
+## 0.35.0 (2025-01-21)
+
+Full Changelog: [sdk-v0.34.0...sdk-v0.35.0](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.34.0...sdk-v0.35.0)
+
+### Features
+
+* add beta message streaming helpers ([#655](https://github.com/anthropics/anthropic-sdk-typescript/issues/655)) ([d7b5af1](https://github.com/anthropics/anthropic-sdk-typescript/commit/d7b5af1629dbcefdb7bfdca271ab497567830227))
+* **stream:** add `.withResponse()` ([#654](https://github.com/anthropics/anthropic-sdk-typescript/issues/654)) ([b54477f](https://github.com/anthropics/anthropic-sdk-typescript/commit/b54477f20c92db4c2c5ed89af5d46c36b035bf1e))
+* **streaming:** add `.request_id` getter ([4572478](https://github.com/anthropics/anthropic-sdk-typescript/commit/4572478266a67e12e32ffef69817cbc495943b1d))
+
+
+### Bug Fixes
+
+* **docs:** correct results return type ([#657](https://github.com/anthropics/anthropic-sdk-typescript/issues/657)) ([4e6d031](https://github.com/anthropics/anthropic-sdk-typescript/commit/4e6d031a41625ebf9c4311638e0c149179fcae0c))
+* **examples:** add token counting example ([2498e2e](https://github.com/anthropics/anthropic-sdk-typescript/commit/2498e2eaf49d66a664ed1fdcd7bbd331979cf5b2))
+* send correct Accept header for certain endpoints ([#651](https://github.com/anthropics/anthropic-sdk-typescript/issues/651)) ([17ffaeb](https://github.com/anthropics/anthropic-sdk-typescript/commit/17ffaeba5af48d13b08483973b82cfe1ae79347f))
+* **vertex:** add beta.messages.countTokens method ([51d3f23](https://github.com/anthropics/anthropic-sdk-typescript/commit/51d3f23a7cc1bea798cc8e4041e08114ebc3a4eb))
+
+
+### Chores
+
+* deprecate more models ([661f5f9](https://github.com/anthropics/anthropic-sdk-typescript/commit/661f5f9d9b24f3661df246dcf101dd9812b3e19e))
+* **internal:** add test ([#660](https://github.com/anthropics/anthropic-sdk-typescript/issues/660)) ([3ec7d1a](https://github.com/anthropics/anthropic-sdk-typescript/commit/3ec7d1a9eea30255b24cdb16c1a26705bdfea0ac))
+* **internal:** temporary revert commit ([#643](https://github.com/anthropics/anthropic-sdk-typescript/issues/643)) ([43dd43c](https://github.com/anthropics/anthropic-sdk-typescript/commit/43dd43c4c8ab69d5a60e59473af7dff5f7799048))
+* **internal:** update examples ([#649](https://github.com/anthropics/anthropic-sdk-typescript/issues/649)) ([036a239](https://github.com/anthropics/anthropic-sdk-typescript/commit/036a239800fec7e6cbc439f125101d5475eae5b3))
+* **types:** add `| undefined` to client options properties ([#656](https://github.com/anthropics/anthropic-sdk-typescript/issues/656)) ([d642298](https://github.com/anthropics/anthropic-sdk-typescript/commit/d642298334529ff95b9d7ac497d548a6b04dbcfb))
+
+
+### Documentation
+
+* **readme:** fix misplaced period ([#650](https://github.com/anthropics/anthropic-sdk-typescript/issues/650)) ([8754744](https://github.com/anthropics/anthropic-sdk-typescript/commit/87547448c8b4bf69a61756af1f12927f33b68680))
+* **readme:** fix Request IDs example ([#659](https://github.com/anthropics/anthropic-sdk-typescript/issues/659)) ([6d3162d](https://github.com/anthropics/anthropic-sdk-typescript/commit/6d3162da1ddb964b75e575376f278468ba1ed9f5))
+
+## 0.34.0 (2024-12-20)
+
+Full Changelog: [sdk-v0.33.1...sdk-v0.34.0](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.33.1...sdk-v0.34.0)
+
+### Features
+
+* **api:** add message batch delete endpoint ([#640](https://github.com/anthropics/anthropic-sdk-typescript/issues/640)) ([54f7e1f](https://github.com/anthropics/anthropic-sdk-typescript/commit/54f7e1ffb9a2956ee27a4a715b84717aa681eb7c))
+
+
+### Bug Fixes
+
+* **client:** normalize method ([#639](https://github.com/anthropics/anthropic-sdk-typescript/issues/639)) ([384bb04](https://github.com/anthropics/anthropic-sdk-typescript/commit/384bb042dd854ed753c6bd8e25f522d0e042bfbf))
+
+
+### Chores
+
+* bump testing data uri ([#637](https://github.com/anthropics/anthropic-sdk-typescript/issues/637)) ([3f23530](https://github.com/anthropics/anthropic-sdk-typescript/commit/3f23530fb55d9fec7278967ea02600e44e9f58e2))
+* **internal:** temporary revert commit ([#643](https://github.com/anthropics/anthropic-sdk-typescript/issues/643)) ([8057b1e](https://github.com/anthropics/anthropic-sdk-typescript/commit/8057b1eb67ccccee042a45f2efe53cccced15682))
+
+
+### Documentation
+
+* minor formatting changes ([#641](https://github.com/anthropics/anthropic-sdk-typescript/issues/641)) ([8b362ee](https://github.com/anthropics/anthropic-sdk-typescript/commit/8b362ee72954b31b4de920b35aed97255efa5e2e))
+* **readme:** add alpha callout ([#646](https://github.com/anthropics/anthropic-sdk-typescript/issues/646)) ([640304c](https://github.com/anthropics/anthropic-sdk-typescript/commit/640304c7c7e8bc67cbf799a646169736d89ad4c8))
+
 ## 0.33.1 (2024-12-17)
 
 Full Changelog: [sdk-v0.33.0...sdk-v0.33.1](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.33.0...sdk-v0.33.1)
diff --git CONTRIBUTING.md CONTRIBUTING.md
index 9a869b0f..7d94b319 100644
--- CONTRIBUTING.md
+++ CONTRIBUTING.md
@@ -1,6 +1,6 @@
 ## Setting up the environment
 
-This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable).
+This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install).
 Other package managers may work but are not officially supported for development.
 
 To set up the repository, run:
@@ -29,10 +29,10 @@ All files in the `examples/` directory are not modified by the generator and can
 …
 \`\`\`
 
-```
-chmod +x examples/<your-example>.ts
+```sh
+$ chmod +x examples/<your-example>.ts
 # run the example against your api
-yarn tsn -T examples/<your-example>.ts
+$ yarn tsn -T examples/<your-example>.ts

Using the repository from source

diff --git README.md README.md
index da3db48e..fac24b92 100644
--- README.md
+++ README.md
@@ -1,3 +1,9 @@
+> [!IMPORTANT]
+> We're actively working on a new alpha version that migrates from node-fetch to builtin fetch.
+>
+> Please try it out and let us know if you run into any issues!
+> anthropics/anthropic-sdk-typescript#645
+

Anthropic TypeScript API Library

NPM version npm bundle size
@@ -235,7 +241,7 @@ All object responses in the SDK provide a _request_id property which is added

const message = await client.messages.create({ max_tokens: 1024, messages: [{ role: 'user', content: 'Hello, Claude' }], model: 'claude-3-5-sonnet-latest' });
-console.log(completion._request_id) // req_018EeWyXxfu5pfWkrYcMdjWG
+console.log(message._request_id) // req_018EeWyXxfu5pfWkrYcMdjWG

@@ -486,7 +492,7 @@ await client.messages.create(
This package generally follows SemVer conventions, though certain backwards-incompatible changes may be released as minor versions:

  1. Changes that only affect static types, without breaking runtime behavior.
    -2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals).
    +2. Changes to library internals which are technically public but not intended or documented for external use. (Please open a GitHub issue to let us know if you are relying on such internals.)
  2. Changes that we do not expect to impact the vast majority of users in practice.

We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
diff --git api.md api.md
index 48d1c9a8..9aed2e92 100644
--- api.md
+++ api.md
@@ -70,6 +70,7 @@ Methods:

Types:

+- DeletedMessageBatch

  • MessageBatch
  • MessageBatchCanceledResult
  • MessageBatchErroredResult
    @@ -84,8 +85,9 @@ Methods:
  • client.messages.batches.create({ ...params }) -> MessageBatch
  • client.messages.batches.retrieve(messageBatchId) -> MessageBatch
  • client.messages.batches.list({ ...params }) -> MessageBatchesPage
    +- client.messages.batches.delete(messageBatchId) -> DeletedMessageBatch
  • client.messages.batches.cancel(messageBatchId) -> MessageBatch
    -- client.messages.batches.results(messageBatchId) -> Response
    +- client.messages.batches.results(messageBatchId) -> JSONLDecoder<MessageBatchIndividualResponse>

Models

@@ -175,6 +177,7 @@ Methods:

Types:

+- BetaDeletedMessageBatch

  • BetaMessageBatch
  • BetaMessageBatchCanceledResult
  • BetaMessageBatchErroredResult
    @@ -189,5 +192,6 @@ Methods:
  • client.beta.messages.batches.create({ ...params }) -> BetaMessageBatch
  • client.beta.messages.batches.retrieve(messageBatchId, { ...params }) -> BetaMessageBatch
  • client.beta.messages.batches.list({ ...params }) -> BetaMessageBatchesPage
    +- client.beta.messages.batches.delete(messageBatchId, { ...params }) -> BetaDeletedMessageBatch
  • client.beta.messages.batches.cancel(messageBatchId, { ...params }) -> BetaMessageBatch
    -- client.beta.messages.batches.results(messageBatchId, { ...params }) -> Response
    +- client.beta.messages.batches.results(messageBatchId, { ...params }) -> JSONLDecoder<MessageBatchIndividualResponse>
    diff --git examples/count-tokens.ts examples/count-tokens.ts
    index e69de29b..22fae1f1 100755
    --- examples/count-tokens.ts
    +++ examples/count-tokens.ts
    @@ -0,0 +1,20 @@
    +#!/usr/bin/env -S npm run tsn -T

+import Anthropic from '@anthropic-ai/sdk';
+
+const client = new Anthropic(); // gets API Key from environment variable ANTHROPIC_API_KEY
+
+async function main() {

  • const result = await client.messages.countTokens({
  • messages: [
  •  {
    
  •    role: 'user',
    
  •    content: 'Hey Claude!?',
    
  •  },
    
  • ],
  • model: 'claude-3-5-sonnet-latest',
  • });
  • console.dir(result);
    +}

+main();
diff --git package.json package.json
index d8f88f57..aa23123e 100644
--- package.json
+++ package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/sdk",

  • "version": "0.33.1",
  • "version": "0.35.0",
    "description": "The official TypeScript library for the Anthropic API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/bedrock-sdk/CHANGELOG.md packages/bedrock-sdk/CHANGELOG.md
    index 837af37e..12fec54c 100644
    --- packages/bedrock-sdk/CHANGELOG.md
    +++ packages/bedrock-sdk/CHANGELOG.md
    @@ -1,5 +1,21 @@

Changelog

+## 0.12.2 (2025-01-21)
+
+Full Changelog: bedrock-sdk-v0.12.1...bedrock-sdk-v0.12.2
+
+### Chores
+
+* internal: temporary revert commit (#643) (43dd43c)
+
+## 0.12.1 (2024-12-20)
+
+Full Changelog: bedrock-sdk-v0.12.0...bedrock-sdk-v0.12.1
+
+### Chores
+
+* internal: temporary revert commit (#643) (8057b1e)
+

0.12.0 (2024-12-17)

Full Changelog: bedrock-sdk-v0.11.2...bedrock-sdk-v0.12.0
diff --git packages/bedrock-sdk/package.json packages/bedrock-sdk/package.json
index 352931a5..8e7a906d 100644
--- packages/bedrock-sdk/package.json
+++ packages/bedrock-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/bedrock-sdk",

  • "version": "0.12.0",
  • "version": "0.12.2",
    "description": "The official TypeScript library for the Anthropic Bedrock API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/vertex-sdk/CHANGELOG.md packages/vertex-sdk/CHANGELOG.md
    index 94191164..e01d1d71 100644
    --- packages/vertex-sdk/CHANGELOG.md
    +++ packages/vertex-sdk/CHANGELOG.md
    @@ -1,5 +1,26 @@

Changelog

+## 0.6.3 (2025-01-21)
+
+Full Changelog: vertex-sdk-v0.6.2...vertex-sdk-v0.6.3
+
+### Bug Fixes
+
+* vertex: add beta.messages.countTokens method (51d3f23)
+
+
+### Chores
+
+* internal: temporary revert commit (#643) (43dd43c)
+
+## 0.6.2 (2024-12-20)
+
+Full Changelog: vertex-sdk-v0.6.1...vertex-sdk-v0.6.2
+
+### Chores
+
+* internal: temporary revert commit (#643) (8057b1e)
+

0.6.1 (2024-12-17)

Full Changelog: vertex-sdk-v0.6.0...vertex-sdk-v0.6.1
diff --git packages/vertex-sdk/package.json packages/vertex-sdk/package.json
index 43fc356d..ae4cf6f9 100644
--- packages/vertex-sdk/package.json
+++ packages/vertex-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@anthropic-ai/vertex-sdk",

  • "version": "0.6.1",
  • "version": "0.6.3",
    "description": "The official TypeScript library for the Anthropic Vertex API",
    "author": "Anthropic [email protected]",
    "types": "dist/index.d.ts",
    diff --git packages/vertex-sdk/src/client.ts packages/vertex-sdk/src/client.ts
    index f1046455..0f8a1626 100644
    --- packages/vertex-sdk/src/client.ts
    +++ packages/vertex-sdk/src/client.ts
    @@ -179,23 +179,17 @@ function makeMessagesResource(client: AnthropicVertex): MessagesResource {
    }

/**

    • The Vertex API does not currently support prompt caching, token counting or the Batch API.
    • The Vertex API does not currently support the Batch API.
      */
      -type BetaResource = Omit<Resources.Beta, 'promptCaching' | 'messages'> & {
  • messages: Omit<Resources.Beta['messages'], 'batches' | 'countTokens'>;
    +type BetaResource = Omit<Resources.Beta, 'messages'> & {
  • messages: Omit<Resources.Beta['messages'], 'batches'>;
    };

function makeBetaResource(client: AnthropicVertex): BetaResource {
const resource = new Resources.Beta(client);

  • // @ts-expect-error we're deleting non-optional properties

  • delete resource.promptCaching;

  • // @ts-expect-error we're deleting non-optional properties
    delete resource.messages.batches;

  • // @ts-expect-error we're deleting non-optional properties

  • delete resource.messages.countTokens;

  • return resource;
    }
    diff --git src/core.ts src/core.ts
    index ea8d8dca..344bf6ac 100644
    --- src/core.ts
    +++ src/core.ts
    @@ -556,9 +556,19 @@ export abstract class APIClient {

    const timeout = setTimeout(() => controller.abort(), ms);

  • const fetchOptions = {
  •  signal: controller.signal as any,
    
  •  ...options,
    
  • };
  • if (fetchOptions.method) {
  •  // Custom methods like 'patch' need to be uppercased
    
  •  // See https://github.com/nodejs/undici/issues/2294
    
  •  fetchOptions.method = fetchOptions.method.toUpperCase();
    
  • }
  • return (
    // use undefined this binding; fetch errors if bound to something else in browser/cloudflare
  •  this.fetch.call(undefined, url, { signal: controller.signal as any, ...options }).finally(() => {
    
  •  this.fetch.call(undefined, url, fetchOptions).finally(() => {
       clearTimeout(timeout);
     })
    
    );
    diff --git src/index.ts src/index.ts
    index bfca4fc8..44f6bc2d 100644
    --- src/index.ts
    +++ src/index.ts
    @@ -103,7 +103,7 @@ export interface ClientOptions {
    • Note that request timeouts are retried by default, so in a worst-case scenario you may wait
    • much longer than this timeout before the promise succeeds or fails.
      */
  • timeout?: number;
  • timeout?: number | undefined;

    /**

    • An HTTP agent used to manage HTTP(S) connections.
      @@ -111,7 +111,7 @@ export interface ClientOptions {
    • If not provided, an agent will be constructed by default in the Node.js environment,
    • otherwise no agent is used.
      */
  • httpAgent?: Agent;
  • httpAgent?: Agent | undefined;

    /**

    • Specify a custom fetch function implementation.
      @@ -127,7 +127,7 @@ export interface ClientOptions {
    • @default 2
      */
  • maxRetries?: number;
  • maxRetries?: number | undefined;

    /**

    • Default headers to include with every request to the API.
      @@ -135,7 +135,7 @@ export interface ClientOptions {
    • These can be removed in individual requests by explicitly setting the
    • header to undefined or null in request options.
      */
  • defaultHeaders?: Core.Headers;
  • defaultHeaders?: Core.Headers | undefined;

    /**

    • Default query parameters to include with every request to the API.
      @@ -143,13 +143,13 @@ export interface ClientOptions {
    • These can be removed in individual requests by explicitly setting the
    • param to undefined in request options.
      */
  • defaultQuery?: Core.DefaultQuery;
  • defaultQuery?: Core.DefaultQuery | undefined;

    /**

    • By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
    • Only set this option to true if you understand the risks and have appropriate mitigations in place.
      */
  • dangerouslyAllowBrowser?: boolean;
  • dangerouslyAllowBrowser?: boolean | undefined;
    }

/**
diff --git a/src/lib/BetaMessageStream.ts b/src/lib/BetaMessageStream.ts
new file mode 100644
index 00000000..06fbc46a
--- /dev/null
+++ src/lib/BetaMessageStream.ts
@@ -0,0 +1,593 @@
+import * as Core from '@anthropic-ai/sdk/core';
+import { AnthropicError, APIUserAbortError } from '@anthropic-ai/sdk/error';
+import {

  • type BetaContentBlock,
  • Messages as BetaMessages,
  • type BetaMessage,
  • type BetaRawMessageStreamEvent as BetaMessageStreamEvent,
  • type BetaMessageParam,
  • type MessageCreateParams as BetaMessageCreateParams,
  • type MessageCreateParamsBase as BetaMessageCreateParamsBase,
  • type BetaTextBlock,
    +} from '@anthropic-ai/sdk/resources/beta/messages/messages';
    +import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index';
    +import { Stream } from '@anthropic-ai/sdk/streaming';
    +import { partialParse } from '../_vendor/partial-json-parser/parser';

+export interface MessageStreamEvents {

  • connect: () => void;
  • streamEvent: (event: BetaMessageStreamEvent, snapshot: BetaMessage) => void;
  • text: (textDelta: string, textSnapshot: string) => void;
  • inputJson: (partialJson: string, jsonSnapshot: unknown) => void;
  • message: (message: BetaMessage) => void;
  • contentBlock: (content: BetaContentBlock) => void;
  • finalMessage: (message: BetaMessage) => void;
  • error: (error: AnthropicError) => void;
  • abort: (error: APIUserAbortError) => void;
  • end: () => void;
    +}

+type MessageStreamEventListeners = {

  • listener: MessageStreamEvents[Event];
  • once?: boolean;
    +}[];

+const JSON_BUF_PROPERTY = '__json_buf';
+
+export class BetaMessageStream implements AsyncIterable {

  • messages: BetaMessageParam[] = [];
  • receivedMessages: BetaMessage[] = [];
  • #currentMessageSnapshot: BetaMessage | undefined;
  • controller: AbortController = new AbortController();
  • #connectedPromise: Promise<Response | null>;
  • #resolveConnectedPromise: (response: Response | null) => void = () => {};
  • #rejectConnectedPromise: (error: AnthropicError) => void = () => {};
  • #endPromise: Promise;
  • #resolveEndPromise: () => void = () => {};
  • #rejectEndPromise: (error: AnthropicError) => void = () => {};
  • #listeners: { [Event in keyof MessageStreamEvents]?: MessageStreamEventListeners } = {};
  • #ended = false;
  • #errored = false;
  • #aborted = false;
  • #catchingPromiseCreated = false;
  • #request_id: string | null | undefined;
  • constructor() {
  • this.#connectedPromise = new Promise<Response | null>((resolve, reject) => {
  •  this.#resolveConnectedPromise = resolve;
    
  •  this.#rejectConnectedPromise = reject;
    
  • });
  • this.#endPromise = new Promise((resolve, reject) => {
  •  this.#resolveEndPromise = resolve;
    
  •  this.#rejectEndPromise = reject;
    
  • });
  • // Don't let these promises cause unhandled rejection errors.
  • // we will manually cause an unhandled rejection error later
  • // if the user hasn't registered any error listener or called
  • // any promise-returning method.
  • this.#connectedPromise.catch(() => {});
  • this.#endPromise.catch(() => {});
  • }
  • get request_id(): string | null | undefined {
  • return this.#request_id;
  • }
  • /**
    • Returns the MessageStream data, the raw Response instance and the ID of the request,
    • returned vie the request-id header which is useful for debugging requests and resporting
    • issues to Anthropic.
    • This is the same as the APIPromise.withResponse() method.
    • This method will raise an error if you created the stream using MessageStream.fromReadableStream
    • as no Response is available.
  • */
  • async withResponse(): Promise<{
  • data: BetaMessageStream;
  • response: Response;
  • request_id: string | null | undefined;
  • }> {
  • const response = await this.#connectedPromise;
  • if (!response) {
  •  throw new Error('Could not resolve a `Response` object');
    
  • }
  • return {
  •  data: this,
    
  •  response,
    
  •  request_id: response.headers.get('request-id'),
    
  • };
  • }
  • /**
    • Intended for use on the frontend, consuming a stream produced with
    • .toReadableStream() on the backend.
    • Note that messages sent to the model do not appear in .on('message')
    • in this context.
  • */
  • static fromReadableStream(stream: ReadableStream): BetaMessageStream {
  • const runner = new BetaMessageStream();
  • runner._run(() => runner._fromReadableStream(stream));
  • return runner;
  • }
  • static createMessage(
  • messages: BetaMessages,
  • params: BetaMessageCreateParamsBase,
  • options?: Core.RequestOptions,
  • ): BetaMessageStream {
  • const runner = new BetaMessageStream();
  • for (const message of params.messages) {
  •  runner._addMessageParam(message);
    
  • }
  • runner._run(() =>
  •  runner._createMessage(
    
  •    messages,
    
  •    { ...params, stream: true },
    
  •    { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } },
    
  •  ),
    
  • );
  • return runner;
  • }
  • protected _run(executor: () => Promise) {
  • executor().then(() => {
  •  this._emitFinal();
    
  •  this._emit('end');
    
  • }, this.#handleError);
  • }
  • protected _addMessageParam(message: BetaMessageParam) {
  • this.messages.push(message);
  • }
  • protected _addMessage(message: BetaMessage, emit = true) {
  • this.receivedMessages.push(message);
  • if (emit) {
  •  this._emit('message', message);
    
  • }
  • }
  • protected async _createMessage(
  • messages: BetaMessages,
  • params: BetaMessageCreateParams,
  • options?: Core.RequestOptions,
  • ): Promise {
  • const signal = options?.signal;
  • if (signal) {
  •  if (signal.aborted) this.controller.abort();
    
  •  signal.addEventListener('abort', () => this.controller.abort());
    
  • }
  • this.#beginRequest();
  • const { response, data: stream } = await messages
  •  .create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
    
  •  .withResponse();
    
  • this._connected(response);
  • for await (const event of stream) {
  •  this.#addStreamEvent(event);
    
  • }
  • if (stream.controller.signal?.aborted) {
  •  throw new APIUserAbortError();
    
  • }
  • this.#endRequest();
  • }
  • protected _connected(response: Response | null) {
  • if (this.ended) return;
  • this.#request_id = response?.headers.get('request-id');
  • this.#resolveConnectedPromise(response);
  • this._emit('connect');
  • }
  • get ended(): boolean {
  • return this.#ended;
  • }
  • get errored(): boolean {
  • return this.#errored;
  • }
  • get aborted(): boolean {
  • return this.#aborted;
  • }
  • abort() {
  • this.controller.abort();
  • }
  • /**
    • Adds the listener function to the end of the listeners array for the event.
    • No checks are made to see if the listener has already been added. Multiple calls passing
    • the same combination of event and listener will result in the listener being added, and
    • called, multiple times.
    • @returns this MessageStream, so that calls can be chained
  • */
  • on(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners: MessageStreamEventListeners =
  •  this.#listeners[event] || (this.#listeners[event] = []);
    
  • listeners.push({ listener });
  • return this;
  • }
  • /**
    • Removes the specified listener from the listener array for the event.
    • off() will remove, at most, one instance of a listener from the listener array. If any single
    • listener has been added multiple times to the listener array for the specified event, then
    • off() must be called multiple times to remove each instance.
    • @returns this MessageStream, so that calls can be chained
  • */
  • off(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners = this.#listeners[event];
  • if (!listeners) return this;
  • const index = listeners.findIndex((l) => l.listener === listener);
  • if (index >= 0) listeners.splice(index, 1);
  • return this;
  • }
  • /**
    • Adds a one-time listener function for the event. The next time the event is triggered,
    • this listener is removed and then invoked.
    • @returns this MessageStream, so that calls can be chained
  • */
  • once(event: Event, listener: MessageStreamEvents[Event]): this {
  • const listeners: MessageStreamEventListeners =
  •  this.#listeners[event] || (this.#listeners[event] = []);
    
  • listeners.push({ listener, once: true });
  • return this;
  • }
  • /**
    • This is similar to .once(), but returns a Promise that resolves the next time
    • the event is triggered, instead of calling a listener callback.
    • @returns a Promise that resolves the next time given event is triggered,
    • or rejects if an error is emitted. (If you request the 'error' event,
    • returns a promise that resolves with the error).
    • Example:
    • const message = await stream.emitted('message') // rejects if the stream errors
  • */
  • emitted(
  • event: Event,
  • ): Promise<
  • Parameters<MessageStreamEvents[Event]> extends [infer Param] ? Param
  • : Parameters<MessageStreamEvents[Event]> extends [] ? void
  • : Parameters<MessageStreamEvents[Event]>
  • {

  • return new Promise((resolve, reject) => {
  •  this.#catchingPromiseCreated = true;
    
  •  if (event !== 'error') this.once('error', reject);
    
  •  this.once(event, resolve as any);
    
  • });
  • }
  • async done(): Promise {
  • this.#catchingPromiseCreated = true;
  • await this.#endPromise;
  • }
  • get currentMessage(): BetaMessage | undefined {
  • return this.#currentMessageSnapshot;
  • }
  • #getFinalMessage(): BetaMessage {
  • if (this.receivedMessages.length === 0) {
  •  throw new AnthropicError('stream ended without producing a Message with role=assistant');
    
  • }
  • return this.receivedMessages.at(-1)!;
  • }
  • /**
    • @returns a promise that resolves with the the final assistant Message response,
    • or rejects if an error occurred or the stream ended prematurely without producing a Message.
  • */
  • async finalMessage(): Promise {
  • await this.done();
  • return this.#getFinalMessage();
  • }
  • #getFinalText(): string {
  • if (this.receivedMessages.length === 0) {
  •  throw new AnthropicError('stream ended without producing a Message with role=assistant');
    
  • }
  • const textBlocks = this.receivedMessages
  •  .at(-1)!
    
  •  .content.filter((block): block is BetaTextBlock => block.type === 'text')
    
  •  .map((block) => block.text);
    
  • if (textBlocks.length === 0) {
  •  throw new AnthropicError('stream ended without producing a content block with type=text');
    
  • }
  • return textBlocks.join(' ');
  • }
  • /**
    • @returns a promise that resolves with the the final assistant Message's text response, concatenated
    • together if there are more than one text blocks.
    • Rejects if an error occurred or the stream ended prematurely without producing a Message.
  • */
  • async finalText(): Promise {
  • await this.done();
  • return this.#getFinalText();
  • }
  • #handleError = (error: unknown) => {
  • this.#errored = true;
  • if (error instanceof Error && error.name === 'AbortError') {
  •  error = new APIUserAbortError();
    
  • }
  • if (error instanceof APIUserAbortError) {
  •  this.#aborted = true;
    
  •  return this._emit('abort', error);
    
  • }
  • if (error instanceof AnthropicError) {
  •  return this._emit('error', error);
    
  • }
  • if (error instanceof Error) {
  •  const anthropicError: AnthropicError = new AnthropicError(error.message);
    
  •  // @ts-ignore
    
  •  anthropicError.cause = error;
    
  •  return this._emit('error', anthropicError);
    
  • }
  • return this._emit('error', new AnthropicError(String(error)));
  • };
  • protected _emit(
  • event: Event,
  • ...args: Parameters<MessageStreamEvents[Event]>
  • ) {
  • // make sure we don't emit any MessageStreamEvents after end
  • if (this.#ended) return;
  • if (event === 'end') {
  •  this.#ended = true;
    
  •  this.#resolveEndPromise();
    
  • }
  • const listeners: MessageStreamEventListeners | undefined = this.#listeners[event];
  • if (listeners) {
  •  this.#listeners[event] = listeners.filter((l) => !l.once) as any;
    
  •  listeners.forEach(({ listener }: any) => listener(...args));
    
  • }
  • if (event === 'abort') {
  •  const error = args[0] as APIUserAbortError;
    
  •  if (!this.#catchingPromiseCreated && !listeners?.length) {
    
  •    Promise.reject(error);
    
  •  }
    
  •  this.#rejectConnectedPromise(error);
    
  •  this.#rejectEndPromise(error);
    
  •  this._emit('end');
    
  •  return;
    
  • }
  • if (event === 'error') {
  •  // NOTE: _emit('error', error) should only be called from #handleError().
    
  •  const error = args[0] as AnthropicError;
    
  •  if (!this.#catchingPromiseCreated && !listeners?.length) {
    
  •    // Trigger an unhandled rejection if the user hasn't registered any error handlers.
    
  •    // If you are seeing stack traces here, make sure to handle errors via either:
    
  •    // - runner.on('error', () => ...)
    
  •    // - await runner.done()
    
  •    // - await runner.final...()
    
  •    // - etc.
    
  •    Promise.reject(error);
    
  •  }
    
  •  this.#rejectConnectedPromise(error);
    
  •  this.#rejectEndPromise(error);
    
  •  this._emit('end');
    
  • }
  • }
  • protected _emitFinal() {
  • const finalMessage = this.receivedMessages.at(-1);
  • if (finalMessage) {
  •  this._emit('finalMessage', this.#getFinalMessage());
    
  • }
  • }
  • #beginRequest() {
  • if (this.ended) return;
  • this.#currentMessageSnapshot = undefined;
  • }
  • #addStreamEvent(event: BetaMessageStreamEvent) {
  • if (this.ended) return;
  • const messageSnapshot = this.#accumulateMessage(event);
  • this._emit('streamEvent', event, messageSnapshot);
  • switch (event.type) {
  •  case 'content_block_delta': {
    
  •    const content = messageSnapshot.content.at(-1)!;
    
  •    if (event.delta.type === 'text_delta' && content.type === 'text') {
    
  •      this._emit('text', event.delta.text, content.text || '');
    
  •    } else if (event.delta.type === 'input_json_delta' && content.type === 'tool_use') {
    
  •      if (content.input) {
    
  •        this._emit('inputJson', event.delta.partial_json, content.input);
    
  •      }
    
  •    }
    
  •    break;
    
  •  }
    
  •  case 'message_stop': {
    
  •    this._addMessageParam(messageSnapshot);
    
  •    this._addMessage(messageSnapshot, true);
    
  •    break;
    
  •  }
    
  •  case 'content_block_stop': {
    
  •    this._emit('contentBlock', messageSnapshot.content.at(-1)!);
    
  •    break;
    
  •  }
    
  •  case 'message_start': {
    
  •    this.#currentMessageSnapshot = messageSnapshot;
    
  •    break;
    
  •  }
    
  •  case 'content_block_start':
    
  •  case 'message_delta':
    
  •    break;
    
  • }
  • }
  • #endRequest(): BetaMessage {
  • if (this.ended) {
  •  throw new AnthropicError(`stream has ended, this shouldn't happen`);
    
  • }
  • const snapshot = this.#currentMessageSnapshot;
  • if (!snapshot) {
  •  throw new AnthropicError(`request ended without sending any chunks`);
    
  • }
  • this.#currentMessageSnapshot = undefined;
  • return snapshot;
  • }
  • protected async _fromReadableStream(
  • readableStream: ReadableStream,
  • options?: Core.RequestOptions,
  • ): Promise {
  • const signal = options?.signal;
  • if (signal) {
  •  if (signal.aborted) this.controller.abort();
    
  •  signal.addEventListener('abort', () => this.controller.abort());
    
  • }
  • this.#beginRequest();
  • this._connected(null);
  • const stream = Stream.fromReadableStream(readableStream, this.controller);
  • for await (const event of stream) {
  •  this.#addStreamEvent(event);
    
  • }
  • if (stream.controller.signal?.aborted) {
  •  throw new APIUserAbortError();
    
  • }
  • this.#endRequest();
  • }
  • /**
    • Mutates this.#currentMessage with the current event. Handling the accumulation of multiple messages
    • will be needed to be handled by the caller, this method will throw if you try to accumulate for multiple
    • messages.
  • */
  • #accumulateMessage(event: BetaMessageStreamEvent): BetaMessage {
  • let snapshot = this.#currentMessageSnapshot;
  • if (event.type === 'message_start') {
  •  if (snapshot) {
    
  •    throw new AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
    
  •  }
    
  •  return event.message;
    
  • }
  • if (!snapshot) {
  •  throw new AnthropicError(`Unexpected event order, got ${event.type} before "message_start"`);
    
  • }
  • switch (event.type) {
  •  case 'message_stop':
    
  •    return snapshot;
    
  •  case 'message_delta':
    
  •    snapshot.stop_reason = event.delta.stop_reason;
    
  •    snapshot.stop_sequence = event.delta.stop_sequence;
    
  •    snapshot.usage.output_tokens = event.usage.output_tokens;
    
  •    return snapshot;
    
  •  case 'content_block_start':
    
  •    snapshot.content.push(event.content_block);
    
  •    return snapshot;
    
  •  case 'content_block_delta': {
    
  •    const snapshotContent = snapshot.content.at(event.index);
    
  •    if (snapshotContent?.type === 'text' && event.delta.type === 'text_delta') {
    
  •      snapshotContent.text += event.delta.text;
    
  •    } else if (snapshotContent?.type === 'tool_use' && event.delta.type === 'input_json_delta') {
    
  •      // we need to keep track of the raw JSON string as well so that we can
    
  •      // re-parse it for each delta, for now we just store it as an untyped
    
  •      // non-enumerable property on the snapshot
    
  •      let jsonBuf = (snapshotContent as any)[JSON_BUF_PROPERTY] || '';
    
  •      jsonBuf += event.delta.partial_json;
    
  •      Object.defineProperty(snapshotContent, JSON_BUF_PROPERTY, {
    
  •        value: jsonBuf,
    
  •        enumerable: false,
    
  •        writable: true,
    
  •      });
    
  •      if (jsonBuf) {
    
  •        snapshotContent.input = partialParse(jsonBuf);
    
  •      }
    
  •    }
    
  •    return snapshot;
    
  •  }
    
  •  case 'content_block_stop':
    
  •    return snapshot;
    
  • }
  • }
  • Symbol.asyncIterator: AsyncIterator {
  • const pushQueue: BetaMessageStreamEvent[] = [];
  • const readQueue: {
  •  resolve: (chunk: BetaMessageStreamEvent | undefined) => void;
    
  •  reject: (error: unknown) => void;
    
  • }[] = [];
  • let done = false;
  • this.on('streamEvent', (event) => {
  •  const reader = readQueue.shift();
    
  •  if (reader) {
    
  •    reader.resolve(event);
    
  •  } else {
    
  •    pushQueue.push(event);
    
  •  }
    
  • });
  • this.on('end', () => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.resolve(undefined);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • this.on('abort', (err) => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.reject(err);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • this.on('error', (err) => {
  •  done = true;
    
  •  for (const reader of readQueue) {
    
  •    reader.reject(err);
    
  •  }
    
  •  readQueue.length = 0;
    
  • });
  • return {
  •  next: async (): Promise<IteratorResult<BetaMessageStreamEvent>> => {
    
  •    if (!pushQueue.length) {
    
  •      if (done) {
    
  •        return { value: undefined, done: true };
    
  •      }
    
  •      return new Promise<BetaMessageStreamEvent | undefined>((resolve, reject) =>
    
  •        readQueue.push({ resolve, reject }),
    
  •      ).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true }));
    
  •    }
    
  •    const chunk = pushQueue.shift()!;
    
  •    return { value: chunk, done: false };
    
  •  },
    
  •  return: async () => {
    
  •    this.abort();
    
  •    return { value: undefined, done: true };
    
  •  },
    
  • };
  • }
  • toReadableStream(): ReadableStream {
  • const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
  • return stream.toReadableStream();
  • }
    +}
    diff --git src/lib/MessageStream.ts src/lib/MessageStream.ts
    index dea739f1..65e84b29 100644
    --- src/lib/MessageStream.ts
    +++ src/lib/MessageStream.ts
    @@ -10,7 +10,7 @@ import {
    type MessageCreateParamsBase,
    type TextBlock,
    } from '@anthropic-ai/sdk/resources/messages';
    -import { type ReadableStream } from '@anthropic-ai/sdk/_shims/index';
    +import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index';
    import { Stream } from '@anthropic-ai/sdk/streaming';
    import { partialParse } from '../_vendor/partial-json-parser/parser';

@@ -41,8 +41,8 @@ export class MessageStream implements AsyncIterable {

controller: AbortController = new AbortController();

  • #connectedPromise: Promise;
  • #resolveConnectedPromise: () => void = () => {};
  • #connectedPromise: Promise<Response | null>;

  • #resolveConnectedPromise: (response: Response | null) => void = () => {};
    #rejectConnectedPromise: (error: AnthropicError) => void = () => {};

    #endPromise: Promise;
    @@ -55,9 +55,10 @@ export class MessageStream implements AsyncIterable {
    #errored = false;
    #aborted = false;
    #catchingPromiseCreated = false;

  • #request_id: string | null | undefined;

    constructor() {

  • this.#connectedPromise = new Promise((resolve, reject) => {
  • this.#connectedPromise = new Promise<Response | null>((resolve, reject) => {
    this.#resolveConnectedPromise = resolve;
    this.#rejectConnectedPromise = reject;
    });
    @@ -75,6 +76,37 @@ export class MessageStream implements AsyncIterable {
    this.#endPromise.catch(() => {});
    }

  • get request_id(): string | null | undefined {

  • return this.#request_id;

  • }

  • /**

    • Returns the MessageStream data, the raw Response instance and the ID of the request,
    • returned vie the request-id header which is useful for debugging requests and resporting
    • issues to Anthropic.
    • This is the same as the APIPromise.withResponse() method.
    • This method will raise an error if you created the stream using MessageStream.fromReadableStream
    • as no Response is available.
  • */

  • async withResponse(): Promise<{

  • data: MessageStream;

  • response: Response;

  • request_id: string | null | undefined;

  • }> {

  • const response = await this.#connectedPromise;

  • if (!response) {

  •  throw new Error('Could not resolve a `Response` object');
    
  • }

  • return {

  •  data: this,
    
  •  response,
    
  •  request_id: response.headers.get('request-id'),
    
  • };

  • }

  • /**

    • Intended for use on the frontend, consuming a stream produced with
    • .toReadableStream() on the backend.
      @@ -136,11 +168,10 @@ export class MessageStream implements AsyncIterable {
      signal.addEventListener('abort', () => this.controller.abort());
      }
      this.#beginRequest();
  • const stream = await messages.create(
  •  { ...params, stream: true },
    
  •  { ...options, signal: this.controller.signal },
    
  • );
  • this._connected();
  • const { response, data: stream } = await messages
  •  .create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
    
  •  .withResponse();
    
  • this._connected(response);
    for await (const event of stream) {
    this.#addStreamEvent(event);
    }
    @@ -150,9 +181,10 @@ export class MessageStream implements AsyncIterable {
    this.#endRequest();
    }
  • protected _connected() {
  • protected _connected(response: Response | null) {
    if (this.ended) return;
  • this.#resolveConnectedPromise();
  • this.#request_id = response?.headers.get('request-id');
  • this.#resolveConnectedPromise(response);
    this._emit('connect');
    }

@@ -424,7 +456,7 @@ export class MessageStream implements AsyncIterable {
signal.addEventListener('abort', () => this.controller.abort());
}
this.#beginRequest();

  • this._connected();
  • this._connected(null);
    const stream = Stream.fromReadableStream(readableStream, this.controller);
    for await (const event of stream) {
    this.#addStreamEvent(event);
    diff --git src/resources/beta/messages/batches.ts src/resources/beta/messages/batches.ts
    index 0a863e64..74f4e53b 100644
    --- src/resources/beta/messages/batches.ts
    +++ src/resources/beta/messages/batches.ts
    @@ -85,6 +85,35 @@ export class Batches extends APIResource {
    });
    }

  • /**

    • This endpoint is idempotent and can be used to poll for Message Batch
    • completion. To access the results of a Message Batch, make a request to the
    • results_url field in the response.
  • */

  • delete(

  • messageBatchId: string,

  • params?: BatchDeleteParams,

  • options?: Core.RequestOptions,

  • ): Core.APIPromise;

  • delete(messageBatchId: string, options?: Core.RequestOptions): Core.APIPromise;

  • delete(

  • messageBatchId: string,

  • params: BatchDeleteParams | Core.RequestOptions = {},

  • options?: Core.RequestOptions,

  • ): Core.APIPromise {

  • if (isRequestOptions(params)) {

  •  return this.delete(messageBatchId, {}, params);
    
  • }

  • const { betas } = params;

  • return this._client.delete(/v1/messages/batches/${messageBatchId}?beta=true, {

  •  ...options,
    
  •  headers: {
    
  •    'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
    
  •    ...options?.headers,
    
  •  },
    
  • });

  • }

  • /**

    • Batches may be canceled any time before processing ends. Once cancellation is
    • initiated, the batch enters a canceling state, at which time the system may
      @@ -158,6 +187,7 @@ export class Batches extends APIResource {
      ...options,
      headers: {
      'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
  •      Accept: 'application/binary',
         ...options?.headers,
       },
       __binaryResponse: true,
    

@@ -168,6 +198,20 @@ export class Batches extends APIResource {

export class BetaMessageBatchesPage extends Page {}

+export interface BetaDeletedMessageBatch {

  • /**
    • ID of the Message Batch.
  • */
  • id: string;
  • /**
    • Deleted object type.
    • For Message Batches, this is always "message_batch_deleted".
  • */
  • type: 'message_batch_deleted';
    +}

export interface BetaMessageBatch {
/**
* Unique object identifier.
@@ -374,6 +418,13 @@ export interface BatchListParams extends PageParams {
betas?: Array<BetaAPI.AnthropicBeta>;
}

+export interface BatchDeleteParams {

  • /**
    • Optional header to specify the beta version(s) you want to use.
  • */
  • betas?: Array<BetaAPI.AnthropicBeta>;
    +}

export interface BatchCancelParams {
/**
* Optional header to specify the beta version(s) you want to use.
@@ -392,6 +443,7 @@ Batches.BetaMessageBatchesPage = BetaMessageBatchesPage;

export declare namespace Batches {
export {

  • type BetaDeletedMessageBatch as BetaDeletedMessageBatch,
    type BetaMessageBatch as BetaMessageBatch,
    type BetaMessageBatchCanceledResult as BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult as BetaMessageBatchErroredResult,
    @@ -404,6 +456,7 @@ export declare namespace Batches {
    type BatchCreateParams as BatchCreateParams,
    type BatchRetrieveParams as BatchRetrieveParams,
    type BatchListParams as BatchListParams,
  • type BatchDeleteParams as BatchDeleteParams,
    type BatchCancelParams as BatchCancelParams,
    type BatchResultsParams as BatchResultsParams,
    };
    diff --git src/resources/beta/messages/index.ts src/resources/beta/messages/index.ts
    index 2cf85964..eac5d34f 100644
    --- src/resources/beta/messages/index.ts
    +++ src/resources/beta/messages/index.ts
    @@ -3,6 +3,7 @@
    export {
    BetaMessageBatchesPage,
    Batches,
  • type BetaDeletedMessageBatch,
    type BetaMessageBatch,
    type BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult,
    @@ -14,6 +15,7 @@ export {
    type BatchCreateParams,
    type BatchRetrieveParams,
    type BatchListParams,
  • type BatchDeleteParams,
    type BatchCancelParams,
    type BatchResultsParams,
    } from './batches';
    @@ -58,4 +60,5 @@ export {
    type MessageCreateParamsNonStreaming,
    type MessageCreateParamsStreaming,
    type MessageCountTokensParams,
  • type BetaMessageStreamParams,
    } from './messages';
    diff --git src/resources/beta/messages/messages.ts src/resources/beta/messages/messages.ts
    index 186a6c36..ecb1d79f 100644
    --- src/resources/beta/messages/messages.ts
    +++ src/resources/beta/messages/messages.ts
    @@ -10,10 +10,12 @@ import * as BatchesAPI from './batches';
    import {
    BatchCancelParams,
    BatchCreateParams,
  • BatchDeleteParams,
    BatchListParams,
    BatchResultsParams,
    BatchRetrieveParams,
    Batches,
  • BetaDeletedMessageBatch,
    BetaMessageBatch,
    BetaMessageBatchCanceledResult,
    BetaMessageBatchErroredResult,
    @@ -25,6 +27,21 @@ import {
    BetaMessageBatchesPage,
    } from './batches';
    import { Stream } from '../../../streaming';
    +import { BetaMessageStream } from '../../../lib/BetaMessageStream';
    +import type { Model } from '../../messages/messages';

+const DEPRECATED_MODELS: {

  • [K in Model]?: string;
    +} = {
  • 'claude-1.3': 'November 6th, 2024',
  • 'claude-1.3-100k': 'November 6th, 2024',
  • 'claude-instant-1.1': 'November 6th, 2024',
  • 'claude-instant-1.1-100k': 'November 6th, 2024',
  • 'claude-instant-1.2': 'November 6th, 2024',
  • 'claude-3-sonnet-20240229': 'July 21st, 2025',
  • 'claude-2.1': 'July 21st, 2025',
  • 'claude-2.0': 'July 21st, 2025',
    +};

export class Messages extends APIResource {
batches: BatchesAPI.Batches = new BatchesAPI.Batches(this._client);
@@ -50,6 +67,15 @@ export class Messages extends APIResource {
options?: Core.RequestOptions,
): APIPromise | APIPromise<Stream> {
const { betas, ...body } = params;
+

  • if (body.model in DEPRECATED_MODELS) {

  •  console.warn(
    
  •    `The model '${body.model}' is deprecated and will reach end-of-life on ${
    
  •      DEPRECATED_MODELS[body.model]
    
  •    }\nPlease migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resources/model-deprecations for more information.`,
    
  •  );
    
  • }

  • return this._client.post('/v1/messages?beta=true', {
    body,
    timeout: (this._client as any)._options.timeout ?? 600000,
    @@ -62,6 +88,13 @@ export class Messages extends APIResource {
    }) as APIPromise | APIPromise<Stream>;
    }

  • /**

    • Create a Message stream
  • */

  • stream(body: BetaMessageStreamParams, options?: Core.RequestOptions): BetaMessageStream {

  • return BetaMessageStream.createMessage(this, body, options);

  • }

  • /**

    • Count the number of tokens in a Message.

@@ -84,6 +117,8 @@ export class Messages extends APIResource {
}
}

+export type BetaMessageStreamParams = MessageCreateParamsBase;
+
export interface BetaBase64PDFBlock {
source: BetaBase64PDFSource;

@@ -1115,6 +1150,7 @@ export declare namespace Messages {

export {
Batches as Batches,

  • type BetaDeletedMessageBatch as BetaDeletedMessageBatch,
    type BetaMessageBatch as BetaMessageBatch,
    type BetaMessageBatchCanceledResult as BetaMessageBatchCanceledResult,
    type BetaMessageBatchErroredResult as BetaMessageBatchErroredResult,
    @@ -1127,6 +1163,7 @@ export declare namespace Messages {
    type BatchCreateParams as BatchCreateParams,
    type BatchRetrieveParams as BatchRetrieveParams,
    type BatchListParams as BatchListParams,

  • type BatchDeleteParams as BatchDeleteParams,
    type BatchCancelParams as BatchCancelParams,
    type BatchResultsParams as BatchResultsParams,
    };
    diff --git src/resources/messages/batches.ts src/resources/messages/batches.ts
    index b4fd45e8..a6b328e2 100644
    --- src/resources/messages/batches.ts
    +++ src/resources/messages/batches.ts
    @@ -49,6 +49,15 @@ export class Batches extends APIResource {
    return this._client.getAPIList('/v1/messages/batches', MessageBatchesPage, { query, ...options });
    }

  • /**

    • This endpoint is idempotent and can be used to poll for Message Batch
    • completion. To access the results of a Message Batch, make a request to the
    • results_url field in the response.
  • */

  • delete(messageBatchId: string, options?: Core.RequestOptions): Core.APIPromise {

  • return this._client.delete(/v1/messages/batches/${messageBatchId}, options);

  • }

  • /**

    • Batches may be canceled any time before processing ends. Once cancellation is
    • initiated, the batch enters a canceling state, at which time the system may
      @@ -83,13 +92,34 @@ export class Batches extends APIResource {
      }

    return this._client

  •  .get(batch.results_url, { ...options, __binaryResponse: true })
    
  •  .get(batch.results_url, {
    
  •    ...options,
    
  •    headers: {
    
  •      Accept: 'application/binary',
    
  •      ...options?.headers,
    
  •    },
    
  •    __binaryResponse: true,
    
  •  })
     ._thenUnwrap((_, props) => JSONLDecoder.fromResponse(props.response, props.controller));
    
    }
    }

export class MessageBatchesPage extends Page {}

+export interface DeletedMessageBatch {

  • /**
    • ID of the Message Batch.
  • */
  • id: string;
  • /**
    • Deleted object type.
    • For Message Batches, this is always "message_batch_deleted".
  • */
  • type: 'message_batch_deleted';
    +}

export interface MessageBatch {
/**
* Unique object identifier.
@@ -283,6 +313,7 @@ Batches.MessageBatchesPage = MessageBatchesPage;

export declare namespace Batches {
export {

  • type DeletedMessageBatch as DeletedMessageBatch,
    type MessageBatch as MessageBatch,
    type MessageBatchCanceledResult as MessageBatchCanceledResult,
    type MessageBatchErroredResult as MessageBatchErroredResult,
    diff --git src/resources/messages/index.ts src/resources/messages/index.ts
    index 10308d2a..1c9178ad 100644
    --- src/resources/messages/index.ts
    +++ src/resources/messages/index.ts
    @@ -3,6 +3,7 @@
    export {
    MessageBatchesPage,
    Batches,
  • type DeletedMessageBatch,
    type MessageBatch,
    type MessageBatchCanceledResult,
    type MessageBatchErroredResult,
    diff --git src/resources/messages/messages.ts src/resources/messages/messages.ts
    index a1affbf5..12cc9b83 100644
    --- src/resources/messages/messages.ts
    +++ src/resources/messages/messages.ts
    @@ -9,6 +9,7 @@ import {
    BatchCreateParams,
    BatchListParams,
    Batches,
  • DeletedMessageBatch,
    MessageBatch,
    MessageBatchCanceledResult,
    MessageBatchErroredResult,
    @@ -308,16 +309,17 @@ export type Model =
    | 'claude-2.1'
    | 'claude-2.0';

-type DeprecatedModelsType = {
+const DEPRECATED_MODELS: {
[K in Model]?: string;
-};

-const DEPRECATED_MODELS: DeprecatedModelsType = {
+} = {
'claude-1.3': 'November 6th, 2024',
'claude-1.3-100k': 'November 6th, 2024',
'claude-instant-1.1': 'November 6th, 2024',
'claude-instant-1.1-100k': 'November 6th, 2024',
'claude-instant-1.2': 'November 6th, 2024',

  • 'claude-3-sonnet-20240229': 'July 21st, 2025',
  • 'claude-2.1': 'July 21st, 2025',
  • 'claude-2.0': 'July 21st, 2025',
    };

export interface RawContentBlockDeltaEvent {
@@ -1114,6 +1116,7 @@ export declare namespace Messages {

export {
Batches as Batches,

  • type DeletedMessageBatch as DeletedMessageBatch,
    type MessageBatch as MessageBatch,
    type MessageBatchCanceledResult as MessageBatchCanceledResult,
    type MessageBatchErroredResult as MessageBatchErroredResult,
    diff --git src/version.ts src/version.ts
    index 4a46c186..3f1d4329 100644
    --- src/version.ts
    +++ src/version.ts
    @@ -1 +1 @@
    -export const VERSION = '0.33.1'; // x-release-please-version
    +export const VERSION = '0.35.0'; // x-release-please-version
    diff --git tests/api-resources/beta/messages/batches.test.ts tests/api-resources/beta/messages/batches.test.ts
    index e395910a..98d39506 100644
    --- tests/api-resources/beta/messages/batches.test.ts
    +++ tests/api-resources/beta/messages/batches.test.ts
    @@ -60,7 +60,7 @@ describe('resource batches', () => {
    },
    },
    },
  •            name: 'x',
    
  •            name: 'name',
               cache_control: { type: 'ephemeral' },
               description: 'Get the current weather in a given location',
               type: 'custom',
    

@@ -132,6 +132,35 @@ describe('resource batches', () => {
).rejects.toThrow(Anthropic.NotFoundError);
});

  • test('delete', async () => {
  • const responsePromise = client.beta.messages.batches.delete('message_batch_id');
  • const rawResponse = await responsePromise.asResponse();
  • expect(rawResponse).toBeInstanceOf(Response);
  • const response = await responsePromise;
  • expect(response).not.toBeInstanceOf(Response);
  • const dataAndResponse = await responsePromise.withResponse();
  • expect(dataAndResponse.data).toBe(response);
  • expect(dataAndResponse.response).toBe(rawResponse);
  • });
  • test('delete: request options instead of params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.beta.messages.batches.delete('message_batch_id', { path: '/_stainless_unknown_path' }),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('delete: request options and params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.beta.messages.batches.delete(
    
  •    'message_batch_id',
    
  •    { betas: ['string'] },
    
  •    { path: '/_stainless_unknown_path' },
    
  •  ),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('cancel', async () => {
    const responsePromise = client.beta.messages.batches.cancel('message_batch_id');
    const rawResponse = await responsePromise.asResponse();
    diff --git tests/api-resources/beta/messages/messages.test.ts tests/api-resources/beta/messages/messages.test.ts
    index ec73d9c0..493de962 100644
    --- tests/api-resources/beta/messages/messages.test.ts
    +++ tests/api-resources/beta/messages/messages.test.ts
    @@ -44,7 +44,7 @@ describe('resource messages', () => {
    unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
    },
    },
  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
         type: 'custom',
    

@@ -85,7 +85,7 @@ describe('resource messages', () => {
unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
},
},

  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
         type: 'custom',
    

diff --git tests/api-resources/messages/batches.test.ts tests/api-resources/messages/batches.test.ts
index 26efdbc8..4137fa31 100644
--- tests/api-resources/messages/batches.test.ts
+++ tests/api-resources/messages/batches.test.ts
@@ -59,7 +59,7 @@ describe('resource batches', () => {
},
},
},

  •            name: 'x',
    
  •            name: 'name',
               cache_control: { type: 'ephemeral' },
               description: 'Get the current weather in a given location',
             },
    

@@ -118,6 +118,24 @@ describe('resource batches', () => {
).rejects.toThrow(Anthropic.NotFoundError);
});

  • test('delete', async () => {
  • const responsePromise = client.messages.batches.delete('message_batch_id');
  • const rawResponse = await responsePromise.asResponse();
  • expect(rawResponse).toBeInstanceOf(Response);
  • const response = await responsePromise;
  • expect(response).not.toBeInstanceOf(Response);
  • const dataAndResponse = await responsePromise.withResponse();
  • expect(dataAndResponse.data).toBe(response);
  • expect(dataAndResponse.response).toBe(rawResponse);
  • });
  • test('delete: request options instead of params are passed correctly', async () => {
  • // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
  • await expect(
  •  client.messages.batches.delete('message_batch_id', { path: '/_stainless_unknown_path' }),
    
  • ).rejects.toThrow(Anthropic.NotFoundError);
  • });
  • test('cancel', async () => {
    const responsePromise = client.messages.batches.cancel('message_batch_id');
    const rawResponse = await responsePromise.asResponse();
    diff --git tests/api-resources/messages/messages.test.ts tests/api-resources/messages/messages.test.ts
    index 3ae41d32..7b9d6f96 100644
    --- tests/api-resources/messages/messages.test.ts
    +++ tests/api-resources/messages/messages.test.ts
    @@ -44,7 +44,7 @@ describe('resource messages', () => {
    unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
    },
    },
  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
       },
    

@@ -83,7 +83,7 @@ describe('resource messages', () => {
unit: { description: 'Unit for the output - one of (celsius, fahrenheit)', type: 'string' },
},
},

  •      name: 'x',
    
  •      name: 'name',
         cache_control: { type: 'ephemeral' },
         description: 'Get the current weather in a given location',
       },
    

diff --git tests/index.test.ts tests/index.test.ts
index b6398085..bc0c1645 100644
--- tests/index.test.ts
+++ tests/index.test.ts
@@ -96,6 +96,15 @@ describe('instantiate client', () => {
expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true });
});

  • test('explicit global fetch', async () => {

  • // make sure the global fetch type is assignable to our Fetch type

  • const client = new Anthropic({

  •  baseURL: 'http://localhost:5000/',
    
  •  apiKey: 'my-anthropic-api-key',
    
  •  fetch: defaultFetch,
    
  • });

  • });

  • test('custom signal', async () => {
    const client = new Anthropic({
    baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
    @@ -122,6 +131,23 @@ describe('instantiate client', () => {
    expect(spy).toHaveBeenCalledTimes(1);
    });

  • test('normalized method', async () => {

  • let capturedRequest: RequestInit | undefined;

  • const testFetch = async (url: RequestInfo, init: RequestInit = {}): Promise => {

  •  capturedRequest = init;
    
  •  return new Response(JSON.stringify({}), { headers: { 'Content-Type': 'application/json' } });
    
  • };

  • const client = new Anthropic({

  •  baseURL: 'http://localhost:5000/',
    
  •  apiKey: 'my-anthropic-api-key',
    
  •  fetch: testFetch,
    
  • });

  • await client.patch('/foo');

  • expect(capturedRequest?.method).toEqual('PATCH');

  • });

  • describe('baseUrl', () => {
    test('trailing slash', () => {
    const client = new Anthropic({


</details>

### Description
This pull request includes several enhancements and bug fixes to the anthropic-sdk-typescript repository:

1. **Version Bumps**:
   - Updated the main SDK version to 0.35.0.
   - Updated the vertex-sdk version to 0.6.3.
   - Updated the bedrock-sdk version to 0.12.2.

2. **Added Features**:
   - Added beta message streaming helpers.
   - Introduced `.withResponse()` method in the stream.
   - Added `.request_id` getter in the streaming.

3. **Documentation Updates**:
   - Corrected various documentation issues.
   - Added new examples for token counting.
   - Minor formatting changes and README improvements, including additional example corrections.

4. **Bug Fixes**:
   - Improved type consistency for client options.
   - Corrected Accept header for certain endpoints.
   - Added the beta.messages.countTokens method to vertex-sdk.

5. **Chores**:
   - Deprecated some outdated models.
   - Temporary reversion of certain commits for stability.
   - Added more internal tests and example updates.

6. **Internal Changes and Refactoring**:
   - Refactored message batch delete operations to support new SDK versions.
   - Added additional test cases for delete operations on message batches.
   - Introduced BetaMessageStream and related tests.
   - Made adjustments in the methods to normalize HTTP methods and handler signal events correctly.

### Security Hotspots
1. **Fetching with Custom/Global Fetch**:
   - The implementation now allows custom and global fetch functions, requiring developers to ensure that these fetch implementations are secure and not leaking sensitive information.
   - Validate the use of fetch and ensure proper security measures are in place for client-side usage.

2. **Deprecation Warnings**:
   - The PR introduces deprecation warnings, which if not properly handled, might lead to using unsupported API endpoints potentially introducing security or operational risks.

<details>
<summary><i>Changes</i></summary>

### Changes
1. **Manifest and Configurations**
   - `.release-please-manifest.json`:
     ```diff
     -".": "0.33.1",
     - "packages/vertex-sdk": "0.6.1",
     - "packages/bedrock-sdk": "0.12.0"
     + ".": "0.35.0",
     + "packages/vertex-sdk": "0.6.3",
     + "packages/bedrock-sdk": "0.12.2"
     ```
   - `.stats.yml`:
     ```diff
     - configured_endpoints: 19
     - openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-be055148d227480fcacc9086c37ac8009dcb487731069ada51af35044f65bee4.yml
     + configured_endpoints: 21
     + openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-fd67aea6883f1ee9e46f31a42d3940f0acb1749e787055bd9b9f278b20fa53ec.yml
     ```

2. **Changelog Updates**
   - `CHANGELOG.md`:
     ```diff
     ## 0.35.0 (2025-01-21)
     - Full Changelog: sdk-v0.34.0...sdk-v0.35.0
     ...
     +### Documentation
     +* **readme:** fix misplaced period ([#650](https://github.com/anthropics/anthropic-sdk-typescript/issues/650)) ([8754744](https://github.com/anthropics/anthropic-sdk-typescript/commit/87547448c8b4bf69a61756af1f12927f33b68680))
     ```

3. **Added Example**
   - `examples/count-tokens.ts`:
     ```typescript
     +#!/usr/bin/env -S npm run tsn -T
     +import Anthropic from '@anthropic-ai/sdk';
     +const client = new Anthropic(); // gets API Key from environment variable ANTHROPIC_API_KEY
     +async function main() {
     +  const result = await client.messages.countTokens({
     +    messages: [
     +      {
     +        role: 'user',
     +        content: 'Hey Claude!?',
     +      },
     +    ],
     +    model: 'claude-3-5-sonnet-latest',
     +  });
     +  console.dir(result);
     +}
     +main();
     ```

4. **Package Updates**
   - `package.json`:
     ```diff
     - "version": "0.33.1",
     + "version": "0.35.0",
     ```

5. **SDK Enhancements**
   - `src/core.ts`:
     ```diff
     + if (fetchOptions.method) {
     +   fetchOptions.method = fetchOptions.method.toUpperCase();
     + }
     ```

6. **Testing Enhancements**
   - `tests/api-resources/beta/messages/batches.test.ts`:
     ```diff
     +test('delete: request options and params are passed correctly', async () => {
     +  await expect(
     +    client.beta.messages.batches.delete(
     +      'message_batch_id',
     +      { betas: ['string'] },
     +      { path: '/_stainless_unknown_path' },
     +    ),
     +  ).rejects.toThrow(Anthropic.NotFoundError);
     +});
     ```



```mermaid
sequenceDiagram
    participant User
    participant SDK as SDK Library
    participant API as Backend API
    participant Logger

    User->>+SDK: Call createMessageStream()
    Note over SDK: Initialize BetaMessageStream
    SDK->>API: Call messages.create with streaming option
    API-->>SDK: StreamMessageEvent
    SDK->>Logger: Emit Event (text, message, contentBlock, etc.)
    Note over SDK, Logger: Resolve Promises, Call Listeners

    User->>+SDK: Call countTokens()
    SDK->>API: POST /messages/tokens
    API-->>SDK: Return Token Count
    SDK-->>User: Return Token Count

    User->>SDK: Log Deprecation Warning (if applicable)
    SDK->>Logger: Log Deprecation Warning

@thypon thypon merged commit 44a9076 into main Jan 29, 2025
8 checks passed
@thypon thypon deleted the renovate/anthropic-ai-sdk-0.x branch January 29, 2025 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant