Add extracted source directory and README navigation

This commit is contained in:
Shawn Bot
2026-03-31 14:56:06 +00:00
parent 6252bb6eb5
commit 91e01d755b
4757 changed files with 984951 additions and 0 deletions

View File

@@ -0,0 +1,616 @@
var _BetaMessageStream_instances, _BetaMessageStream_currentMessageSnapshot, _BetaMessageStream_params, _BetaMessageStream_connectedPromise, _BetaMessageStream_resolveConnectedPromise, _BetaMessageStream_rejectConnectedPromise, _BetaMessageStream_endPromise, _BetaMessageStream_resolveEndPromise, _BetaMessageStream_rejectEndPromise, _BetaMessageStream_listeners, _BetaMessageStream_ended, _BetaMessageStream_errored, _BetaMessageStream_aborted, _BetaMessageStream_catchingPromiseCreated, _BetaMessageStream_response, _BetaMessageStream_request_id, _BetaMessageStream_logger, _BetaMessageStream_getFinalMessage, _BetaMessageStream_getFinalText, _BetaMessageStream_handleError, _BetaMessageStream_beginRequest, _BetaMessageStream_addStreamEvent, _BetaMessageStream_endRequest, _BetaMessageStream_accumulateMessage;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
import { partialParse } from "../_vendor/partial-json-parser/parser.mjs";
import { AnthropicError, APIUserAbortError } from "../error.mjs";
import { isAbortError } from "../internal/errors.mjs";
import { Stream } from "../streaming.mjs";
import { maybeParseBetaMessage } from "./beta-parser.mjs";
const JSON_BUF_PROPERTY = '__json_buf';
function tracksToolInput(content) {
return content.type === 'tool_use' || content.type === 'server_tool_use' || content.type === 'mcp_tool_use';
}
export class BetaMessageStream {
constructor(params, opts) {
_BetaMessageStream_instances.add(this);
this.messages = [];
this.receivedMessages = [];
_BetaMessageStream_currentMessageSnapshot.set(this, void 0);
_BetaMessageStream_params.set(this, null);
this.controller = new AbortController();
_BetaMessageStream_connectedPromise.set(this, void 0);
_BetaMessageStream_resolveConnectedPromise.set(this, () => { });
_BetaMessageStream_rejectConnectedPromise.set(this, () => { });
_BetaMessageStream_endPromise.set(this, void 0);
_BetaMessageStream_resolveEndPromise.set(this, () => { });
_BetaMessageStream_rejectEndPromise.set(this, () => { });
_BetaMessageStream_listeners.set(this, {});
_BetaMessageStream_ended.set(this, false);
_BetaMessageStream_errored.set(this, false);
_BetaMessageStream_aborted.set(this, false);
_BetaMessageStream_catchingPromiseCreated.set(this, false);
_BetaMessageStream_response.set(this, void 0);
_BetaMessageStream_request_id.set(this, void 0);
_BetaMessageStream_logger.set(this, void 0);
_BetaMessageStream_handleError.set(this, (error) => {
__classPrivateFieldSet(this, _BetaMessageStream_errored, true, "f");
if (isAbortError(error)) {
error = new APIUserAbortError();
}
if (error instanceof APIUserAbortError) {
__classPrivateFieldSet(this, _BetaMessageStream_aborted, true, "f");
return this._emit('abort', error);
}
if (error instanceof AnthropicError) {
return this._emit('error', error);
}
if (error instanceof Error) {
const anthropicError = new AnthropicError(error.message);
// @ts-ignore
anthropicError.cause = error;
return this._emit('error', anthropicError);
}
return this._emit('error', new AnthropicError(String(error)));
});
__classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((resolve, reject) => {
__classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise, resolve, "f");
__classPrivateFieldSet(this, _BetaMessageStream_rejectConnectedPromise, reject, "f");
}), "f");
__classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((resolve, reject) => {
__classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise, resolve, "f");
__classPrivateFieldSet(this, _BetaMessageStream_rejectEndPromise, reject, "f");
}), "f");
// 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.
__classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f").catch(() => { });
__classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f").catch(() => { });
__classPrivateFieldSet(this, _BetaMessageStream_params, params, "f");
__classPrivateFieldSet(this, _BetaMessageStream_logger, opts?.logger ?? console, "f");
}
get response() {
return __classPrivateFieldGet(this, _BetaMessageStream_response, "f");
}
get request_id() {
return __classPrivateFieldGet(this, _BetaMessageStream_request_id, "f");
}
/**
* 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() {
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
const response = await __classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f");
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) {
const runner = new BetaMessageStream(null);
runner._run(() => runner._fromReadableStream(stream));
return runner;
}
static createMessage(messages, params, options, { logger } = {}) {
const runner = new BetaMessageStream(params, { logger });
for (const message of params.messages) {
runner._addMessageParam(message);
}
__classPrivateFieldSet(runner, _BetaMessageStream_params, { ...params, stream: true }, "f");
runner._run(() => runner._createMessage(messages, { ...params, stream: true }, { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } }));
return runner;
}
_run(executor) {
executor().then(() => {
this._emitFinal();
this._emit('end');
}, __classPrivateFieldGet(this, _BetaMessageStream_handleError, "f"));
}
_addMessageParam(message) {
this.messages.push(message);
}
_addMessage(message, emit = true) {
this.receivedMessages.push(message);
if (emit) {
this._emit('message', message);
}
}
async _createMessage(messages, params, options) {
const signal = options?.signal;
let abortHandler;
if (signal) {
if (signal.aborted)
this.controller.abort();
abortHandler = this.controller.abort.bind(this.controller);
signal.addEventListener('abort', abortHandler);
}
try {
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_beginRequest).call(this);
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) {
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new APIUserAbortError();
}
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_endRequest).call(this);
}
finally {
if (signal && abortHandler) {
signal.removeEventListener('abort', abortHandler);
}
}
}
_connected(response) {
if (this.ended)
return;
__classPrivateFieldSet(this, _BetaMessageStream_response, response, "f");
__classPrivateFieldSet(this, _BetaMessageStream_request_id, response?.headers.get('request-id'), "f");
__classPrivateFieldGet(this, _BetaMessageStream_resolveConnectedPromise, "f").call(this, response);
this._emit('connect');
}
get ended() {
return __classPrivateFieldGet(this, _BetaMessageStream_ended, "f");
}
get errored() {
return __classPrivateFieldGet(this, _BetaMessageStream_errored, "f");
}
get aborted() {
return __classPrivateFieldGet(this, _BetaMessageStream_aborted, "f");
}
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, listener) {
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[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, listener) {
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[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, listener) {
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[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) {
return new Promise((resolve, reject) => {
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
if (event !== 'error')
this.once('error', reject);
this.once(event, resolve);
});
}
async done() {
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
await __classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f");
}
get currentMessage() {
return __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
}
/**
* @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.
* If structured outputs were used, this will be a ParsedMessage with a `parsed` field.
*/
async finalMessage() {
await this.done();
return __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalMessage).call(this);
}
/**
* @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() {
await this.done();
return __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalText).call(this);
}
_emit(event, ...args) {
// make sure we don't emit any MessageStreamEvents after end
if (__classPrivateFieldGet(this, _BetaMessageStream_ended, "f"))
return;
if (event === 'end') {
__classPrivateFieldSet(this, _BetaMessageStream_ended, true, "f");
__classPrivateFieldGet(this, _BetaMessageStream_resolveEndPromise, "f").call(this);
}
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event];
if (listeners) {
__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
listeners.forEach(({ listener }) => listener(...args));
}
if (event === 'abort') {
const error = args[0];
if (!__classPrivateFieldGet(this, _BetaMessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
Promise.reject(error);
}
__classPrivateFieldGet(this, _BetaMessageStream_rejectConnectedPromise, "f").call(this, error);
__classPrivateFieldGet(this, _BetaMessageStream_rejectEndPromise, "f").call(this, error);
this._emit('end');
return;
}
if (event === 'error') {
// NOTE: _emit('error', error) should only be called from #handleError().
const error = args[0];
if (!__classPrivateFieldGet(this, _BetaMessageStream_catchingPromiseCreated, "f") && !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);
}
__classPrivateFieldGet(this, _BetaMessageStream_rejectConnectedPromise, "f").call(this, error);
__classPrivateFieldGet(this, _BetaMessageStream_rejectEndPromise, "f").call(this, error);
this._emit('end');
}
}
_emitFinal() {
const finalMessage = this.receivedMessages.at(-1);
if (finalMessage) {
this._emit('finalMessage', __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalMessage).call(this));
}
}
async _fromReadableStream(readableStream, options) {
const signal = options?.signal;
let abortHandler;
if (signal) {
if (signal.aborted)
this.controller.abort();
abortHandler = this.controller.abort.bind(this.controller);
signal.addEventListener('abort', abortHandler);
}
try {
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_beginRequest).call(this);
this._connected(null);
const stream = Stream.fromReadableStream(readableStream, this.controller);
for await (const event of stream) {
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new APIUserAbortError();
}
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_endRequest).call(this);
}
finally {
if (signal && abortHandler) {
signal.removeEventListener('abort', abortHandler);
}
}
}
[(_BetaMessageStream_currentMessageSnapshot = new WeakMap(), _BetaMessageStream_params = new WeakMap(), _BetaMessageStream_connectedPromise = new WeakMap(), _BetaMessageStream_resolveConnectedPromise = new WeakMap(), _BetaMessageStream_rejectConnectedPromise = new WeakMap(), _BetaMessageStream_endPromise = new WeakMap(), _BetaMessageStream_resolveEndPromise = new WeakMap(), _BetaMessageStream_rejectEndPromise = new WeakMap(), _BetaMessageStream_listeners = new WeakMap(), _BetaMessageStream_ended = new WeakMap(), _BetaMessageStream_errored = new WeakMap(), _BetaMessageStream_aborted = new WeakMap(), _BetaMessageStream_catchingPromiseCreated = new WeakMap(), _BetaMessageStream_response = new WeakMap(), _BetaMessageStream_request_id = new WeakMap(), _BetaMessageStream_logger = new WeakMap(), _BetaMessageStream_handleError = new WeakMap(), _BetaMessageStream_instances = new WeakSet(), _BetaMessageStream_getFinalMessage = function _BetaMessageStream_getFinalMessage() {
if (this.receivedMessages.length === 0) {
throw new AnthropicError('stream ended without producing a Message with role=assistant');
}
return this.receivedMessages.at(-1);
}, _BetaMessageStream_getFinalText = function _BetaMessageStream_getFinalText() {
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.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(' ');
}, _BetaMessageStream_beginRequest = function _BetaMessageStream_beginRequest() {
if (this.ended)
return;
__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f");
}, _BetaMessageStream_addStreamEvent = function _BetaMessageStream_addStreamEvent(event) {
if (this.ended)
return;
const messageSnapshot = __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_accumulateMessage).call(this, event);
this._emit('streamEvent', event, messageSnapshot);
switch (event.type) {
case 'content_block_delta': {
const content = messageSnapshot.content.at(-1);
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 (tracksToolInput(content) && content.input) {
this._emit('inputJson', event.delta.partial_json, content.input);
}
break;
}
case 'thinking_delta': {
if (content.type === 'thinking') {
this._emit('thinking', event.delta.thinking, content.thinking);
}
break;
}
case 'signature_delta': {
if (content.type === 'thinking') {
this._emit('signature', content.signature);
}
break;
}
case 'compaction_delta': {
if (content.type === 'compaction' && content.content) {
this._emit('compaction', content.content);
}
break;
}
default:
checkNever(event.delta);
}
break;
}
case 'message_stop': {
this._addMessageParam(messageSnapshot);
this._addMessage(maybeParseBetaMessage(messageSnapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _BetaMessageStream_logger, "f") }), true);
break;
}
case 'content_block_stop': {
this._emit('contentBlock', messageSnapshot.content.at(-1));
break;
}
case 'message_start': {
__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, messageSnapshot, "f");
break;
}
case 'content_block_start':
case 'message_delta':
break;
}
}, _BetaMessageStream_endRequest = function _BetaMessageStream_endRequest() {
if (this.ended) {
throw new AnthropicError(`stream has ended, this shouldn't happen`);
}
const snapshot = __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
if (!snapshot) {
throw new AnthropicError(`request ended without sending any chunks`);
}
__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f");
return maybeParseBetaMessage(snapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _BetaMessageStream_logger, "f") });
}, _BetaMessageStream_accumulateMessage = function _BetaMessageStream_accumulateMessage(event) {
let snapshot = __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
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.container = event.delta.container;
snapshot.stop_reason = event.delta.stop_reason;
snapshot.stop_sequence = event.delta.stop_sequence;
snapshot.usage.output_tokens = event.usage.output_tokens;
snapshot.context_management = event.context_management;
if (event.usage.input_tokens != null) {
snapshot.usage.input_tokens = event.usage.input_tokens;
}
if (event.usage.cache_creation_input_tokens != null) {
snapshot.usage.cache_creation_input_tokens = event.usage.cache_creation_input_tokens;
}
if (event.usage.cache_read_input_tokens != null) {
snapshot.usage.cache_read_input_tokens = event.usage.cache_read_input_tokens;
}
if (event.usage.server_tool_use != null) {
snapshot.usage.server_tool_use = event.usage.server_tool_use;
}
if (event.usage.iterations != null) {
snapshot.usage.iterations = event.usage.iterations;
}
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);
switch (event.delta.type) {
case 'text_delta': {
if (snapshotContent?.type === 'text') {
snapshot.content[event.index] = {
...snapshotContent,
text: (snapshotContent.text || '') + event.delta.text,
};
}
break;
}
case 'citations_delta': {
if (snapshotContent?.type === 'text') {
snapshot.content[event.index] = {
...snapshotContent,
citations: [...(snapshotContent.citations ?? []), event.delta.citation],
};
}
break;
}
case 'input_json_delta': {
if (snapshotContent && tracksToolInput(snapshotContent)) {
// 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[JSON_BUF_PROPERTY] || '';
jsonBuf += event.delta.partial_json;
const newContent = { ...snapshotContent };
Object.defineProperty(newContent, JSON_BUF_PROPERTY, {
value: jsonBuf,
enumerable: false,
writable: true,
});
if (jsonBuf) {
try {
newContent.input = partialParse(jsonBuf);
}
catch (err) {
const error = new AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err}. JSON: ${jsonBuf}`);
__classPrivateFieldGet(this, _BetaMessageStream_handleError, "f").call(this, error);
}
}
snapshot.content[event.index] = newContent;
}
break;
}
case 'thinking_delta': {
if (snapshotContent?.type === 'thinking') {
snapshot.content[event.index] = {
...snapshotContent,
thinking: snapshotContent.thinking + event.delta.thinking,
};
}
break;
}
case 'signature_delta': {
if (snapshotContent?.type === 'thinking') {
snapshot.content[event.index] = {
...snapshotContent,
signature: event.delta.signature,
};
}
break;
}
case 'compaction_delta': {
if (snapshotContent?.type === 'compaction') {
snapshot.content[event.index] = {
...snapshotContent,
content: (snapshotContent.content || '') + event.delta.content,
};
}
break;
}
default:
checkNever(event.delta);
}
return snapshot;
}
case 'content_block_stop':
return snapshot;
}
}, Symbol.asyncIterator)]() {
const pushQueue = [];
const readQueue = [];
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 () => {
if (!pushQueue.length) {
if (done) {
return { value: undefined, done: true };
}
return new Promise((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() {
const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
return stream.toReadableStream();
}
}
// used to ensure exhaustive case matching without throwing a runtime error
function checkNever(x) { }
//# sourceMappingURL=BetaMessageStream.mjs.map

View File

@@ -0,0 +1,591 @@
var _MessageStream_instances, _MessageStream_currentMessageSnapshot, _MessageStream_params, _MessageStream_connectedPromise, _MessageStream_resolveConnectedPromise, _MessageStream_rejectConnectedPromise, _MessageStream_endPromise, _MessageStream_resolveEndPromise, _MessageStream_rejectEndPromise, _MessageStream_listeners, _MessageStream_ended, _MessageStream_errored, _MessageStream_aborted, _MessageStream_catchingPromiseCreated, _MessageStream_response, _MessageStream_request_id, _MessageStream_logger, _MessageStream_getFinalMessage, _MessageStream_getFinalText, _MessageStream_handleError, _MessageStream_beginRequest, _MessageStream_addStreamEvent, _MessageStream_endRequest, _MessageStream_accumulateMessage;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
import { isAbortError } from "../internal/errors.mjs";
import { AnthropicError, APIUserAbortError } from "../error.mjs";
import { Stream } from "../streaming.mjs";
import { partialParse } from "../_vendor/partial-json-parser/parser.mjs";
import { maybeParseMessage } from "./parser.mjs";
const JSON_BUF_PROPERTY = '__json_buf';
function tracksToolInput(content) {
return content.type === 'tool_use' || content.type === 'server_tool_use';
}
export class MessageStream {
constructor(params, opts) {
_MessageStream_instances.add(this);
this.messages = [];
this.receivedMessages = [];
_MessageStream_currentMessageSnapshot.set(this, void 0);
_MessageStream_params.set(this, null);
this.controller = new AbortController();
_MessageStream_connectedPromise.set(this, void 0);
_MessageStream_resolveConnectedPromise.set(this, () => { });
_MessageStream_rejectConnectedPromise.set(this, () => { });
_MessageStream_endPromise.set(this, void 0);
_MessageStream_resolveEndPromise.set(this, () => { });
_MessageStream_rejectEndPromise.set(this, () => { });
_MessageStream_listeners.set(this, {});
_MessageStream_ended.set(this, false);
_MessageStream_errored.set(this, false);
_MessageStream_aborted.set(this, false);
_MessageStream_catchingPromiseCreated.set(this, false);
_MessageStream_response.set(this, void 0);
_MessageStream_request_id.set(this, void 0);
_MessageStream_logger.set(this, void 0);
_MessageStream_handleError.set(this, (error) => {
__classPrivateFieldSet(this, _MessageStream_errored, true, "f");
if (isAbortError(error)) {
error = new APIUserAbortError();
}
if (error instanceof APIUserAbortError) {
__classPrivateFieldSet(this, _MessageStream_aborted, true, "f");
return this._emit('abort', error);
}
if (error instanceof AnthropicError) {
return this._emit('error', error);
}
if (error instanceof Error) {
const anthropicError = new AnthropicError(error.message);
// @ts-ignore
anthropicError.cause = error;
return this._emit('error', anthropicError);
}
return this._emit('error', new AnthropicError(String(error)));
});
__classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((resolve, reject) => {
__classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise, resolve, "f");
__classPrivateFieldSet(this, _MessageStream_rejectConnectedPromise, reject, "f");
}), "f");
__classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((resolve, reject) => {
__classPrivateFieldSet(this, _MessageStream_resolveEndPromise, resolve, "f");
__classPrivateFieldSet(this, _MessageStream_rejectEndPromise, reject, "f");
}), "f");
// 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.
__classPrivateFieldGet(this, _MessageStream_connectedPromise, "f").catch(() => { });
__classPrivateFieldGet(this, _MessageStream_endPromise, "f").catch(() => { });
__classPrivateFieldSet(this, _MessageStream_params, params, "f");
__classPrivateFieldSet(this, _MessageStream_logger, opts?.logger ?? console, "f");
}
get response() {
return __classPrivateFieldGet(this, _MessageStream_response, "f");
}
get request_id() {
return __classPrivateFieldGet(this, _MessageStream_request_id, "f");
}
/**
* 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() {
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
const response = await __classPrivateFieldGet(this, _MessageStream_connectedPromise, "f");
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) {
const runner = new MessageStream(null);
runner._run(() => runner._fromReadableStream(stream));
return runner;
}
static createMessage(messages, params, options, { logger } = {}) {
const runner = new MessageStream(params, { logger });
for (const message of params.messages) {
runner._addMessageParam(message);
}
__classPrivateFieldSet(runner, _MessageStream_params, { ...params, stream: true }, "f");
runner._run(() => runner._createMessage(messages, { ...params, stream: true }, { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } }));
return runner;
}
_run(executor) {
executor().then(() => {
this._emitFinal();
this._emit('end');
}, __classPrivateFieldGet(this, _MessageStream_handleError, "f"));
}
_addMessageParam(message) {
this.messages.push(message);
}
_addMessage(message, emit = true) {
this.receivedMessages.push(message);
if (emit) {
this._emit('message', message);
}
}
async _createMessage(messages, params, options) {
const signal = options?.signal;
let abortHandler;
if (signal) {
if (signal.aborted)
this.controller.abort();
abortHandler = this.controller.abort.bind(this.controller);
signal.addEventListener('abort', abortHandler);
}
try {
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_beginRequest).call(this);
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) {
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new APIUserAbortError();
}
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_endRequest).call(this);
}
finally {
if (signal && abortHandler) {
signal.removeEventListener('abort', abortHandler);
}
}
}
_connected(response) {
if (this.ended)
return;
__classPrivateFieldSet(this, _MessageStream_response, response, "f");
__classPrivateFieldSet(this, _MessageStream_request_id, response?.headers.get('request-id'), "f");
__classPrivateFieldGet(this, _MessageStream_resolveConnectedPromise, "f").call(this, response);
this._emit('connect');
}
get ended() {
return __classPrivateFieldGet(this, _MessageStream_ended, "f");
}
get errored() {
return __classPrivateFieldGet(this, _MessageStream_errored, "f");
}
get aborted() {
return __classPrivateFieldGet(this, _MessageStream_aborted, "f");
}
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, listener) {
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _MessageStream_listeners, "f")[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, listener) {
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[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, listener) {
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _MessageStream_listeners, "f")[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) {
return new Promise((resolve, reject) => {
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
if (event !== 'error')
this.once('error', reject);
this.once(event, resolve);
});
}
async done() {
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
await __classPrivateFieldGet(this, _MessageStream_endPromise, "f");
}
get currentMessage() {
return __classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
}
/**
* @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.
* If structured outputs were used, this will be a ParsedMessage with a `parsed_output` field.
*/
async finalMessage() {
await this.done();
return __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalMessage).call(this);
}
/**
* @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() {
await this.done();
return __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalText).call(this);
}
_emit(event, ...args) {
// make sure we don't emit any MessageStreamEvents after end
if (__classPrivateFieldGet(this, _MessageStream_ended, "f"))
return;
if (event === 'end') {
__classPrivateFieldSet(this, _MessageStream_ended, true, "f");
__classPrivateFieldGet(this, _MessageStream_resolveEndPromise, "f").call(this);
}
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event];
if (listeners) {
__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
listeners.forEach(({ listener }) => listener(...args));
}
if (event === 'abort') {
const error = args[0];
if (!__classPrivateFieldGet(this, _MessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
Promise.reject(error);
}
__classPrivateFieldGet(this, _MessageStream_rejectConnectedPromise, "f").call(this, error);
__classPrivateFieldGet(this, _MessageStream_rejectEndPromise, "f").call(this, error);
this._emit('end');
return;
}
if (event === 'error') {
// NOTE: _emit('error', error) should only be called from #handleError().
const error = args[0];
if (!__classPrivateFieldGet(this, _MessageStream_catchingPromiseCreated, "f") && !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);
}
__classPrivateFieldGet(this, _MessageStream_rejectConnectedPromise, "f").call(this, error);
__classPrivateFieldGet(this, _MessageStream_rejectEndPromise, "f").call(this, error);
this._emit('end');
}
}
_emitFinal() {
const finalMessage = this.receivedMessages.at(-1);
if (finalMessage) {
this._emit('finalMessage', __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalMessage).call(this));
}
}
async _fromReadableStream(readableStream, options) {
const signal = options?.signal;
let abortHandler;
if (signal) {
if (signal.aborted)
this.controller.abort();
abortHandler = this.controller.abort.bind(this.controller);
signal.addEventListener('abort', abortHandler);
}
try {
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_beginRequest).call(this);
this._connected(null);
const stream = Stream.fromReadableStream(readableStream, this.controller);
for await (const event of stream) {
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new APIUserAbortError();
}
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_endRequest).call(this);
}
finally {
if (signal && abortHandler) {
signal.removeEventListener('abort', abortHandler);
}
}
}
[(_MessageStream_currentMessageSnapshot = new WeakMap(), _MessageStream_params = new WeakMap(), _MessageStream_connectedPromise = new WeakMap(), _MessageStream_resolveConnectedPromise = new WeakMap(), _MessageStream_rejectConnectedPromise = new WeakMap(), _MessageStream_endPromise = new WeakMap(), _MessageStream_resolveEndPromise = new WeakMap(), _MessageStream_rejectEndPromise = new WeakMap(), _MessageStream_listeners = new WeakMap(), _MessageStream_ended = new WeakMap(), _MessageStream_errored = new WeakMap(), _MessageStream_aborted = new WeakMap(), _MessageStream_catchingPromiseCreated = new WeakMap(), _MessageStream_response = new WeakMap(), _MessageStream_request_id = new WeakMap(), _MessageStream_logger = new WeakMap(), _MessageStream_handleError = new WeakMap(), _MessageStream_instances = new WeakSet(), _MessageStream_getFinalMessage = function _MessageStream_getFinalMessage() {
if (this.receivedMessages.length === 0) {
throw new AnthropicError('stream ended without producing a Message with role=assistant');
}
return this.receivedMessages.at(-1);
}, _MessageStream_getFinalText = function _MessageStream_getFinalText() {
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.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(' ');
}, _MessageStream_beginRequest = function _MessageStream_beginRequest() {
if (this.ended)
return;
__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, undefined, "f");
}, _MessageStream_addStreamEvent = function _MessageStream_addStreamEvent(event) {
if (this.ended)
return;
const messageSnapshot = __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_accumulateMessage).call(this, event);
this._emit('streamEvent', event, messageSnapshot);
switch (event.type) {
case 'content_block_delta': {
const content = messageSnapshot.content.at(-1);
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 (tracksToolInput(content) && content.input) {
this._emit('inputJson', event.delta.partial_json, content.input);
}
break;
}
case 'thinking_delta': {
if (content.type === 'thinking') {
this._emit('thinking', event.delta.thinking, content.thinking);
}
break;
}
case 'signature_delta': {
if (content.type === 'thinking') {
this._emit('signature', content.signature);
}
break;
}
default:
checkNever(event.delta);
}
break;
}
case 'message_stop': {
this._addMessageParam(messageSnapshot);
this._addMessage(maybeParseMessage(messageSnapshot, __classPrivateFieldGet(this, _MessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _MessageStream_logger, "f") }), true);
break;
}
case 'content_block_stop': {
this._emit('contentBlock', messageSnapshot.content.at(-1));
break;
}
case 'message_start': {
__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, messageSnapshot, "f");
break;
}
case 'content_block_start':
case 'message_delta':
break;
}
}, _MessageStream_endRequest = function _MessageStream_endRequest() {
if (this.ended) {
throw new AnthropicError(`stream has ended, this shouldn't happen`);
}
const snapshot = __classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
if (!snapshot) {
throw new AnthropicError(`request ended without sending any chunks`);
}
__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, undefined, "f");
return maybeParseMessage(snapshot, __classPrivateFieldGet(this, _MessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _MessageStream_logger, "f") });
}, _MessageStream_accumulateMessage = function _MessageStream_accumulateMessage(event) {
let snapshot = __classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
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;
// Update other usage fields if they exist in the event
if (event.usage.input_tokens != null) {
snapshot.usage.input_tokens = event.usage.input_tokens;
}
if (event.usage.cache_creation_input_tokens != null) {
snapshot.usage.cache_creation_input_tokens = event.usage.cache_creation_input_tokens;
}
if (event.usage.cache_read_input_tokens != null) {
snapshot.usage.cache_read_input_tokens = event.usage.cache_read_input_tokens;
}
if (event.usage.server_tool_use != null) {
snapshot.usage.server_tool_use = event.usage.server_tool_use;
}
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);
switch (event.delta.type) {
case 'text_delta': {
if (snapshotContent?.type === 'text') {
snapshot.content[event.index] = {
...snapshotContent,
text: (snapshotContent.text || '') + event.delta.text,
};
}
break;
}
case 'citations_delta': {
if (snapshotContent?.type === 'text') {
snapshot.content[event.index] = {
...snapshotContent,
citations: [...(snapshotContent.citations ?? []), event.delta.citation],
};
}
break;
}
case 'input_json_delta': {
if (snapshotContent && tracksToolInput(snapshotContent)) {
// 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[JSON_BUF_PROPERTY] || '';
jsonBuf += event.delta.partial_json;
const newContent = { ...snapshotContent };
Object.defineProperty(newContent, JSON_BUF_PROPERTY, {
value: jsonBuf,
enumerable: false,
writable: true,
});
if (jsonBuf) {
newContent.input = partialParse(jsonBuf);
}
snapshot.content[event.index] = newContent;
}
break;
}
case 'thinking_delta': {
if (snapshotContent?.type === 'thinking') {
snapshot.content[event.index] = {
...snapshotContent,
thinking: snapshotContent.thinking + event.delta.thinking,
};
}
break;
}
case 'signature_delta': {
if (snapshotContent?.type === 'thinking') {
snapshot.content[event.index] = {
...snapshotContent,
signature: event.delta.signature,
};
}
break;
}
default:
checkNever(event.delta);
}
return snapshot;
}
case 'content_block_stop':
return snapshot;
}
}, Symbol.asyncIterator)]() {
const pushQueue = [];
const readQueue = [];
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 () => {
if (!pushQueue.length) {
if (done) {
return { value: undefined, done: true };
}
return new Promise((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() {
const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
return stream.toReadableStream();
}
}
// used to ensure exhaustive case matching without throwing a runtime error
function checkNever(x) { }
//# sourceMappingURL=MessageStream.mjs.map

View File

@@ -0,0 +1,75 @@
import { AnthropicError } from "../core/error.mjs";
function getOutputFormat(params) {
// Prefer output_format (deprecated) over output_config.format for backward compatibility
return params?.output_format ?? params?.output_config?.format;
}
export function maybeParseBetaMessage(message, params, opts) {
const outputFormat = getOutputFormat(params);
if (!params || !('parse' in (outputFormat ?? {}))) {
return {
...message,
content: message.content.map((block) => {
if (block.type === 'text') {
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
value: null,
enumerable: false,
});
return Object.defineProperty(parsedBlock, 'parsed', {
get() {
opts.logger.warn('The `parsed` property on `text` blocks is deprecated, please use `parsed_output` instead.');
return null;
},
enumerable: false,
});
}
return block;
}),
parsed_output: null,
};
}
return parseBetaMessage(message, params, opts);
}
export function parseBetaMessage(message, params, opts) {
let firstParsedOutput = null;
const content = message.content.map((block) => {
if (block.type === 'text') {
const parsedOutput = parseBetaOutputFormat(params, block.text);
if (firstParsedOutput === null) {
firstParsedOutput = parsedOutput;
}
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
value: parsedOutput,
enumerable: false,
});
return Object.defineProperty(parsedBlock, 'parsed', {
get() {
opts.logger.warn('The `parsed` property on `text` blocks is deprecated, please use `parsed_output` instead.');
return parsedOutput;
},
enumerable: false,
});
}
return block;
});
return {
...message,
content,
parsed_output: firstParsedOutput,
};
}
function parseBetaOutputFormat(params, content) {
const outputFormat = getOutputFormat(params);
if (outputFormat?.type !== 'json_schema') {
return null;
}
try {
if ('parse' in outputFormat) {
return outputFormat.parse(content);
}
return JSON.parse(content);
}
catch (error) {
throw new AnthropicError(`Failed to parse structured output: ${error}`);
}
}
//# sourceMappingURL=beta-parser.mjs.map

View File

@@ -0,0 +1,62 @@
import { AnthropicError } from "../core/error.mjs";
function getOutputFormat(params) {
return params?.output_config?.format;
}
export function maybeParseMessage(message, params, opts) {
const outputFormat = getOutputFormat(params);
if (!params || !('parse' in (outputFormat ?? {}))) {
return {
...message,
content: message.content.map((block) => {
if (block.type === 'text') {
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
value: null,
enumerable: false,
});
return parsedBlock;
}
return block;
}),
parsed_output: null,
};
}
return parseMessage(message, params, opts);
}
export function parseMessage(message, params, opts) {
let firstParsedOutput = null;
const content = message.content.map((block) => {
if (block.type === 'text') {
const parsedOutput = parseOutputFormat(params, block.text);
if (firstParsedOutput === null) {
firstParsedOutput = parsedOutput;
}
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
value: parsedOutput,
enumerable: false,
});
return parsedBlock;
}
return block;
});
return {
...message,
content,
parsed_output: firstParsedOutput,
};
}
function parseOutputFormat(params, content) {
const outputFormat = getOutputFormat(params);
if (outputFormat?.type !== 'json_schema') {
return null;
}
try {
if ('parse' in outputFormat) {
return outputFormat.parse(content);
}
return JSON.parse(content);
}
catch (error) {
throw new AnthropicError(`Failed to parse structured output: ${error}`);
}
}
//# sourceMappingURL=parser.mjs.map

View File

@@ -0,0 +1,63 @@
/**
* Shared utilities for tracking SDK helper usage.
*/
/**
* Symbol used to mark objects created by SDK helpers for tracking.
* The value is the helper name (e.g., 'mcpTool', 'betaZodTool').
*/
export const SDK_HELPER_SYMBOL = Symbol('anthropic.sdk.stainlessHelper');
export function wasCreatedByStainlessHelper(value) {
return typeof value === 'object' && value !== null && SDK_HELPER_SYMBOL in value;
}
/**
* Collects helper names from tools and messages arrays.
* Returns a deduplicated array of helper names found.
*/
export function collectStainlessHelpers(tools, messages) {
const helpers = new Set();
// Collect from tools
if (tools) {
for (const tool of tools) {
if (wasCreatedByStainlessHelper(tool)) {
helpers.add(tool[SDK_HELPER_SYMBOL]);
}
}
}
// Collect from messages and their content blocks
if (messages) {
for (const message of messages) {
if (wasCreatedByStainlessHelper(message)) {
helpers.add(message[SDK_HELPER_SYMBOL]);
}
if (Array.isArray(message.content)) {
for (const block of message.content) {
if (wasCreatedByStainlessHelper(block)) {
helpers.add(block[SDK_HELPER_SYMBOL]);
}
}
}
}
}
return Array.from(helpers);
}
/**
* Builds x-stainless-helper header value from tools and messages.
* Returns an empty object if no helpers are found.
*/
export function stainlessHelperHeader(tools, messages) {
const helpers = collectStainlessHelpers(tools, messages);
if (helpers.length === 0)
return {};
return { 'x-stainless-helper': helpers.join(', ') };
}
/**
* Builds x-stainless-helper header value from a file object.
* Returns an empty object if the file is not marked with a helper.
*/
export function stainlessHelperHeaderFromFile(file) {
if (wasCreatedByStainlessHelper(file)) {
return { 'x-stainless-helper': file[SDK_HELPER_SYMBOL] };
}
return {};
}
//# sourceMappingURL=stainless-helper-header.mjs.map

