From 751ecd0d44707b21ccb390c81716937fae3d8e35 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:25:03 +0000 Subject: [PATCH 1/3] chore(docs): updates (#673) --- .stats.yml | 2 +- src/resources/beta/messages/batches.ts | 4 ++++ src/resources/messages/batches.ts | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index e7d06698..64f8716d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-7270ee0a79d885681ee507414608229f61c27f47c40f355dcd210b38aa7cddf1.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-f5276eeef7512112e802c85530c51e0a971ee521eebe3a0db309621587b4973d.yml diff --git a/src/resources/beta/messages/batches.ts b/src/resources/beta/messages/batches.ts index 04d3c9cf..6370119c 100644 --- a/src/resources/beta/messages/batches.ts +++ b/src/resources/beta/messages/batches.ts @@ -299,6 +299,10 @@ export interface BetaMessageBatchExpiredResult { type: 'expired'; } +/** + * This is a single line in the response `.jsonl` file and does not represent the + * response as a whole. + */ export interface BetaMessageBatchIndividualResponse { /** * Developer-provided ID created for each request in a Message Batch. Useful for diff --git a/src/resources/messages/batches.ts b/src/resources/messages/batches.ts index a185b6cc..46bc64ed 100644 --- a/src/resources/messages/batches.ts +++ b/src/resources/messages/batches.ts @@ -207,6 +207,10 @@ export interface MessageBatchExpiredResult { type: 'expired'; } +/** + * This is a single line in the response `.jsonl` file and does not represent the + * response as a whole. + */ export interface MessageBatchIndividualResponse { /** * Developer-provided ID created for each request in a Message Batch. Useful for From 522118ffeab327e8476f12d9b9fa1f19042ed714 Mon Sep 17 00:00:00 2001 From: Robert Craigie Date: Mon, 27 Jan 2025 16:14:33 +0000 Subject: [PATCH 2/3] fix(streaming): accumulate citations (#675) --- src/lib/BetaMessageStream.ts | 83 +++++++++++++++++++++++++---------- src/lib/MessageStream.ts | 84 ++++++++++++++++++++++++++---------- 2 files changed, 123 insertions(+), 44 deletions(-) diff --git a/src/lib/BetaMessageStream.ts b/src/lib/BetaMessageStream.ts index 2baa482a..5de54f06 100644 --- a/src/lib/BetaMessageStream.ts +++ b/src/lib/BetaMessageStream.ts @@ -9,6 +9,7 @@ import { type MessageCreateParams as BetaMessageCreateParams, type MessageCreateParamsBase as BetaMessageCreateParamsBase, type BetaTextBlock, + type BetaTextCitation, } 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'; @@ -18,6 +19,7 @@ export interface MessageStreamEvents { connect: () => void; streamEvent: (event: BetaMessageStreamEvent, snapshot: BetaMessage) => void; text: (textDelta: string, textSnapshot: string) => void; + citation: (citation: BetaTextCitation, citationsSnapshot: BetaTextCitation[]) => void; inputJson: (partialJson: string, jsonSnapshot: unknown) => void; message: (message: BetaMessage) => void; contentBlock: (content: BetaContentBlock) => void; @@ -413,12 +415,27 @@ export class BetaMessageStream implements AsyncIterable 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); + switch (event.delta.type) { + case 'text_delta': { + if (content.type === 'text') { + this._emit('text', event.delta.text, content.text || ''); + } + break; } + case 'citations_delta': { + if (content.type === 'text') { + this._emit('citation', event.delta.citation, content.citations ?? []); + } + break; + } + case 'input_json_delta': { + if (content.type === 'tool_use' && content.input) { + this._emit('inputJson', event.delta.partial_json, content.input); + } + break; + } + default: + checkNever(event.delta); } break; } @@ -505,24 +522,43 @@ export class BetaMessageStream implements AsyncIterable 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); + + switch (event.delta.type) { + case 'text_delta': { + if (snapshotContent?.type === 'text') { + snapshotContent.text += event.delta.text; + } + break; } + case 'citations_delta': { + if (snapshotContent?.type === 'text') { + snapshotContent.citations ??= []; + snapshotContent.citations.push(event.delta.citation); + } + break; + } + case 'input_json_delta': { + if (snapshotContent?.type === 'tool_use') { + // 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); + } + } + break; + } + default: + checkNever(event.delta); } return snapshot; } @@ -597,3 +633,6 @@ export class BetaMessageStream implements AsyncIterable return stream.toReadableStream(); } } + +// used to ensure exhaustive case matching without throwing a runtime error +function checkNever(x: never) {} diff --git a/src/lib/MessageStream.ts b/src/lib/MessageStream.ts index b47cded0..4ce3a382 100644 --- a/src/lib/MessageStream.ts +++ b/src/lib/MessageStream.ts @@ -9,6 +9,7 @@ import { type MessageCreateParams, type MessageCreateParamsBase, type TextBlock, + type TextCitation, } from '@anthropic-ai/sdk/resources/messages'; import { type ReadableStream, type Response } from '@anthropic-ai/sdk/_shims/index'; import { Stream } from '@anthropic-ai/sdk/streaming'; @@ -18,6 +19,7 @@ export interface MessageStreamEvents { connect: () => void; streamEvent: (event: MessageStreamEvent, snapshot: Message) => void; text: (textDelta: string, textSnapshot: string) => void; + citation: (citation: TextCitation, citationsSnapshot: TextCitation[]) => void; inputJson: (partialJson: string, jsonSnapshot: unknown) => void; message: (message: Message) => void; contentBlock: (content: ContentBlock) => void; @@ -413,12 +415,27 @@ export class MessageStream implements AsyncIterable { 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); + switch (event.delta.type) { + case 'text_delta': { + if (content.type === 'text') { + this._emit('text', event.delta.text, content.text || ''); + } + break; } + case 'citations_delta': { + if (content.type === 'text') { + this._emit('citation', event.delta.citation, content.citations ?? []); + } + break; + } + case 'input_json_delta': { + if (content.type === 'tool_use' && content.input) { + this._emit('inputJson', event.delta.partial_json, content.input); + } + break; + } + default: + checkNever(event.delta); } break; } @@ -505,25 +522,45 @@ export class MessageStream implements AsyncIterable { 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); + + switch (event.delta.type) { + case 'text_delta': { + if (snapshotContent?.type === 'text') { + snapshotContent.text += event.delta.text; + } + break; + } + case 'citations_delta': { + if (snapshotContent?.type === 'text') { + snapshotContent.citations ??= []; + snapshotContent.citations.push(event.delta.citation); + } + break; } + case 'input_json_delta': { + if (snapshotContent?.type === 'tool_use') { + // 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); + } + } + break; + } + default: + checkNever(event.delta); } + return snapshot; } case 'content_block_stop': @@ -597,3 +634,6 @@ export class MessageStream implements AsyncIterable { return stream.toReadableStream(); } } + +// used to ensure exhaustive case matching without throwing a runtime error +function checkNever(x: never) {} From 8988db1c85ad0508ac3771259778e62fad3177a3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 16:15:00 +0000 Subject: [PATCH 3/3] chore: release main --- .release-please-manifest.json | 2 +- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- packages/bedrock-sdk/yarn.lock | 2 +- packages/vertex-sdk/yarn.lock | 2 +- src/version.ts | 2 +- 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3d91c0c7..e6222438 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,5 +1,5 @@ { - ".": "0.36.2", + ".": "0.36.3", "packages/vertex-sdk": "0.6.4", "packages/bedrock-sdk": "0.12.4" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 66a6694f..da99f256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.36.3 (2025-01-27) + +Full Changelog: [sdk-v0.36.2...sdk-v0.36.3](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.36.2...sdk-v0.36.3) + +### Bug Fixes + +* **streaming:** accumulate citations ([#675](https://github.com/anthropics/anthropic-sdk-typescript/issues/675)) ([522118f](https://github.com/anthropics/anthropic-sdk-typescript/commit/522118ffeab327e8476f12d9b9fa1f19042ed714)) + + +### Chores + +* **docs:** updates ([#673](https://github.com/anthropics/anthropic-sdk-typescript/issues/673)) ([751ecd0](https://github.com/anthropics/anthropic-sdk-typescript/commit/751ecd0d44707b21ccb390c81716937fae3d8e35)) + ## 0.36.2 (2025-01-23) Full Changelog: [sdk-v0.36.1...sdk-v0.36.2](https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.36.1...sdk-v0.36.2) diff --git a/package.json b/package.json index 9ffbee79..6fb9c0c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@anthropic-ai/sdk", - "version": "0.36.2", + "version": "0.36.3", "description": "The official TypeScript library for the Anthropic API", "author": "Anthropic ", "types": "dist/index.d.ts", diff --git a/packages/bedrock-sdk/yarn.lock b/packages/bedrock-sdk/yarn.lock index 88dba610..e38e12b0 100644 --- a/packages/bedrock-sdk/yarn.lock +++ b/packages/bedrock-sdk/yarn.lock @@ -17,7 +17,7 @@ "@anthropic-ai/sdk@file:../../dist": # x-release-please-start-version - version "0.36.2" + version "0.36.3" # x-release-please-end-version dependencies: "@types/node" "^18.11.18" diff --git a/packages/vertex-sdk/yarn.lock b/packages/vertex-sdk/yarn.lock index 9320c797..a4394b8a 100644 --- a/packages/vertex-sdk/yarn.lock +++ b/packages/vertex-sdk/yarn.lock @@ -17,7 +17,7 @@ "@anthropic-ai/sdk@file:../../dist": # x-release-please-start-version - version "0.36.2" + version "0.36.3" # x-release-please-end-version dependencies: "@types/node" "^18.11.18" diff --git a/src/version.ts b/src/version.ts index ea46c671..0d285762 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.36.2'; // x-release-please-version +export const VERSION = '0.36.3'; // x-release-please-version