View File

@@ -0,0 +1,372 @@
var _BetaToolRunner_instances, _BetaToolRunner_consumed, _BetaToolRunner_mutated, _BetaToolRunner_state, _BetaToolRunner_options, _BetaToolRunner_message, _BetaToolRunner_toolResponse, _BetaToolRunner_completion, _BetaToolRunner_iterationCount, _BetaToolRunner_checkAndCompact, _BetaToolRunner_generateToolResponse;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../../internal/tslib.mjs";
import { ToolError } from "./ToolError.mjs";
import { AnthropicError } from "../../core/error.mjs";
import { buildHeaders } from "../../internal/headers.mjs";
import { DEFAULT_SUMMARY_PROMPT, DEFAULT_TOKEN_THRESHOLD } from "./CompactionControl.mjs";
import { collectStainlessHelpers } from "../stainless-helper-header.mjs";
/**
* Just Promise.withResolvers(), which is not available in all environments.
*/
function promiseWithResolvers() {
let resolve;
let reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve: resolve, reject: reject };
}
/**
* A ToolRunner handles the automatic conversation loop between the assistant and tools.
*
* A ToolRunner is an async iterable that yields either BetaMessage or BetaMessageStream objects
* depending on the streaming configuration.
*/
export class BetaToolRunner {
constructor(client, params, options) {
_BetaToolRunner_instances.add(this);
this.client = client;
/** Whether the async iterator has been consumed */
_BetaToolRunner_consumed.set(this, false);
/** Whether parameters have been mutated since the last API call */
_BetaToolRunner_mutated.set(this, false);
/** Current state containing the request parameters */
_BetaToolRunner_state.set(this, void 0);
_BetaToolRunner_options.set(this, void 0);
/** Promise for the last message received from the assistant */
_BetaToolRunner_message.set(this, void 0);
/** Cached tool response to avoid redundant executions */
_BetaToolRunner_toolResponse.set(this, void 0);
/** Promise resolvers for waiting on completion */
_BetaToolRunner_completion.set(this, void 0);
/** Number of iterations (API requests) made so far */
_BetaToolRunner_iterationCount.set(this, 0);
__classPrivateFieldSet(this, _BetaToolRunner_state, {
params: {
// You can't clone the entire params since there are functions as handlers.
// You also don't really need to clone params.messages, but it probably will prevent a foot gun
// somewhere.
...params,
messages: structuredClone(params.messages),
},
}, "f");
const helpers = collectStainlessHelpers(params.tools, params.messages);
const helperValue = ['BetaToolRunner', ...helpers].join(', ');
__classPrivateFieldSet(this, _BetaToolRunner_options, {
...options,
headers: buildHeaders([{ 'x-stainless-helper': helperValue }, options?.headers]),
}, "f");
__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
}
async *[(_BetaToolRunner_consumed = new WeakMap(), _BetaToolRunner_mutated = new WeakMap(), _BetaToolRunner_state = new WeakMap(), _BetaToolRunner_options = new WeakMap(), _BetaToolRunner_message = new WeakMap(), _BetaToolRunner_toolResponse = new WeakMap(), _BetaToolRunner_completion = new WeakMap(), _BetaToolRunner_iterationCount = new WeakMap(), _BetaToolRunner_instances = new WeakSet(), _BetaToolRunner_checkAndCompact = async function _BetaToolRunner_checkAndCompact() {
const compactionControl = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.compactionControl;
if (!compactionControl || !compactionControl.enabled) {
return false;
}
let tokensUsed = 0;
if (__classPrivateFieldGet(this, _BetaToolRunner_message, "f") !== undefined) {
try {
const message = await __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
const totalInputTokens = message.usage.input_tokens +
(message.usage.cache_creation_input_tokens ?? 0) +
(message.usage.cache_read_input_tokens ?? 0);
tokensUsed = totalInputTokens + message.usage.output_tokens;
}
catch {
// If we can't get the message, skip compaction
return false;
}
}
const threshold = compactionControl.contextTokenThreshold ?? DEFAULT_TOKEN_THRESHOLD;
if (tokensUsed < threshold) {
return false;
}
const model = compactionControl.model ?? __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.model;
const summaryPrompt = compactionControl.summaryPrompt ?? DEFAULT_SUMMARY_PROMPT;
const messages = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages;
if (messages[messages.length - 1].role === 'assistant') {
// Remove tool_use blocks from the last message to avoid 400 error
// (tool_use requires tool_result, which we don't have yet)
const lastMessage = messages[messages.length - 1];
if (Array.isArray(lastMessage.content)) {
const nonToolBlocks = lastMessage.content.filter((block) => block.type !== 'tool_use');
if (nonToolBlocks.length === 0) {
// If all blocks were tool_use, just remove the message entirely
messages.pop();
}
else {
lastMessage.content = nonToolBlocks;
}
}
}
const response = await this.client.beta.messages.create({
model,
messages: [
...messages,
{
role: 'user',
content: [
{
type: 'text',
text: summaryPrompt,
},
],
},
],
max_tokens: __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_tokens,
}, {
headers: { 'x-stainless-helper': 'compaction' },
});
if (response.content[0]?.type !== 'text') {
throw new AnthropicError('Expected text response for compaction');
}
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages = [
{
role: 'user',
content: response.content,
},
];
return true;
}, Symbol.asyncIterator)]() {
var _a;
if (__classPrivateFieldGet(this, _BetaToolRunner_consumed, "f")) {
throw new AnthropicError('Cannot iterate over a consumed stream');
}
__classPrivateFieldSet(this, _BetaToolRunner_consumed, true, "f");
__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
try {
while (true) {
let stream;
try {
if (__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations &&
__classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f") >= __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations) {
break;
}
__classPrivateFieldSet(this, _BetaToolRunner_mutated, false, "f");
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
__classPrivateFieldSet(this, _BetaToolRunner_iterationCount, (_a = __classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f"), _a++, _a), "f");
__classPrivateFieldSet(this, _BetaToolRunner_message, undefined, "f");
const { max_iterations, compactionControl, ...params } = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
if (params.stream) {
stream = this.client.beta.messages.stream({ ...params }, __classPrivateFieldGet(this, _BetaToolRunner_options, "f"));
__classPrivateFieldSet(this, _BetaToolRunner_message, stream.finalMessage(), "f");
// Make sure that this promise doesn't throw before we get the option to do something about it.
// Error will be caught when we call await this.#message ultimately
__classPrivateFieldGet(this, _BetaToolRunner_message, "f").catch(() => { });
yield stream;
}
else {
__classPrivateFieldSet(this, _BetaToolRunner_message, this.client.beta.messages.create({ ...params, stream: false }, __classPrivateFieldGet(this, _BetaToolRunner_options, "f")), "f");
yield __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
}
const isCompacted = await __classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_checkAndCompact).call(this);
if (!isCompacted) {
if (!__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
const { role, content } = await __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push({ role, content });
}
const toolMessage = await __classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_generateToolResponse).call(this, __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.at(-1));
if (toolMessage) {
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push(toolMessage);
}
else if (!__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
break;
}
}
}
finally {
if (stream) {
stream.abort();
}
}
}
if (!__classPrivateFieldGet(this, _BetaToolRunner_message, "f")) {
throw new AnthropicError('ToolRunner concluded without a message from the server');
}
__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").resolve(await __classPrivateFieldGet(this, _BetaToolRunner_message, "f"));
}
catch (error) {
__classPrivateFieldSet(this, _BetaToolRunner_consumed, false, "f");
// Silence unhandled promise errors
__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").promise.catch(() => { });
__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").reject(error);
__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
throw error;
}
}
setMessagesParams(paramsOrMutator) {
if (typeof paramsOrMutator === 'function') {
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator(__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params);
}
else {
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator;
}
__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
// Invalidate cached tool response since parameters changed
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
}
/**
* Get the tool response for the last message from the assistant.
* Avoids redundant tool executions by caching results.
*
* @returns A promise that resolves to a BetaMessageParam containing tool results, or null if no tools need to be executed
*
* @example
* const toolResponse = await runner.generateToolResponse();
* if (toolResponse) {
* console.log('Tool results:', toolResponse.content);
* }
*/
async generateToolResponse() {
const message = (await __classPrivateFieldGet(this, _BetaToolRunner_message, "f")) ?? this.params.messages.at(-1);
if (!message) {
return null;
}
return __classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_generateToolResponse).call(this, message);
}
/**
* Wait for the async iterator to complete. This works even if the async iterator hasn't yet started, and
* will wait for an instance to start and go to completion.
*
* @returns A promise that resolves to the final BetaMessage when the iterator completes
*
* @example
* // Start consuming the iterator
* for await (const message of runner) {
* console.log('Message:', message.content);
* }
*
* // Meanwhile, wait for completion from another part of the code
* const finalMessage = await runner.done();
* console.log('Final response:', finalMessage.content);
*/
done() {
return __classPrivateFieldGet(this, _BetaToolRunner_completion, "f").promise;
}
/**
* Returns a promise indicating that the stream is done. Unlike .done(), this will eagerly read the stream:
* * If the iterator has not been consumed, consume the entire iterator and return the final message from the
* assistant.
* * If the iterator has been consumed, waits for it to complete and returns the final message.
*
* @returns A promise that resolves to the final BetaMessage from the conversation
* @throws {AnthropicError} If no messages were processed during the conversation
*
* @example
* const finalMessage = await runner.runUntilDone();
* console.log('Final response:', finalMessage.content);
*/
async runUntilDone() {
// If not yet consumed, start consuming and wait for completion
if (!__classPrivateFieldGet(this, _BetaToolRunner_consumed, "f")) {
for await (const _ of this) {
// Iterator naturally populates this.#message
}
}
// If consumed but not completed, wait for completion
return this.done();
}
/**
* Get the current parameters being used by the ToolRunner.
*
* @returns A readonly view of the current ToolRunnerParams
*
* @example
* const currentParams = runner.params;
* console.log('Current model:', currentParams.model);
* console.log('Message count:', currentParams.messages.length);
*/
get params() {
return __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
}
/**
* Add one or more messages to the conversation history.
*
* @param messages - One or more BetaMessageParam objects to add to the conversation
*
* @example
* runner.pushMessages(
* { role: 'user', content: 'Also, what about the weather in NYC?' }
* );
*
* @example
* // Adding multiple messages
* runner.pushMessages(
* { role: 'user', content: 'What about NYC?' },
* { role: 'user', content: 'And Boston?' }
* );
*/
pushMessages(...messages) {
this.setMessagesParams((params) => ({
...params,
messages: [...params.messages, ...messages],
}));
}
/**
* Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone()
* This allows using `await runner` instead of `await runner.runUntilDone()`
*/
then(onfulfilled, onrejected) {
return this.runUntilDone().then(onfulfilled, onrejected);
}
}
_BetaToolRunner_generateToolResponse = async function _BetaToolRunner_generateToolResponse(lastMessage) {
if (__classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f") !== undefined) {
return __classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f");
}
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, generateToolResponse(__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params, lastMessage), "f");
return __classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f");
};
async function generateToolResponse(params, lastMessage = params.messages.at(-1)) {
// Only process if the last message is from the assistant and has tool use blocks
if (!lastMessage ||
lastMessage.role !== 'assistant' ||
!lastMessage.content ||
typeof lastMessage.content === 'string') {
return null;
}
const toolUseBlocks = lastMessage.content.filter((content) => content.type === 'tool_use');
if (toolUseBlocks.length === 0) {
return null;
}
const toolResults = await Promise.all(toolUseBlocks.map(async (toolUse) => {
const tool = params.tools.find((t) => ('name' in t ? t.name : t.mcp_server_name) === toolUse.name);
if (!tool || !('run' in tool)) {
return {
type: 'tool_result',
tool_use_id: toolUse.id,
content: `Error: Tool '${toolUse.name}' not found`,
is_error: true,
};
}
try {
let input = toolUse.input;
if ('parse' in tool && tool.parse) {
input = tool.parse(input);
}
const result = await tool.run(input);
return {
type: 'tool_result',
tool_use_id: toolUse.id,
content: result,
};
}
catch (error) {
return {
type: 'tool_result',
tool_use_id: toolUse.id,
content: error instanceof ToolError ?
error.content
: `Error: ${error instanceof Error ? error.message : String(error)}`,
is_error: true,
};
}
}));
return {
role: 'user',
content: toolResults,
};
}
//# sourceMappingURL=BetaToolRunner.mjs.map

View File

@@ -0,0 +1,25 @@
export const DEFAULT_TOKEN_THRESHOLD = 100000;
export const DEFAULT_SUMMARY_PROMPT = `You have been working on the task described above but have not yet completed it. Write a continuation summary that will allow you (or another instance of yourself) to resume work efficiently in a future context window where the conversation history will be replaced with this summary. Your summary should be structured, concise, and actionable. Include:
1. Task Overview
The user's core request and success criteria
Any clarifications or constraints they specified
2. Current State
What has been completed so far
Files created, modified, or analyzed (with paths if relevant)
Key outputs or artifacts produced
3. Important Discoveries
Technical constraints or requirements uncovered
Decisions made and their rationale
Errors encountered and how they were resolved
What approaches were tried that didn't work (and why)
4. Next Steps
Specific actions needed to complete the task
Any blockers or open questions to resolve
Priority order if multiple steps remain
5. Context to Preserve
User preferences or style requirements
Domain-specific details that aren't obvious
Any promises made to the user
Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes. Write in a way that enables immediate resumption of the task.
Wrap your summary in <summary></summary> tags.`;
//# sourceMappingURL=CompactionControl.mjs.map

View File

@@ -0,0 +1,38 @@
/**
* An error that can be thrown from a tool's `run` method to return structured
* content blocks as the error result, rather than just a string message.
*
* When the ToolRunner catches this error, it will use the `content` property
* as the tool result with `is_error: true`.
*
* @example
* ```ts
* const tool = {
* name: 'my_tool',
* run: async (input) => {
* if (somethingWentWrong) {
* throw new ToolError([
* { type: 'text', text: 'Error details here' },
* { type: 'image', source: { type: 'base64', data: '...', media_type: 'image/png' } },
* ]);
* }
* return 'success';
* },
* };
* ```
*/
export class ToolError extends Error {
constructor(content) {
const message = typeof content === 'string' ? content : (content
.map((block) => {
if (block.type === 'text')
return block.text;
return `[${block.type}]`;
})
.join(' '));
super(message);
this.name = 'ToolError';
this.content = content;
}
}
//# sourceMappingURL=ToolError.mjs.map