feat: Complete zCode CLI X with Telegram bot integration

- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation

🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
This commit is contained in:
admin
2026-05-05 09:01:26 +00:00
Unverified
parent 4a7035dd92
commit 875c7f9b91
24688 changed files with 3224957 additions and 221 deletions

View File

@@ -0,0 +1,122 @@
import type { Logger } from "../client.mjs";
import { AnthropicError, APIUserAbortError } from "../error.mjs";
import { type RequestOptions } from "../internal/request-options.mjs";
import { type BetaContentBlock, type BetaMCPToolUseBlock, type BetaMessage, type BetaMessageParam, Messages as BetaMessages, type BetaRawMessageStreamEvent as BetaMessageStreamEvent, type BetaServerToolUseBlock, type BetaTextCitation, type BetaToolUseBlock, type MessageCreateParams, type MessageCreateParamsBase } from "../resources/beta/messages/messages.mjs";
import { type ParsedBetaMessage } from "./beta-parser.mjs";
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;
thinking: (thinkingDelta: string, thinkingSnapshot: string) => void;
signature: (signature: string) => void;
compaction: (compactedContent: string) => void;
message: (message: BetaMessage) => void;
contentBlock: (content: BetaContentBlock) => void;
finalMessage: (message: BetaMessage) => void;
error: (error: AnthropicError) => void;
abort: (error: APIUserAbortError) => void;
end: () => void;
}
export type TracksToolInput = BetaToolUseBlock | BetaServerToolUseBlock | BetaMCPToolUseBlock;
export declare class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMessageStreamEvent> {
#private;
messages: BetaMessageParam[];
receivedMessages: ParsedBetaMessage<ParsedT>[];
controller: AbortController;
constructor(params: MessageCreateParamsBase | null, opts?: {
logger?: Logger | undefined;
});
get response(): Response | null | undefined;
get request_id(): string | null | undefined;
/**
* 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.
*/
withResponse(): Promise<{
data: BetaMessageStream<ParsedT>;
response: Response;
request_id: string | null | undefined;
}>;
/**
* 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;
static createMessage<ParsedT>(messages: BetaMessages, params: MessageCreateParamsBase, options?: RequestOptions, { logger }?: {
logger?: Logger | undefined;
}): BetaMessageStream<ParsedT>;
protected _run(executor: () => Promise<any>): void;
protected _addMessageParam(message: BetaMessageParam): void;
protected _addMessage(message: ParsedBetaMessage<ParsedT>, emit?: boolean): void;
protected _createMessage(messages: BetaMessages, params: MessageCreateParams, options?: RequestOptions): Promise<void>;
protected _connected(response: Response | null): void;
get ended(): boolean;
get errored(): boolean;
get aborted(): boolean;
abort(): void;
/**
* 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 extends keyof MessageStreamEvents>(event: Event, listener: MessageStreamEvents[Event]): 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 extends keyof MessageStreamEvents>(event: Event, listener: MessageStreamEvents[Event]): 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 extends keyof MessageStreamEvents>(event: Event, listener: MessageStreamEvents[Event]): 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 extends keyof MessageStreamEvents>(event: Event): Promise<Parameters<MessageStreamEvents[Event]> extends [infer Param] ? Param : Parameters<MessageStreamEvents[Event]> extends [] ? void : Parameters<MessageStreamEvents[Event]>>;
done(): Promise<void>;
get currentMessage(): BetaMessage | undefined;
/**
* @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.
*/
finalMessage(): Promise<ParsedBetaMessage<ParsedT>>;
/**
* @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.
*/
finalText(): Promise<string>;
protected _emit<Event extends keyof MessageStreamEvents>(event: Event, ...args: Parameters<MessageStreamEvents[Event]>): void;
protected _emitFinal(): void;
protected _fromReadableStream(readableStream: ReadableStream, options?: RequestOptions): Promise<void>;
[Symbol.asyncIterator](): AsyncIterator<BetaMessageStreamEvent>;
toReadableStream(): ReadableStream;
}
//# sourceMappingURL=BetaMessageStream.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaMessageStream.d.mts","sourceRoot":"","sources":["../src/lib/BetaMessageStream.ts"],"names":[],"mappings":"OACO,KAAK,EAAE,MAAM,EAAE;OACf,EAAE,cAAc,EAAE,iBAAiB,EAAE;OAErC,EAAE,KAAK,cAAc,EAAE;OACvB,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,QAAQ,IAAI,YAAY,EACxB,KAAK,yBAAyB,IAAI,sBAAsB,EACxD,KAAK,sBAAsB,EAE3B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAE7B;OAEM,EAAyB,KAAK,iBAAiB,EAAE;AAExD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,CAAC,KAAK,EAAE,sBAAsB,EAAE,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5E,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,QAAQ,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACtF,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;IAChE,QAAQ,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,UAAU,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,KAAK,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC1C,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AASD,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;AAM9F,qBAAa,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAE,YAAW,aAAa,CAAC,sBAAsB,CAAC;;IAC7F,QAAQ,EAAE,gBAAgB,EAAE,CAAM;IAClC,gBAAgB,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAM;IAIpD,UAAU,EAAE,eAAe,CAAyB;gBAoBxC,MAAM,EAAE,uBAAuB,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;IAsB1F,IAAI,QAAQ,IAAI,QAAQ,GAAG,IAAI,GAAG,SAAS,CAE1C;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,IAAI,GAAG,SAAS,CAE1C;IAED;;;;;;;;;OASG;IACG,YAAY,IAAI,OAAO,CAAC;QAC5B,IAAI,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACjC,QAAQ,EAAE,QAAQ,CAAC;QACnB,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;KACvC,CAAC;IAeF;;;;;;OAMG;IACH,MAAM,CAAC,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,iBAAiB;IAMpE,MAAM,CAAC,aAAa,CAAC,OAAO,EAC1B,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,uBAAuB,EAC/B,OAAO,CAAC,EAAE,cAAc,EACxB,EAAE,MAAM,EAAE,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAO,GAC/C,iBAAiB,CAAC,OAAO,CAAC;IAgB7B,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC;IAO3C,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,gBAAgB;IAIpD,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,UAAO;cAOtD,cAAc,CAC5B,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;IA4BhB,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAQ9C,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,KAAK;IAIL;;;;;;OAMG;IACH,EAAE,CAAC,KAAK,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,IAAI;IAOrG;;;;;;OAMG;IACH,GAAG,CAAC,KAAK,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,IAAI;IAQtG;;;;OAIG;IACH,IAAI,CAAC,KAAK,SAAS,MAAM,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,IAAI;IAOvG;;;;;;;;;;OAUG;IACH,OAAO,CAAC,KAAK,SAAS,MAAM,mBAAmB,EAC7C,KAAK,EAAE,KAAK,GACX,OAAO,CACR,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,GAAG,KAAK,GAClE,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,GAAG,IAAI,GACxD,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CACzC;IAQK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,IAAI,cAAc,IAAI,WAAW,GAAG,SAAS,CAE5C;IASD;;;;OAIG;IACG,YAAY,IAAI,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAmBzD;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IA0BlC,SAAS,CAAC,KAAK,CAAC,KAAK,SAAS,MAAM,mBAAmB,EACrD,KAAK,EAAE,KAAK,EACZ,GAAG,IAAI,EAAE,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IA8CjD,SAAS,CAAC,UAAU;cA8FJ,mBAAmB,CACjC,cAAc,EAAE,cAAc,EAC9B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC;IAuKhB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,sBAAsB,CAAC;IA6D/D,gBAAgB,IAAI,cAAc;CAInC"}

View File

@@ -0,0 +1,122 @@
import type { Logger } from "../client.js";
import { AnthropicError, APIUserAbortError } from "../error.js";
import { type RequestOptions } from "../internal/request-options.js";
import { type BetaContentBlock, type BetaMCPToolUseBlock, type BetaMessage, type BetaMessageParam, Messages as BetaMessages, type BetaRawMessageStreamEvent as BetaMessageStreamEvent, type BetaServerToolUseBlock, type BetaTextCitation, type BetaToolUseBlock, type MessageCreateParams, type MessageCreateParamsBase } from "../resources/beta/messages/messages.js";
import { type ParsedBetaMessage } from "./beta-parser.js";
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;
thinking: (thinkingDelta: string, thinkingSnapshot: string) => void;
signature: (signature: string) => void;
compaction: (compactedContent: string) => void;
message: (message: BetaMessage) => void;
contentBlock: (content: BetaContentBlock) => void;
finalMessage: (message: BetaMessage) => void;
error: (error: AnthropicError) => void;
abort: (error: APIUserAbortError) => void;
end: () => void;
}
export type TracksToolInput = BetaToolUseBlock | BetaServerToolUseBlock | BetaMCPToolUseBlock;
export declare class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMessageStreamEvent> {
#private;
messages: BetaMessageParam[];
receivedMessages: ParsedBetaMessage<ParsedT>[];
controller: AbortController;
constructor(params: MessageCreateParamsBase | null, opts?: {
logger?: Logger | undefined;
});
get response(): Response | null | undefined;
get request_id(): string | null | undefined;
/**
* 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.
*/
withResponse(): Promise<{
data: BetaMessageStream<ParsedT>;
response: Response;
request_id: string | null | undefined;
}>;
/**
* 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;
static createMessage<ParsedT>(messages: BetaMessages, params: MessageCreateParamsBase, options?: RequestOptions, { logger }?: {
logger?: Logger | undefined;
}): BetaMessageStream<ParsedT>;
protected _run(executor: () => Promise<any>): void;
protected _addMessageParam(message: BetaMessageParam): void;
protected _addMessage(message: ParsedBetaMessage<ParsedT>, emit?: boolean): void;
protected _createMessage(messages: BetaMessages, params: MessageCreateParams, options?: RequestOptions): Promise<void>;
protected _connected(response: Response | null): void;
get ended(): boolean;
get errored(): boolean;
get aborted(): boolean;
abort(): void;
/**
* 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 extends keyof MessageStreamEvents>(event: Event, listener: MessageStreamEvents[Event]): 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 extends keyof MessageStreamEvents>(event: Event, listener: MessageStreamEvents[Event]): 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 extends keyof MessageStreamEvents>(event: Event, listener: MessageStreamEvents[Event]): 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 extends keyof MessageStreamEvents>(event: Event): Promise<Parameters<MessageStreamEvents[Event]> extends [infer Param] ? Param : Parameters<MessageStreamEvents[Event]> extends [] ? void : Parameters<MessageStreamEvents[Event]>>;
done(): Promise<void>;
get currentMessage(): BetaMessage | undefined;
/**
* @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.
*/
finalMessage(): Promise<ParsedBetaMessage<ParsedT>>;
/**
* @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.
*/
finalText(): Promise<string>;
protected _emit<Event extends keyof MessageStreamEvents>(event: Event, ...args: Parameters<MessageStreamEvents[Event]>): void;
protected _emitFinal(): void;
protected _fromReadableStream(readableStream: ReadableStream, options?: RequestOptions): Promise<void>;
[Symbol.asyncIterator](): AsyncIterator<BetaMessageStreamEvent>;
toReadableStream(): ReadableStream;
}
//# sourceMappingURL=BetaMessageStream.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaMessageStream.d.ts","sourceRoot":"","sources":["../src/lib/BetaMessageStream.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,620 @@
"use strict";
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;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BetaMessageStream = void 0;
const tslib_1 = require("../internal/tslib.js");
const parser_1 = require("../_vendor/partial-json-parser/parser.js");
const error_1 = require("../error.js");
const errors_1 = require("../internal/errors.js");
const streaming_1 = require("../streaming.js");
const beta_parser_1 = require("./beta-parser.js");
const JSON_BUF_PROPERTY = '__json_buf';
function tracksToolInput(content) {
return content.type === 'tool_use' || content.type === 'server_tool_use' || content.type === 'mcp_tool_use';
}
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) => {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_errored, true, "f");
if ((0, errors_1.isAbortError)(error)) {
error = new error_1.APIUserAbortError();
}
if (error instanceof error_1.APIUserAbortError) {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_aborted, true, "f");
return this._emit('abort', error);
}
if (error instanceof error_1.AnthropicError) {
return this._emit('error', error);
}
if (error instanceof Error) {
const anthropicError = new error_1.AnthropicError(error.message);
// @ts-ignore
anthropicError.cause = error;
return this._emit('error', anthropicError);
}
return this._emit('error', new error_1.AnthropicError(String(error)));
});
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((resolve, reject) => {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise, resolve, "f");
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_rejectConnectedPromise, reject, "f");
}), "f");
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((resolve, reject) => {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise, resolve, "f");
tslib_1.__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.
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f").catch(() => { });
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f").catch(() => { });
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_params, params, "f");
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_logger, opts?.logger ?? console, "f");
}
get response() {
return tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_response, "f");
}
get request_id() {
return tslib_1.__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() {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
const response = await tslib_1.__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);
}
tslib_1.__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');
}, tslib_1.__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 {
tslib_1.__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) {
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new error_1.APIUserAbortError();
}
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_endRequest).call(this);
}
finally {
if (signal && abortHandler) {
signal.removeEventListener('abort', abortHandler);
}
}
}
_connected(response) {
if (this.ended)
return;
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_response, response, "f");
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_request_id, response?.headers.get('request-id'), "f");
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_resolveConnectedPromise, "f").call(this, response);
this._emit('connect');
}
get ended() {
return tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_ended, "f");
}
get errored() {
return tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_errored, "f");
}
get aborted() {
return tslib_1.__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 = tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] || (tslib_1.__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 = tslib_1.__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 = tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] || (tslib_1.__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) => {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
if (event !== 'error')
this.once('error', reject);
this.once(event, resolve);
});
}
async done() {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
await tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f");
}
get currentMessage() {
return tslib_1.__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 tslib_1.__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 tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalText).call(this);
}
_emit(event, ...args) {
// make sure we don't emit any MessageStreamEvents after end
if (tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_ended, "f"))
return;
if (event === 'end') {
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_ended, true, "f");
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_resolveEndPromise, "f").call(this);
}
const listeners = tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event];
if (listeners) {
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
listeners.forEach(({ listener }) => listener(...args));
}
if (event === 'abort') {
const error = args[0];
if (!tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
Promise.reject(error);
}
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_rejectConnectedPromise, "f").call(this, error);
tslib_1.__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 (!tslib_1.__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);
}
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_rejectConnectedPromise, "f").call(this, error);
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_rejectEndPromise, "f").call(this, error);
this._emit('end');
}
}
_emitFinal() {
const finalMessage = this.receivedMessages.at(-1);
if (finalMessage) {
this._emit('finalMessage', tslib_1.__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 {
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_beginRequest).call(this);
this._connected(null);
const stream = streaming_1.Stream.fromReadableStream(readableStream, this.controller);
for await (const event of stream) {
tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new error_1.APIUserAbortError();
}
tslib_1.__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 error_1.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 error_1.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 error_1.AnthropicError('stream ended without producing a content block with type=text');
}
return textBlocks.join(' ');
}, _BetaMessageStream_beginRequest = function _BetaMessageStream_beginRequest() {
if (this.ended)
return;
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f");
}, _BetaMessageStream_addStreamEvent = function _BetaMessageStream_addStreamEvent(event) {
if (this.ended)
return;
const messageSnapshot = tslib_1.__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((0, beta_parser_1.maybeParseBetaMessage)(messageSnapshot, tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_logger, "f") }), true);
break;
}
case 'content_block_stop': {
this._emit('contentBlock', messageSnapshot.content.at(-1));
break;
}
case 'message_start': {
tslib_1.__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 error_1.AnthropicError(`stream has ended, this shouldn't happen`);
}
const snapshot = tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
if (!snapshot) {
throw new error_1.AnthropicError(`request ended without sending any chunks`);
}
tslib_1.__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f");
return (0, beta_parser_1.maybeParseBetaMessage)(snapshot, tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_logger, "f") });
}, _BetaMessageStream_accumulateMessage = function _BetaMessageStream_accumulateMessage(event) {
let snapshot = tslib_1.__classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
if (event.type === 'message_start') {
if (snapshot) {
throw new error_1.AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
}
return event.message;
}
if (!snapshot) {
throw new error_1.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 = (0, parser_1.partialParse)(jsonBuf);
}
catch (err) {
const error = new error_1.AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err}. JSON: ${jsonBuf}`);
tslib_1.__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 streaming_1.Stream(this[Symbol.asyncIterator].bind(this), this.controller);
return stream.toReadableStream();
}
}
exports.BetaMessageStream = BetaMessageStream;
// used to ensure exhaustive case matching without throwing a runtime error
function checkNever(x) { }
//# sourceMappingURL=BetaMessageStream.js.map

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,121 @@
import { AnthropicError, APIUserAbortError } from "../error.mjs";
import { type ContentBlock, Messages, type Message, type MessageStreamEvent, type MessageParam, type MessageCreateParams, type MessageCreateParamsBase, type TextCitation, type ToolUseBlock, type ServerToolUseBlock } from "../resources/messages.mjs";
import { RequestOptions } from "../internal/request-options.mjs";
import type { Logger } from "../client.mjs";
import { type ParsedMessage } from "./parser.mjs";
export interface MessageStreamEvents<ParsedT = null> {
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;
thinking: (thinkingDelta: string, thinkingSnapshot: string) => void;
signature: (signature: string) => void;
message: (message: ParsedMessage<ParsedT>) => void;
contentBlock: (content: ContentBlock) => void;
finalMessage: (message: ParsedMessage<ParsedT>) => void;
error: (error: AnthropicError) => void;
abort: (error: APIUserAbortError) => void;
end: () => void;
}
export type TracksToolInput = ToolUseBlock | ServerToolUseBlock;
export declare class MessageStream<ParsedT = null> implements AsyncIterable<MessageStreamEvent> {
#private;
messages: MessageParam[];
receivedMessages: ParsedMessage<ParsedT>[];
controller: AbortController;
constructor(params: MessageCreateParamsBase | null, opts?: {
logger?: Logger | undefined;
});
get response(): Response | null | undefined;
get request_id(): string | null | undefined;
/**
* 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.
*/
withResponse(): Promise<{
data: MessageStream<ParsedT>;
response: Response;
request_id: string | null | undefined;
}>;
/**
* 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): MessageStream;
static createMessage<ParsedT>(messages: Messages, params: MessageCreateParamsBase, options?: RequestOptions, { logger }?: {
logger?: Logger | undefined;
}): MessageStream<ParsedT>;
protected _run(executor: () => Promise<any>): void;
protected _addMessageParam(message: MessageParam): void;
protected _addMessage(message: ParsedMessage<ParsedT>, emit?: boolean): void;
protected _createMessage(messages: Messages, params: MessageCreateParams, options?: RequestOptions): Promise<void>;
protected _connected(response: Response | null): void;
get ended(): boolean;
get errored(): boolean;
get aborted(): boolean;
abort(): void;
/**
* 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event, listener: MessageStreamEvents<ParsedT>[Event]): 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event, listener: MessageStreamEvents<ParsedT>[Event]): 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event, listener: MessageStreamEvents<ParsedT>[Event]): 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event): Promise<Parameters<MessageStreamEvents<ParsedT>[Event]> extends [infer Param] ? Param : Parameters<MessageStreamEvents<ParsedT>[Event]> extends [] ? void : Parameters<MessageStreamEvents<ParsedT>[Event]>>;
done(): Promise<void>;
get currentMessage(): Message | undefined;
/**
* @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.
*/
finalMessage(): Promise<ParsedMessage<ParsedT>>;
/**
* @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.
*/
finalText(): Promise<string>;
protected _emit<Event extends keyof MessageStreamEvents<ParsedT>>(event: Event, ...args: Parameters<MessageStreamEvents<ParsedT>[Event]>): void;
protected _emitFinal(): void;
protected _fromReadableStream(readableStream: ReadableStream, options?: RequestOptions): Promise<void>;
[Symbol.asyncIterator](): AsyncIterator<MessageStreamEvent>;
toReadableStream(): ReadableStream;
}
//# sourceMappingURL=MessageStream.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MessageStream.d.mts","sourceRoot":"","sources":["../src/lib/MessageStream.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,121 @@
import { AnthropicError, APIUserAbortError } from "../error.js";
import { type ContentBlock, Messages, type Message, type MessageStreamEvent, type MessageParam, type MessageCreateParams, type MessageCreateParamsBase, type TextCitation, type ToolUseBlock, type ServerToolUseBlock } from "../resources/messages.js";
import { RequestOptions } from "../internal/request-options.js";
import type { Logger } from "../client.js";
import { type ParsedMessage } from "./parser.js";
export interface MessageStreamEvents<ParsedT = null> {
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;
thinking: (thinkingDelta: string, thinkingSnapshot: string) => void;
signature: (signature: string) => void;
message: (message: ParsedMessage<ParsedT>) => void;
contentBlock: (content: ContentBlock) => void;
finalMessage: (message: ParsedMessage<ParsedT>) => void;
error: (error: AnthropicError) => void;
abort: (error: APIUserAbortError) => void;
end: () => void;
}
export type TracksToolInput = ToolUseBlock | ServerToolUseBlock;
export declare class MessageStream<ParsedT = null> implements AsyncIterable<MessageStreamEvent> {
#private;
messages: MessageParam[];
receivedMessages: ParsedMessage<ParsedT>[];
controller: AbortController;
constructor(params: MessageCreateParamsBase | null, opts?: {
logger?: Logger | undefined;
});
get response(): Response | null | undefined;
get request_id(): string | null | undefined;
/**
* 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.
*/
withResponse(): Promise<{
data: MessageStream<ParsedT>;
response: Response;
request_id: string | null | undefined;
}>;
/**
* 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): MessageStream;
static createMessage<ParsedT>(messages: Messages, params: MessageCreateParamsBase, options?: RequestOptions, { logger }?: {
logger?: Logger | undefined;
}): MessageStream<ParsedT>;
protected _run(executor: () => Promise<any>): void;
protected _addMessageParam(message: MessageParam): void;
protected _addMessage(message: ParsedMessage<ParsedT>, emit?: boolean): void;
protected _createMessage(messages: Messages, params: MessageCreateParams, options?: RequestOptions): Promise<void>;
protected _connected(response: Response | null): void;
get ended(): boolean;
get errored(): boolean;
get aborted(): boolean;
abort(): void;
/**
* 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event, listener: MessageStreamEvents<ParsedT>[Event]): 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event, listener: MessageStreamEvents<ParsedT>[Event]): 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event, listener: MessageStreamEvents<ParsedT>[Event]): 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 extends keyof MessageStreamEvents<ParsedT>>(event: Event): Promise<Parameters<MessageStreamEvents<ParsedT>[Event]> extends [infer Param] ? Param : Parameters<MessageStreamEvents<ParsedT>[Event]> extends [] ? void : Parameters<MessageStreamEvents<ParsedT>[Event]>>;
done(): Promise<void>;
get currentMessage(): Message | undefined;
/**
* @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.
*/
finalMessage(): Promise<ParsedMessage<ParsedT>>;
/**
* @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.
*/
finalText(): Promise<string>;
protected _emit<Event extends keyof MessageStreamEvents<ParsedT>>(event: Event, ...args: Parameters<MessageStreamEvents<ParsedT>[Event]>): void;
protected _emitFinal(): void;
protected _fromReadableStream(readableStream: ReadableStream, options?: RequestOptions): Promise<void>;
[Symbol.asyncIterator](): AsyncIterator<MessageStreamEvent>;
toReadableStream(): ReadableStream;
}
//# sourceMappingURL=MessageStream.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MessageStream.d.ts","sourceRoot":"","sources":["../src/lib/MessageStream.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,595 @@
"use strict";
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;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageStream = void 0;
const tslib_1 = require("../internal/tslib.js");
const errors_1 = require("../internal/errors.js");
const error_1 = require("../error.js");
const streaming_1 = require("../streaming.js");
const parser_1 = require("../_vendor/partial-json-parser/parser.js");
const parser_2 = require("./parser.js");
const JSON_BUF_PROPERTY = '__json_buf';
function tracksToolInput(content) {
return content.type === 'tool_use' || content.type === 'server_tool_use';
}
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) => {
tslib_1.__classPrivateFieldSet(this, _MessageStream_errored, true, "f");
if ((0, errors_1.isAbortError)(error)) {
error = new error_1.APIUserAbortError();
}
if (error instanceof error_1.APIUserAbortError) {
tslib_1.__classPrivateFieldSet(this, _MessageStream_aborted, true, "f");
return this._emit('abort', error);
}
if (error instanceof error_1.AnthropicError) {
return this._emit('error', error);
}
if (error instanceof Error) {
const anthropicError = new error_1.AnthropicError(error.message);
// @ts-ignore
anthropicError.cause = error;
return this._emit('error', anthropicError);
}
return this._emit('error', new error_1.AnthropicError(String(error)));
});
tslib_1.__classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((resolve, reject) => {
tslib_1.__classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise, resolve, "f");
tslib_1.__classPrivateFieldSet(this, _MessageStream_rejectConnectedPromise, reject, "f");
}), "f");
tslib_1.__classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((resolve, reject) => {
tslib_1.__classPrivateFieldSet(this, _MessageStream_resolveEndPromise, resolve, "f");
tslib_1.__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.
tslib_1.__classPrivateFieldGet(this, _MessageStream_connectedPromise, "f").catch(() => { });
tslib_1.__classPrivateFieldGet(this, _MessageStream_endPromise, "f").catch(() => { });
tslib_1.__classPrivateFieldSet(this, _MessageStream_params, params, "f");
tslib_1.__classPrivateFieldSet(this, _MessageStream_logger, opts?.logger ?? console, "f");
}
get response() {
return tslib_1.__classPrivateFieldGet(this, _MessageStream_response, "f");
}
get request_id() {
return tslib_1.__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() {
tslib_1.__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
const response = await tslib_1.__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);
}
tslib_1.__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');
}, tslib_1.__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 {
tslib_1.__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) {
tslib_1.__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new error_1.APIUserAbortError();
}
tslib_1.__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_endRequest).call(this);
}
finally {
if (signal && abortHandler) {
signal.removeEventListener('abort', abortHandler);
}
}
}
_connected(response) {
if (this.ended)
return;
tslib_1.__classPrivateFieldSet(this, _MessageStream_response, response, "f");
tslib_1.__classPrivateFieldSet(this, _MessageStream_request_id, response?.headers.get('request-id'), "f");
tslib_1.__classPrivateFieldGet(this, _MessageStream_resolveConnectedPromise, "f").call(this, response);
this._emit('connect');
}
get ended() {
return tslib_1.__classPrivateFieldGet(this, _MessageStream_ended, "f");
}
get errored() {
return tslib_1.__classPrivateFieldGet(this, _MessageStream_errored, "f");
}
get aborted() {
return tslib_1.__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 = tslib_1.__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] || (tslib_1.__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 = tslib_1.__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 = tslib_1.__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] || (tslib_1.__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) => {
tslib_1.__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
if (event !== 'error')
this.once('error', reject);
this.once(event, resolve);
});
}
async done() {
tslib_1.__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
await tslib_1.__classPrivateFieldGet(this, _MessageStream_endPromise, "f");
}
get currentMessage() {
return tslib_1.__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 tslib_1.__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 tslib_1.__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalText).call(this);
}
_emit(event, ...args) {
// make sure we don't emit any MessageStreamEvents after end
if (tslib_1.__classPrivateFieldGet(this, _MessageStream_ended, "f"))
return;
if (event === 'end') {
tslib_1.__classPrivateFieldSet(this, _MessageStream_ended, true, "f");
tslib_1.__classPrivateFieldGet(this, _MessageStream_resolveEndPromise, "f").call(this);
}
const listeners = tslib_1.__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event];
if (listeners) {
tslib_1.__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
listeners.forEach(({ listener }) => listener(...args));
}
if (event === 'abort') {
const error = args[0];
if (!tslib_1.__classPrivateFieldGet(this, _MessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
Promise.reject(error);
}
tslib_1.__classPrivateFieldGet(this, _MessageStream_rejectConnectedPromise, "f").call(this, error);
tslib_1.__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 (!tslib_1.__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);
}
tslib_1.__classPrivateFieldGet(this, _MessageStream_rejectConnectedPromise, "f").call(this, error);
tslib_1.__classPrivateFieldGet(this, _MessageStream_rejectEndPromise, "f").call(this, error);
this._emit('end');
}
}
_emitFinal() {
const finalMessage = this.receivedMessages.at(-1);
if (finalMessage) {
this._emit('finalMessage', tslib_1.__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 {
tslib_1.__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_beginRequest).call(this);
this._connected(null);
const stream = streaming_1.Stream.fromReadableStream(readableStream, this.controller);
for await (const event of stream) {
tslib_1.__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_addStreamEvent).call(this, event);
}
if (stream.controller.signal?.aborted) {
throw new error_1.APIUserAbortError();
}
tslib_1.__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 error_1.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 error_1.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 error_1.AnthropicError('stream ended without producing a content block with type=text');
}
return textBlocks.join(' ');
}, _MessageStream_beginRequest = function _MessageStream_beginRequest() {
if (this.ended)
return;
tslib_1.__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, undefined, "f");
}, _MessageStream_addStreamEvent = function _MessageStream_addStreamEvent(event) {
if (this.ended)
return;
const messageSnapshot = tslib_1.__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((0, parser_2.maybeParseMessage)(messageSnapshot, tslib_1.__classPrivateFieldGet(this, _MessageStream_params, "f"), { logger: tslib_1.__classPrivateFieldGet(this, _MessageStream_logger, "f") }), true);
break;
}
case 'content_block_stop': {
this._emit('contentBlock', messageSnapshot.content.at(-1));
break;
}
case 'message_start': {
tslib_1.__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 error_1.AnthropicError(`stream has ended, this shouldn't happen`);
}
const snapshot = tslib_1.__classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
if (!snapshot) {
throw new error_1.AnthropicError(`request ended without sending any chunks`);
}
tslib_1.__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, undefined, "f");
return (0, parser_2.maybeParseMessage)(snapshot, tslib_1.__classPrivateFieldGet(this, _MessageStream_params, "f"), { logger: tslib_1.__classPrivateFieldGet(this, _MessageStream_logger, "f") });
}, _MessageStream_accumulateMessage = function _MessageStream_accumulateMessage(event) {
let snapshot = tslib_1.__classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
if (event.type === 'message_start') {
if (snapshot) {
throw new error_1.AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
}
return event.message;
}
if (!snapshot) {
throw new error_1.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 = (0, parser_1.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 streaming_1.Stream(this[Symbol.asyncIterator].bind(this), this.controller);
return stream.toReadableStream();
}
}
exports.MessageStream = MessageStream;
// used to ensure exhaustive case matching without throwing a runtime error
function checkNever(x) { }
//# sourceMappingURL=MessageStream.js.map

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
import type { Logger } from "../client.mjs";
import { BetaContentBlock, BetaJSONOutputFormat, BetaMessage, BetaOutputConfig, BetaTextBlock, MessageCreateParams } from "../resources/beta/messages/messages.mjs";
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
type AutoParseableBetaOutputConfig = Omit<BetaOutputConfig, 'format'> & {
format?: BetaJSONOutputFormat | AutoParseableBetaOutputFormat<any> | null;
};
export type BetaParseableMessageCreateParams = Simplify<Omit<MessageCreateParams, 'output_format' | 'output_config'> & {
/**
* @deprecated Use `output_config.format` instead. This parameter will be removed in a future
* release.
*/
output_format?: BetaJSONOutputFormat | AutoParseableBetaOutputFormat<any> | null;
output_config?: AutoParseableBetaOutputConfig | null;
}>;
export type ExtractParsedContentFromBetaParams<Params extends BetaParseableMessageCreateParams> = Params['output_format'] extends AutoParseableBetaOutputFormat<infer P> ? P : Params['output_config'] extends {
format: AutoParseableBetaOutputFormat<infer P>;
} ? P : null;
export type AutoParseableBetaOutputFormat<ParsedT> = BetaJSONOutputFormat & {
parse(content: string): ParsedT;
};
export type ParsedBetaMessage<ParsedT> = BetaMessage & {
content: Array<ParsedBetaContentBlock<ParsedT>>;
parsed_output: ParsedT | null;
};
export type ParsedBetaContentBlock<ParsedT> = (BetaTextBlock & {
parsed_output: ParsedT | null;
}) | Exclude<BetaContentBlock, BetaTextBlock>;
export declare function maybeParseBetaMessage<Params extends BetaParseableMessageCreateParams | null>(message: BetaMessage, params: Params, opts: {
logger: Logger;
}): ParsedBetaMessage<ExtractParsedContentFromBetaParams<NonNullable<Params>>>;
export declare function parseBetaMessage<Params extends BetaParseableMessageCreateParams>(message: BetaMessage, params: Params, opts: {
logger: Logger;
}): ParsedBetaMessage<ExtractParsedContentFromBetaParams<Params>>;
export {};
//# sourceMappingURL=beta-parser.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"beta-parser.d.mts","sourceRoot":"","sources":["../src/lib/beta-parser.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,MAAM,EAAE;OAEf,EACL,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB;AAGD,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D,KAAK,6BAA6B,GAAG,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG;IACtE,MAAM,CAAC,EAAE,oBAAoB,GAAG,6BAA6B,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CAC3E,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CACrD,IAAI,CAAC,mBAAmB,EAAE,eAAe,GAAG,eAAe,CAAC,GAAG;IAC7D;;;OAGG;IACH,aAAa,CAAC,EAAE,oBAAoB,GAAG,6BAA6B,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACjF,aAAa,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAC;CACtD,CACF,CAAC;AAEF,MAAM,MAAM,kCAAkC,CAAC,MAAM,SAAS,gCAAgC,IAC5F,MAAM,CAAC,eAAe,CAAC,SAAS,6BAA6B,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GACxE,MAAM,CAAC,eAAe,CAAC,SAAS;IAAE,MAAM,EAAE,6BAA6B,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,CAAC,GACtF,IAAI,CAAC;AAET,MAAM,MAAM,6BAA6B,CAAC,OAAO,IAAI,oBAAoB,GAAG;IAC1E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,OAAO,IAAI,WAAW,GAAG;IACrD,OAAO,EAAE,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,OAAO,IACtC,CAAC,aAAa,GAAG;IAAE,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC,GACnD,OAAO,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;AAS7C,wBAAgB,qBAAqB,CAAC,MAAM,SAAS,gCAAgC,GAAG,IAAI,EAC1F,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,iBAAiB,CAAC,kCAAkC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CA6B5E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,gCAAgC,EAC9E,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,iBAAiB,CAAC,kCAAkC,CAAC,MAAM,CAAC,CAAC,CAkC/D"}

View File

@@ -0,0 +1,37 @@
import type { Logger } from "../client.js";
import { BetaContentBlock, BetaJSONOutputFormat, BetaMessage, BetaOutputConfig, BetaTextBlock, MessageCreateParams } from "../resources/beta/messages/messages.js";
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
type AutoParseableBetaOutputConfig = Omit<BetaOutputConfig, 'format'> & {
format?: BetaJSONOutputFormat | AutoParseableBetaOutputFormat<any> | null;
};
export type BetaParseableMessageCreateParams = Simplify<Omit<MessageCreateParams, 'output_format' | 'output_config'> & {
/**
* @deprecated Use `output_config.format` instead. This parameter will be removed in a future
* release.
*/
output_format?: BetaJSONOutputFormat | AutoParseableBetaOutputFormat<any> | null;
output_config?: AutoParseableBetaOutputConfig | null;
}>;
export type ExtractParsedContentFromBetaParams<Params extends BetaParseableMessageCreateParams> = Params['output_format'] extends AutoParseableBetaOutputFormat<infer P> ? P : Params['output_config'] extends {
format: AutoParseableBetaOutputFormat<infer P>;
} ? P : null;
export type AutoParseableBetaOutputFormat<ParsedT> = BetaJSONOutputFormat & {
parse(content: string): ParsedT;
};
export type ParsedBetaMessage<ParsedT> = BetaMessage & {
content: Array<ParsedBetaContentBlock<ParsedT>>;
parsed_output: ParsedT | null;
};
export type ParsedBetaContentBlock<ParsedT> = (BetaTextBlock & {
parsed_output: ParsedT | null;
}) | Exclude<BetaContentBlock, BetaTextBlock>;
export declare function maybeParseBetaMessage<Params extends BetaParseableMessageCreateParams | null>(message: BetaMessage, params: Params, opts: {
logger: Logger;
}): ParsedBetaMessage<ExtractParsedContentFromBetaParams<NonNullable<Params>>>;
export declare function parseBetaMessage<Params extends BetaParseableMessageCreateParams>(message: BetaMessage, params: Params, opts: {
logger: Logger;
}): ParsedBetaMessage<ExtractParsedContentFromBetaParams<Params>>;
export {};
//# sourceMappingURL=beta-parser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"beta-parser.d.ts","sourceRoot":"","sources":["../src/lib/beta-parser.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,MAAM,EAAE;OAEf,EACL,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACpB;AAGD,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D,KAAK,6BAA6B,GAAG,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG;IACtE,MAAM,CAAC,EAAE,oBAAoB,GAAG,6BAA6B,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CAC3E,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CACrD,IAAI,CAAC,mBAAmB,EAAE,eAAe,GAAG,eAAe,CAAC,GAAG;IAC7D;;;OAGG;IACH,aAAa,CAAC,EAAE,oBAAoB,GAAG,6BAA6B,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IACjF,aAAa,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAC;CACtD,CACF,CAAC;AAEF,MAAM,MAAM,kCAAkC,CAAC,MAAM,SAAS,gCAAgC,IAC5F,MAAM,CAAC,eAAe,CAAC,SAAS,6BAA6B,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GACxE,MAAM,CAAC,eAAe,CAAC,SAAS;IAAE,MAAM,EAAE,6BAA6B,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,CAAC,GACtF,IAAI,CAAC;AAET,MAAM,MAAM,6BAA6B,CAAC,OAAO,IAAI,oBAAoB,GAAG;IAC1E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,OAAO,IAAI,WAAW,GAAG;IACrD,OAAO,EAAE,KAAK,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,OAAO,IACtC,CAAC,aAAa,GAAG;IAAE,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC,GACnD,OAAO,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;AAS7C,wBAAgB,qBAAqB,CAAC,MAAM,SAAS,gCAAgC,GAAG,IAAI,EAC1F,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,iBAAiB,CAAC,kCAAkC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CA6B5E;AAED,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,gCAAgC,EAC9E,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,iBAAiB,CAAC,kCAAkC,CAAC,MAAM,CAAC,CAAC,CAkC/D"}

View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.maybeParseBetaMessage = maybeParseBetaMessage;
exports.parseBetaMessage = parseBetaMessage;
const error_1 = require("../core/error.js");
function getOutputFormat(params) {
// Prefer output_format (deprecated) over output_config.format for backward compatibility
return params?.output_format ?? params?.output_config?.format;
}
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);
}
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 error_1.AnthropicError(`Failed to parse structured output: ${error}`);
}
}
//# sourceMappingURL=beta-parser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"beta-parser.js","sourceRoot":"","sources":["../src/lib/beta-parser.ts"],"names":[],"mappings":"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"}

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 @@
{"version":3,"file":"beta-parser.mjs","sourceRoot":"","sources":["../src/lib/beta-parser.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,32 @@
import type { Logger } from "../client.mjs";
import { ContentBlock, JSONOutputFormat, Message, OutputConfig, TextBlock, MessageCreateParams } from "../resources/messages/messages.mjs";
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
type AutoParseableOutputConfig = Omit<OutputConfig, 'format'> & {
format?: JSONOutputFormat | AutoParseableOutputFormat<any> | null;
};
export type ParseableMessageCreateParams = Simplify<Omit<MessageCreateParams, 'output_config'> & {
output_config?: AutoParseableOutputConfig | null;
}>;
export type ExtractParsedContentFromParams<Params extends ParseableMessageCreateParams> = Params['output_config'] extends {
format: AutoParseableOutputFormat<infer P>;
} ? P : null;
export type AutoParseableOutputFormat<ParsedT> = JSONOutputFormat & {
parse(content: string): ParsedT;
};
export type ParsedMessage<ParsedT> = Message & {
content: Array<ParsedContentBlock<ParsedT>>;
parsed_output: ParsedT | null;
};
export type ParsedContentBlock<ParsedT> = (TextBlock & {
parsed_output: ParsedT | null;
}) | Exclude<ContentBlock, TextBlock>;
export declare function maybeParseMessage<Params extends ParseableMessageCreateParams | null>(message: Message, params: Params, opts: {
logger: Logger;
}): ParsedMessage<ExtractParsedContentFromParams<NonNullable<Params>>>;
export declare function parseMessage<Params extends ParseableMessageCreateParams>(message: Message, params: Params, opts: {
logger: Logger;
}): ParsedMessage<ExtractParsedContentFromParams<Params>>;
export {};
//# sourceMappingURL=parser.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser.d.mts","sourceRoot":"","sources":["../src/lib/parser.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,MAAM,EAAE;OAEf,EACL,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,SAAS,EACT,mBAAmB,EACpB;AAGD,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D,KAAK,yBAAyB,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAC9D,MAAM,CAAC,EAAE,gBAAgB,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CACjD,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,GAAG;IAC3C,aAAa,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAClD,CACF,CAAC;AAEF,MAAM,MAAM,8BAA8B,CAAC,MAAM,SAAS,4BAA4B,IACpF,MAAM,CAAC,eAAe,CAAC,SAAS;IAAE,MAAM,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,IAAI,CAAC;AAE5F,MAAM,MAAM,yBAAyB,CAAC,OAAO,IAAI,gBAAgB,GAAG;IAClE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,OAAO,IAAI,OAAO,GAAG;IAC7C,OAAO,EAAE,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,OAAO,IAClC,CAAC,SAAS,GAAG;IAAE,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC,GAC/C,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AAQrC,wBAAgB,iBAAiB,CAAC,MAAM,SAAS,4BAA4B,GAAG,IAAI,EAClF,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,aAAa,CAAC,8BAA8B,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAqBpE;AAED,wBAAgB,YAAY,CAAC,MAAM,SAAS,4BAA4B,EACtE,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,aAAa,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC,CA2BvD"}

View File

@@ -0,0 +1,32 @@
import type { Logger } from "../client.js";
import { ContentBlock, JSONOutputFormat, Message, OutputConfig, TextBlock, MessageCreateParams } from "../resources/messages/messages.js";
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
type AutoParseableOutputConfig = Omit<OutputConfig, 'format'> & {
format?: JSONOutputFormat | AutoParseableOutputFormat<any> | null;
};
export type ParseableMessageCreateParams = Simplify<Omit<MessageCreateParams, 'output_config'> & {
output_config?: AutoParseableOutputConfig | null;
}>;
export type ExtractParsedContentFromParams<Params extends ParseableMessageCreateParams> = Params['output_config'] extends {
format: AutoParseableOutputFormat<infer P>;
} ? P : null;
export type AutoParseableOutputFormat<ParsedT> = JSONOutputFormat & {
parse(content: string): ParsedT;
};
export type ParsedMessage<ParsedT> = Message & {
content: Array<ParsedContentBlock<ParsedT>>;
parsed_output: ParsedT | null;
};
export type ParsedContentBlock<ParsedT> = (TextBlock & {
parsed_output: ParsedT | null;
}) | Exclude<ContentBlock, TextBlock>;
export declare function maybeParseMessage<Params extends ParseableMessageCreateParams | null>(message: Message, params: Params, opts: {
logger: Logger;
}): ParsedMessage<ExtractParsedContentFromParams<NonNullable<Params>>>;
export declare function parseMessage<Params extends ParseableMessageCreateParams>(message: Message, params: Params, opts: {
logger: Logger;
}): ParsedMessage<ExtractParsedContentFromParams<Params>>;
export {};
//# sourceMappingURL=parser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/lib/parser.ts"],"names":[],"mappings":"OAAO,KAAK,EAAE,MAAM,EAAE;OAEf,EACL,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,YAAY,EACZ,SAAS,EACT,mBAAmB,EACpB;AAGD,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D,KAAK,yBAAyB,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,GAAG;IAC9D,MAAM,CAAC,EAAE,gBAAgB,GAAG,yBAAyB,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CACjD,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,GAAG;IAC3C,aAAa,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAClD,CACF,CAAC;AAEF,MAAM,MAAM,8BAA8B,CAAC,MAAM,SAAS,4BAA4B,IACpF,MAAM,CAAC,eAAe,CAAC,SAAS;IAAE,MAAM,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,IAAI,CAAC;AAE5F,MAAM,MAAM,yBAAyB,CAAC,OAAO,IAAI,gBAAgB,GAAG;IAClE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,OAAO,IAAI,OAAO,GAAG;IAC7C,OAAO,EAAE,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,OAAO,IAClC,CAAC,SAAS,GAAG;IAAE,aAAa,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC,GAC/C,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;AAQrC,wBAAgB,iBAAiB,CAAC,MAAM,SAAS,4BAA4B,GAAG,IAAI,EAClF,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,aAAa,CAAC,8BAA8B,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAqBpE;AAED,wBAAgB,YAAY,CAAC,MAAM,SAAS,4BAA4B,EACtE,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GACvB,aAAa,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC,CA2BvD"}

View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.maybeParseMessage = maybeParseMessage;
exports.parseMessage = parseMessage;
const error_1 = require("../core/error.js");
function getOutputFormat(params) {
return params?.output_config?.format;
}
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);
}
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 error_1.AnthropicError(`Failed to parse structured output: ${error}`);
}
}
//# sourceMappingURL=parser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/lib/parser.ts"],"names":[],"mappings":";;AA8CA,8CAyBC;AAED,oCA+BC;AAvGD,4CAA+C;AAuC/C,SAAS,eAAe,CACtB,MAA2C;IAE3C,OAAO,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC;AACvC,CAAC;AAED,SAAgB,iBAAiB,CAC/B,OAAgB,EAChB,MAAc,EACd,IAAwB;IAExB,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO;YACL,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACrC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC1B,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,EAAE;wBACvE,KAAK,EAAE,IAAI;wBACX,UAAU,EAAE,KAAK;qBAClB,CAA4E,CAAC;oBAE9E,OAAO,WAAW,CAAC;gBACrB,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC,CAAC;YACF,aAAa,EAAE,IAAI;SACkD,CAAC;IAC1E,CAAC;IAED,OAAO,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAgB,YAAY,CAC1B,OAAgB,EAChB,MAAc,EACd,IAAwB;IAExB,IAAI,iBAAiB,GAAwD,IAAI,CAAC;IAElF,MAAM,OAAO,GAAsE,OAAO,CAAC,OAAO,CAAC,GAAG,CACpG,CAAC,KAAK,EAAE,EAAE;QACR,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAE3D,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,iBAAiB,GAAG,YAAY,CAAC;YACnC,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,EAAE;gBACvE,KAAK,EAAE,YAAY;gBACnB,UAAU,EAAE,KAAK;aAClB,CAA+D,CAAC;YACjE,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CACF,CAAC;IAEF,OAAO;QACL,GAAG,OAAO;QACV,OAAO;QACP,aAAa,EAAE,iBAAiB;KACwB,CAAC;AAC7D,CAAC;AAED,SAAS,iBAAiB,CACxB,MAAc,EACd,OAAe;IAEf,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,YAAY,EAAE,IAAI,KAAK,aAAa,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;YAC5B,OAAO,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,sBAAc,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}

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 @@
{"version":3,"file":"parser.mjs","sourceRoot":"","sources":["../src/lib/parser.ts"],"names":[],"mappings":"OACO,EAAE,cAAc,EAAE;AAuCzB,SAAS,eAAe,CACtB,MAA2C;IAE3C,OAAO,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAgB,EAChB,MAAc,EACd,IAAwB;IAExB,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAClD,OAAO;YACL,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACrC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC1B,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,EAAE;wBACvE,KAAK,EAAE,IAAI;wBACX,UAAU,EAAE,KAAK;qBAClB,CAA4E,CAAC;oBAE9E,OAAO,WAAW,CAAC;gBACrB,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC,CAAC;YACF,aAAa,EAAE,IAAI;SACkD,CAAC;IAC1E,CAAC;IAED,OAAO,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAAgB,EAChB,MAAc,EACd,IAAwB;IAExB,IAAI,iBAAiB,GAAwD,IAAI,CAAC;IAElF,MAAM,OAAO,GAAsE,OAAO,CAAC,OAAO,CAAC,GAAG,CACpG,CAAC,KAAK,EAAE,EAAE;QACR,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAE3D,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,iBAAiB,GAAG,YAAY,CAAC;YACnC,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,EAAE;gBACvE,KAAK,EAAE,YAAY;gBACnB,UAAU,EAAE,KAAK;aAClB,CAA+D,CAAC;YACjE,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CACF,CAAC;IAEF,OAAO;QACL,GAAG,OAAO;QACV,OAAO;QACP,aAAa,EAAE,iBAAiB;KACwB,CAAC;AAC7D,CAAC;AAED,SAAS,iBAAiB,CACxB,MAAc,EACd,OAAe;IAEf,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,YAAY,EAAE,IAAI,KAAK,aAAa,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;YAC5B,OAAO,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,cAAc,CAAC,sCAAsC,KAAK,EAAE,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}

View File

@@ -0,0 +1,34 @@
/**
* Shared utilities for tracking SDK helper usage.
*/
import type { BetaMessageParam, BetaToolUnion } from "../resources/beta.mjs";
/**
* Symbol used to mark objects created by SDK helpers for tracking.
* The value is the helper name (e.g., 'mcpTool', 'betaZodTool').
*/
export declare const SDK_HELPER_SYMBOL: unique symbol;
type StainlessHelperObject = {
[SDK_HELPER_SYMBOL]: string;
};
export declare function wasCreatedByStainlessHelper(value: unknown): value is StainlessHelperObject;
/**
* Collects helper names from tools and messages arrays.
* Returns a deduplicated array of helper names found.
*/
export declare function collectStainlessHelpers(tools: BetaToolUnion[] | undefined, messages: BetaMessageParam[] | undefined): string[];
/**
* Builds x-stainless-helper header value from tools and messages.
* Returns an empty object if no helpers are found.
*/
export declare function stainlessHelperHeader(tools: BetaToolUnion[] | undefined, messages: BetaMessageParam[] | undefined): {
'x-stainless-helper'?: string;
};
/**
* Builds x-stainless-helper header value from a file object.
* Returns an empty object if the file is not marked with a helper.
*/
export declare function stainlessHelperHeaderFromFile(file: unknown): {
'x-stainless-helper'?: string;
};
export {};
//# sourceMappingURL=stainless-helper-header.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stainless-helper-header.d.mts","sourceRoot":"","sources":["../src/lib/stainless-helper-header.ts"],"names":[],"mappings":"AAAA;;GAEG;OAEI,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE;AAE/C;;;GAGG;AACH,eAAO,MAAM,iBAAiB,eAA0C,CAAC;AAEzE,KAAK,qBAAqB,GAAG;IAAE,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAE1F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAClC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,SAAS,GACvC,MAAM,EAAE,CA8BV;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAClC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,SAAS,GACvC;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,CAInC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,CAK9F"}

View File

@@ -0,0 +1,34 @@
/**
* Shared utilities for tracking SDK helper usage.
*/
import type { BetaMessageParam, BetaToolUnion } from "../resources/beta.js";
/**
* Symbol used to mark objects created by SDK helpers for tracking.
* The value is the helper name (e.g., 'mcpTool', 'betaZodTool').
*/
export declare const SDK_HELPER_SYMBOL: unique symbol;
type StainlessHelperObject = {
[SDK_HELPER_SYMBOL]: string;
};
export declare function wasCreatedByStainlessHelper(value: unknown): value is StainlessHelperObject;
/**
* Collects helper names from tools and messages arrays.
* Returns a deduplicated array of helper names found.
*/
export declare function collectStainlessHelpers(tools: BetaToolUnion[] | undefined, messages: BetaMessageParam[] | undefined): string[];
/**
* Builds x-stainless-helper header value from tools and messages.
* Returns an empty object if no helpers are found.
*/
export declare function stainlessHelperHeader(tools: BetaToolUnion[] | undefined, messages: BetaMessageParam[] | undefined): {
'x-stainless-helper'?: string;
};
/**
* Builds x-stainless-helper header value from a file object.
* Returns an empty object if the file is not marked with a helper.
*/
export declare function stainlessHelperHeaderFromFile(file: unknown): {
'x-stainless-helper'?: string;
};
export {};
//# sourceMappingURL=stainless-helper-header.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stainless-helper-header.d.ts","sourceRoot":"","sources":["../src/lib/stainless-helper-header.ts"],"names":[],"mappings":"AAAA;;GAEG;OAEI,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE;AAE/C;;;GAGG;AACH,eAAO,MAAM,iBAAiB,eAA0C,CAAC;AAEzE,KAAK,qBAAqB,GAAG;IAAE,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAE1F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAClC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,SAAS,GACvC,MAAM,EAAE,CA8BV;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAClC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,SAAS,GACvC;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,CAInC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,CAK9F"}

View File

@@ -0,0 +1,70 @@
"use strict";
/**
* Shared utilities for tracking SDK helper usage.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SDK_HELPER_SYMBOL = void 0;
exports.wasCreatedByStainlessHelper = wasCreatedByStainlessHelper;
exports.collectStainlessHelpers = collectStainlessHelpers;
exports.stainlessHelperHeader = stainlessHelperHeader;
exports.stainlessHelperHeaderFromFile = stainlessHelperHeaderFromFile;
/**
* Symbol used to mark objects created by SDK helpers for tracking.
* The value is the helper name (e.g., 'mcpTool', 'betaZodTool').
*/
exports.SDK_HELPER_SYMBOL = Symbol('anthropic.sdk.stainlessHelper');
function wasCreatedByStainlessHelper(value) {
return typeof value === 'object' && value !== null && exports.SDK_HELPER_SYMBOL in value;
}
/**
* Collects helper names from tools and messages arrays.
* Returns a deduplicated array of helper names found.
*/
function collectStainlessHelpers(tools, messages) {
const helpers = new Set();
// Collect from tools
if (tools) {
for (const tool of tools) {
if (wasCreatedByStainlessHelper(tool)) {
helpers.add(tool[exports.SDK_HELPER_SYMBOL]);
}
}
}
// Collect from messages and their content blocks
if (messages) {
for (const message of messages) {
if (wasCreatedByStainlessHelper(message)) {
helpers.add(message[exports.SDK_HELPER_SYMBOL]);
}
if (Array.isArray(message.content)) {
for (const block of message.content) {
if (wasCreatedByStainlessHelper(block)) {
helpers.add(block[exports.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.
*/
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.
*/
function stainlessHelperHeaderFromFile(file) {
if (wasCreatedByStainlessHelper(file)) {
return { 'x-stainless-helper': file[exports.SDK_HELPER_SYMBOL] };
}
return {};
}
//# sourceMappingURL=stainless-helper-header.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"stainless-helper-header.js","sourceRoot":"","sources":["../src/lib/stainless-helper-header.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAYH,kEAEC;AAMD,0DAiCC;AAMD,sDAOC;AAMD,sEAKC;AAzED;;;GAGG;AACU,QAAA,iBAAiB,GAAG,MAAM,CAAC,+BAA+B,CAAC,CAAC;AAIzE,SAAgB,2BAA2B,CAAC,KAAc;IACxD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,yBAAiB,IAAI,KAAK,CAAC;AACnF,CAAC;AAED;;;GAGG;AACH,SAAgB,uBAAuB,CACrC,KAAkC,EAClC,QAAwC;IAExC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,qBAAqB;IACrB,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,2BAA2B,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAiB,CAAC,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,2BAA2B,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,yBAAiB,CAAC,CAAC,CAAC;YAC1C,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;oBACpC,IAAI,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC;wBACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,yBAAiB,CAAC,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB,CACnC,KAAkC,EAClC,QAAwC;IAExC,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,SAAgB,6BAA6B,CAAC,IAAa;IACzD,IAAI,2BAA2B,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,oBAAoB,EAAE,IAAI,CAAC,yBAAiB,CAAC,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}

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 @@
{"version":3,"file":"stainless-helper-header.mjs","sourceRoot":"","sources":["../src/lib/stainless-helper-header.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,+BAA+B,CAAC,CAAC;AAIzE,MAAM,UAAU,2BAA2B,CAAC,KAAc;IACxD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,IAAI,KAAK,CAAC;AACnF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,KAAkC,EAClC,QAAwC;IAExC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,qBAAqB;IACrB,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,2BAA2B,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,2BAA2B,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC;YAC1C,CAAC;YAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;oBACpC,IAAI,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC;wBACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAkC,EAClC,QAAwC;IAExC,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,OAAO,EAAE,oBAAoB,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,IAAa;IACzD,IAAI,2BAA2B,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,oBAAoB,EAAE,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAC3D,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}

View File

@@ -0,0 +1,12 @@
import { BetaMemoryTool20250818, BetaTool, BetaToolBash20241022, BetaToolBash20250124, BetaToolComputerUse20241022, BetaToolComputerUse20250124, BetaToolComputerUse20251124, BetaToolResultContentBlockParam, BetaToolTextEditor20241022, BetaToolTextEditor20250124, BetaToolTextEditor20250429, BetaToolTextEditor20250728 } from "../../resources/beta.mjs";
export type Promisable<T> = T | Promise<T>;
/**
* Tool types that can be implemented on the client.
* Excludes server-side tools like code execution, web search, and MCP toolsets.
*/
export type BetaClientRunnableToolType = BetaTool | BetaMemoryTool20250818 | BetaToolBash20241022 | BetaToolBash20250124 | BetaToolComputerUse20241022 | BetaToolComputerUse20250124 | BetaToolComputerUse20251124 | BetaToolTextEditor20241022 | BetaToolTextEditor20250124 | BetaToolTextEditor20250429 | BetaToolTextEditor20250728;
export type BetaRunnableTool<Input = any> = BetaClientRunnableToolType & {
run: (args: Input) => Promisable<string | Array<BetaToolResultContentBlockParam>>;
parse: (content: unknown) => Input;
};
//# sourceMappingURL=BetaRunnableTool.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaRunnableTool.d.mts","sourceRoot":"","sources":["../../src/lib/tools/BetaRunnableTool.ts"],"names":[],"mappings":"OAAO,EACL,sBAAsB,EACtB,QAAQ,EACR,oBAAoB,EACpB,oBAAoB,EACpB,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC3B,+BAA+B,EAC/B,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC3B;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,0BAA0B,GAClC,QAAQ,GACR,sBAAsB,GACtB,oBAAoB,GACpB,oBAAoB,GACpB,2BAA2B,GAC3B,2BAA2B,GAC3B,2BAA2B,GAC3B,0BAA0B,GAC1B,0BAA0B,GAC1B,0BAA0B,GAC1B,0BAA0B,CAAC;AAI/B,MAAM,MAAM,gBAAgB,CAAC,KAAK,GAAG,GAAG,IAAI,0BAA0B,GAAG;IACvE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAClF,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,KAAK,CAAC;CACpC,CAAC"}

View File

@@ -0,0 +1,12 @@
import { BetaMemoryTool20250818, BetaTool, BetaToolBash20241022, BetaToolBash20250124, BetaToolComputerUse20241022, BetaToolComputerUse20250124, BetaToolComputerUse20251124, BetaToolResultContentBlockParam, BetaToolTextEditor20241022, BetaToolTextEditor20250124, BetaToolTextEditor20250429, BetaToolTextEditor20250728 } from "../../resources/beta.js";
export type Promisable<T> = T | Promise<T>;
/**
* Tool types that can be implemented on the client.
* Excludes server-side tools like code execution, web search, and MCP toolsets.
*/
export type BetaClientRunnableToolType = BetaTool | BetaMemoryTool20250818 | BetaToolBash20241022 | BetaToolBash20250124 | BetaToolComputerUse20241022 | BetaToolComputerUse20250124 | BetaToolComputerUse20251124 | BetaToolTextEditor20241022 | BetaToolTextEditor20250124 | BetaToolTextEditor20250429 | BetaToolTextEditor20250728;
export type BetaRunnableTool<Input = any> = BetaClientRunnableToolType & {
run: (args: Input) => Promisable<string | Array<BetaToolResultContentBlockParam>>;
parse: (content: unknown) => Input;
};
//# sourceMappingURL=BetaRunnableTool.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaRunnableTool.d.ts","sourceRoot":"","sources":["../../src/lib/tools/BetaRunnableTool.ts"],"names":[],"mappings":"OAAO,EACL,sBAAsB,EACtB,QAAQ,EACR,oBAAoB,EACpB,oBAAoB,EACpB,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC3B,+BAA+B,EAC/B,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC1B,0BAA0B,EAC3B;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,0BAA0B,GAClC,QAAQ,GACR,sBAAsB,GACtB,oBAAoB,GACpB,oBAAoB,GACpB,2BAA2B,GAC3B,2BAA2B,GAC3B,2BAA2B,GAC3B,0BAA0B,GAC1B,0BAA0B,GAC1B,0BAA0B,GAC1B,0BAA0B,CAAC;AAI/B,MAAM,MAAM,gBAAgB,CAAC,KAAK,GAAG,GAAG,IAAI,0BAA0B,GAAG;IACvE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;IAClF,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,KAAK,CAAC;CACpC,CAAC"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=BetaRunnableTool.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaRunnableTool.js","sourceRoot":"","sources":["../../src/lib/tools/BetaRunnableTool.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=BetaRunnableTool.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaRunnableTool.mjs","sourceRoot":"","sources":["../../src/lib/tools/BetaRunnableTool.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,136 @@
import { BetaRunnableTool } from "./BetaRunnableTool.mjs";
import { Anthropic } from "../../index.mjs";
import { BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams } from "../../resources/beta.mjs";
import { BetaMessageStream } from "../BetaMessageStream.mjs";
import { RequestOptions } from "../../internal/request-options.mjs";
import { CompactionControl } from "./CompactionControl.mjs";
/**
* 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 declare class BetaToolRunner<Stream extends boolean> {
#private;
private client;
constructor(client: Anthropic, params: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions);
[Symbol.asyncIterator](): AsyncIterator<Stream extends true ? BetaMessageStream : Stream extends false ? BetaMessage : BetaMessage | BetaMessageStream>;
/**
* Update the parameters for the next API call. This invalidates any cached tool responses.
*
* @param paramsOrMutator - Either new parameters or a function to mutate existing parameters
*
* @example
* // Direct parameter update
* runner.setMessagesParams({
* model: 'claude-haiku-4-5',
* max_tokens: 500,
* });
*
* @example
* // Using a mutator function
* runner.setMessagesParams((params) => ({
* ...params,
* max_tokens: 100,
* }));
*/
setMessagesParams(params: BetaToolRunnerParams): void;
setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void;
/**
* 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);
* }
*/
generateToolResponse(): Promise<Anthropic.Beta.Messages.BetaMessageParam | null>;
/**
* 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(): Promise<BetaMessage>;
/**
* 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);
*/
runUntilDone(): Promise<BetaMessage>;
/**
* 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(): Readonly<BetaToolRunnerParams>;
/**
* 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: BetaMessageParam[]): void;
/**
* Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone()
* This allows using `await runner` instead of `await runner.runUntilDone()`
*/
then<TResult1 = BetaMessage, TResult2 = never>(onfulfilled?: ((value: BetaMessage) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
}
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
/**
* Parameters for creating a ToolRunner, extending MessageCreateParams with runnable tools.
*/
export type BetaToolRunnerParams = Simplify<Omit<MessageCreateParams, 'tools'> & {
tools: (BetaToolUnion | BetaRunnableTool<any>)[];
/**
* Maximum number of iterations (API requests) to make in the tool execution loop.
* Each iteration consists of: assistant response → tool execution → tool results.
* When exceeded, the loop will terminate even if tools are still being requested.
*/
max_iterations?: number;
compactionControl?: CompactionControl;
}>;
export type BetaToolRunnerRequestOptions = Pick<RequestOptions, 'headers'>;
export {};
//# sourceMappingURL=BetaToolRunner.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaToolRunner.d.mts","sourceRoot":"","sources":["../../src/lib/tools/BetaToolRunner.ts"],"names":[],"mappings":"OAAO,EAAE,gBAAgB,EAAE;OAEpB,EAAE,SAAS,EAAE;OAEb,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAE;OACrE,EAAE,iBAAiB,EAAE;OACrB,EAAE,cAAc,EAAE;OAElB,EAAE,iBAAiB,EAAmD;AAoB7E;;;;;GAKG;AACH,qBAAa,cAAc,CAAC,MAAM,SAAS,OAAO;;IAsB9C,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS,EACzB,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,4BAA4B;IAwGjC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAC5C,MAAM,SAAS,IAAI,GAAG,iBAAiB,GACrC,MAAM,SAAS,KAAK,GAAG,WAAW,GAClC,WAAW,GAAG,iBAAiB,CAClC;IA2ED;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IACrD,iBAAiB,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,oBAAoB,KAAK,oBAAoB,GAAG,IAAI;IAc5F;;;;;;;;;;;OAWG;IACG,oBAAoB;IAgB1B;;;;;;;;;;;;;;;OAeG;IACH,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAI5B;;;;;;;;;;;;OAYG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAY1C;;;;;;;;;OASG;IACH,IAAI,MAAM,IAAI,QAAQ,CAAC,oBAAoB,CAAC,CAE3C;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,GAAG,QAAQ,EAAE,gBAAgB,EAAE;IAO5C;;;OAGG;IACH,IAAI,CAAC,QAAQ,GAAG,WAAW,EAAE,QAAQ,GAAG,KAAK,EAC3C,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,EAC3F,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,GAClF,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;CAGhC;AAkED,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CACzC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,KAAK,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IACjD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,CACF,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC"}

View File

@@ -0,0 +1,136 @@
import { BetaRunnableTool } from "./BetaRunnableTool.js";
import { Anthropic } from "../../index.js";
import { BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams } from "../../resources/beta.js";
import { BetaMessageStream } from "../BetaMessageStream.js";
import { RequestOptions } from "../../internal/request-options.js";
import { CompactionControl } from "./CompactionControl.js";
/**
* 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 declare class BetaToolRunner<Stream extends boolean> {
#private;
private client;
constructor(client: Anthropic, params: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions);
[Symbol.asyncIterator](): AsyncIterator<Stream extends true ? BetaMessageStream : Stream extends false ? BetaMessage : BetaMessage | BetaMessageStream>;
/**
* Update the parameters for the next API call. This invalidates any cached tool responses.
*
* @param paramsOrMutator - Either new parameters or a function to mutate existing parameters
*
* @example
* // Direct parameter update
* runner.setMessagesParams({
* model: 'claude-haiku-4-5',
* max_tokens: 500,
* });
*
* @example
* // Using a mutator function
* runner.setMessagesParams((params) => ({
* ...params,
* max_tokens: 100,
* }));
*/
setMessagesParams(params: BetaToolRunnerParams): void;
setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void;
/**
* 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);
* }
*/
generateToolResponse(): Promise<Anthropic.Beta.Messages.BetaMessageParam | null>;
/**
* 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(): Promise<BetaMessage>;
/**
* 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);
*/
runUntilDone(): Promise<BetaMessage>;
/**
* 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(): Readonly<BetaToolRunnerParams>;
/**
* 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: BetaMessageParam[]): void;
/**
* Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone()
* This allows using `await runner` instead of `await runner.runUntilDone()`
*/
then<TResult1 = BetaMessage, TResult2 = never>(onfulfilled?: ((value: BetaMessage) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
}
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
/**
* Parameters for creating a ToolRunner, extending MessageCreateParams with runnable tools.
*/
export type BetaToolRunnerParams = Simplify<Omit<MessageCreateParams, 'tools'> & {
tools: (BetaToolUnion | BetaRunnableTool<any>)[];
/**
* Maximum number of iterations (API requests) to make in the tool execution loop.
* Each iteration consists of: assistant response → tool execution → tool results.
* When exceeded, the loop will terminate even if tools are still being requested.
*/
max_iterations?: number;
compactionControl?: CompactionControl;
}>;
export type BetaToolRunnerRequestOptions = Pick<RequestOptions, 'headers'>;
export {};
//# sourceMappingURL=BetaToolRunner.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BetaToolRunner.d.ts","sourceRoot":"","sources":["../../src/lib/tools/BetaToolRunner.ts"],"names":[],"mappings":"OAAO,EAAE,gBAAgB,EAAE;OAEpB,EAAE,SAAS,EAAE;OAEb,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAE;OACrE,EAAE,iBAAiB,EAAE;OACrB,EAAE,cAAc,EAAE;OAElB,EAAE,iBAAiB,EAAmD;AAoB7E;;;;;GAKG;AACH,qBAAa,cAAc,CAAC,MAAM,SAAS,OAAO;;IAsB9C,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS,EACzB,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,4BAA4B;IAwGjC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAC5C,MAAM,SAAS,IAAI,GAAG,iBAAiB,GACrC,MAAM,SAAS,KAAK,GAAG,WAAW,GAClC,WAAW,GAAG,iBAAiB,CAClC;IA2ED;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IACrD,iBAAiB,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,oBAAoB,KAAK,oBAAoB,GAAG,IAAI;IAc5F;;;;;;;;;;;OAWG;IACG,oBAAoB;IAgB1B;;;;;;;;;;;;;;;OAeG;IACH,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAI5B;;;;;;;;;;;;OAYG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAY1C;;;;;;;;;OASG;IACH,IAAI,MAAM,IAAI,QAAQ,CAAC,oBAAoB,CAAC,CAE3C;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,GAAG,QAAQ,EAAE,gBAAgB,EAAE;IAO5C;;;OAGG;IACH,IAAI,CAAC,QAAQ,GAAG,WAAW,EAAE,QAAQ,GAAG,KAAK,EAC3C,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,EAC3F,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,GAClF,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;CAGhC;AAkED,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CACzC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,KAAK,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IACjD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,CACF,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC"}

View File

@@ -0,0 +1,376 @@
"use strict";
var _BetaToolRunner_instances, _BetaToolRunner_consumed, _BetaToolRunner_mutated, _BetaToolRunner_state, _BetaToolRunner_options, _BetaToolRunner_message, _BetaToolRunner_toolResponse, _BetaToolRunner_completion, _BetaToolRunner_iterationCount, _BetaToolRunner_checkAndCompact, _BetaToolRunner_generateToolResponse;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BetaToolRunner = void 0;
const tslib_1 = require("../../internal/tslib.js");
const ToolError_1 = require("./ToolError.js");
const error_1 = require("../../core/error.js");
const headers_1 = require("../../internal/headers.js");
const CompactionControl_1 = require("./CompactionControl.js");
const stainless_helper_header_1 = require("../stainless-helper-header.js");
/**
* 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.
*/
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);
tslib_1.__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 = (0, stainless_helper_header_1.collectStainlessHelpers)(params.tools, params.messages);
const helperValue = ['BetaToolRunner', ...helpers].join(', ');
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_options, {
...options,
headers: (0, headers_1.buildHeaders)([{ 'x-stainless-helper': helperValue }, options?.headers]),
}, "f");
tslib_1.__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 = tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.compactionControl;
if (!compactionControl || !compactionControl.enabled) {
return false;
}
let tokensUsed = 0;
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f") !== undefined) {
try {
const message = await tslib_1.__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 ?? CompactionControl_1.DEFAULT_TOKEN_THRESHOLD;
if (tokensUsed < threshold) {
return false;
}
const model = compactionControl.model ?? tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.model;
const summaryPrompt = compactionControl.summaryPrompt ?? CompactionControl_1.DEFAULT_SUMMARY_PROMPT;
const messages = tslib_1.__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: tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_tokens,
}, {
headers: { 'x-stainless-helper': 'compaction' },
});
if (response.content[0]?.type !== 'text') {
throw new error_1.AnthropicError('Expected text response for compaction');
}
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages = [
{
role: 'user',
content: response.content,
},
];
return true;
}, Symbol.asyncIterator)]() {
var _a;
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_consumed, "f")) {
throw new error_1.AnthropicError('Cannot iterate over a consumed stream');
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_consumed, true, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
try {
while (true) {
let stream;
try {
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations &&
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f") >= tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations) {
break;
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_mutated, false, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_iterationCount, (_a = tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f"), _a++, _a), "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_message, undefined, "f");
const { max_iterations, compactionControl, ...params } = tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
if (params.stream) {
stream = this.client.beta.messages.stream({ ...params }, tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_options, "f"));
tslib_1.__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
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f").catch(() => { });
yield stream;
}
else {
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_message, this.client.beta.messages.create({ ...params, stream: false }, tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_options, "f")), "f");
yield tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f");
}
const isCompacted = await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_checkAndCompact).call(this);
if (!isCompacted) {
if (!tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
const { role, content } = await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f");
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push({ role, content });
}
const toolMessage = await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_generateToolResponse).call(this, tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.at(-1));
if (toolMessage) {
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push(toolMessage);
}
else if (!tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
break;
}
}
}
finally {
if (stream) {
stream.abort();
}
}
}
if (!tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f")) {
throw new error_1.AnthropicError('ToolRunner concluded without a message from the server');
}
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").resolve(await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f"));
}
catch (error) {
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_consumed, false, "f");
// Silence unhandled promise errors
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").promise.catch(() => { });
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").reject(error);
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
throw error;
}
}
setMessagesParams(paramsOrMutator) {
if (typeof paramsOrMutator === 'function') {
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator(tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params);
}
else {
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator;
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
// Invalidate cached tool response since parameters changed
tslib_1.__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 tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f")) ?? this.params.messages.at(-1);
if (!message) {
return null;
}
return tslib_1.__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 tslib_1.__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 (!tslib_1.__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 tslib_1.__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);
}
}
exports.BetaToolRunner = BetaToolRunner;
_BetaToolRunner_generateToolResponse = async function _BetaToolRunner_generateToolResponse(lastMessage) {
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f") !== undefined) {
return tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f");
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, generateToolResponse(tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params, lastMessage), "f");
return tslib_1.__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_1.ToolError ?
error.content
: `Error: ${error instanceof Error ? error.message : String(error)}`,
is_error: true,
};
}
}));
return {
role: 'user',
content: toolResults,
};
}
//# sourceMappingURL=BetaToolRunner.js.map

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
import { Model } from "../../resources.mjs";
export declare const DEFAULT_TOKEN_THRESHOLD = 100000;
export declare 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:\n1. Task Overview\nThe user's core request and success criteria\nAny clarifications or constraints they specified\n2. Current State\nWhat has been completed so far\nFiles created, modified, or analyzed (with paths if relevant)\nKey outputs or artifacts produced\n3. Important Discoveries\nTechnical constraints or requirements uncovered\nDecisions made and their rationale\nErrors encountered and how they were resolved\nWhat approaches were tried that didn't work (and why)\n4. Next Steps\nSpecific actions needed to complete the task\nAny blockers or open questions to resolve\nPriority order if multiple steps remain\n5. Context to Preserve\nUser preferences or style requirements\nDomain-specific details that aren't obvious\nAny promises made to the user\nBe concise but complete\u2014err 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.\nWrap your summary in <summary></summary> tags.";
export interface CompactionControl {
/**
* The context token threshold at which to trigger compaction.
*
* When the cumulative token count (input + output) across all messages exceeds this threshold,
* the message history will be automatically summarized and compressed.
*
* @default 100000
*/
contextTokenThreshold?: number;
/**
* The model to use for generating the compaction summary.
* If not specified, defaults to the same model used for the tool runner.
*/
model?: Model;
/**
* The prompt used to instruct the model on how to generate the summary.
*/
summaryPrompt?: string;
enabled: boolean;
}
//# sourceMappingURL=CompactionControl.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CompactionControl.d.mts","sourceRoot":"","sources":["../../src/lib/tools/CompactionControl.ts"],"names":[],"mappings":"OAAO,EAAE,KAAK,EAAE;AAEhB,eAAO,MAAM,uBAAuB,SAAU,CAAC;AAE/C,eAAO,MAAM,sBAAsB,20CAsBY,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,EAAE,OAAO,CAAC;CAClB"}

View File

@@ -0,0 +1,25 @@
import { Model } from "../../resources.js";
export declare const DEFAULT_TOKEN_THRESHOLD = 100000;
export declare 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:\n1. Task Overview\nThe user's core request and success criteria\nAny clarifications or constraints they specified\n2. Current State\nWhat has been completed so far\nFiles created, modified, or analyzed (with paths if relevant)\nKey outputs or artifacts produced\n3. Important Discoveries\nTechnical constraints or requirements uncovered\nDecisions made and their rationale\nErrors encountered and how they were resolved\nWhat approaches were tried that didn't work (and why)\n4. Next Steps\nSpecific actions needed to complete the task\nAny blockers or open questions to resolve\nPriority order if multiple steps remain\n5. Context to Preserve\nUser preferences or style requirements\nDomain-specific details that aren't obvious\nAny promises made to the user\nBe concise but complete\u2014err 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.\nWrap your summary in <summary></summary> tags.";
export interface CompactionControl {
/**
* The context token threshold at which to trigger compaction.
*
* When the cumulative token count (input + output) across all messages exceeds this threshold,
* the message history will be automatically summarized and compressed.
*
* @default 100000
*/
contextTokenThreshold?: number;
/**
* The model to use for generating the compaction summary.
* If not specified, defaults to the same model used for the tool runner.
*/
model?: Model;
/**
* The prompt used to instruct the model on how to generate the summary.
*/
summaryPrompt?: string;
enabled: boolean;
}
//# sourceMappingURL=CompactionControl.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CompactionControl.d.ts","sourceRoot":"","sources":["../../src/lib/tools/CompactionControl.ts"],"names":[],"mappings":"OAAO,EAAE,KAAK,EAAE;AAEhB,eAAO,MAAM,uBAAuB,SAAU,CAAC;AAE/C,eAAO,MAAM,sBAAsB,20CAsBY,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,EAAE,OAAO,CAAC;CAClB"}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_SUMMARY_PROMPT = exports.DEFAULT_TOKEN_THRESHOLD = void 0;
exports.DEFAULT_TOKEN_THRESHOLD = 100000;
exports.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.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CompactionControl.js","sourceRoot":"","sources":["../../src/lib/tools/CompactionControl.ts"],"names":[],"mappings":";;;AAEa,QAAA,uBAAuB,GAAG,MAAO,CAAC;AAElC,QAAA,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;+CAsBS,CAAC"}

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 @@
{"version":3,"file":"CompactionControl.mjs","sourceRoot":"","sources":["../../src/lib/tools/CompactionControl.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAO,CAAC;AAE/C,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;+CAsBS,CAAC"}

View File

@@ -0,0 +1,33 @@
import { BetaToolResultContentBlockParam } from "../../resources/beta.mjs";
/**
* 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 declare class ToolError extends Error {
/**
* The content to return as the tool result. This will be sent back to the model
* with `is_error: true`.
*/
readonly content: string | Array<BetaToolResultContentBlockParam>;
constructor(content: string | Array<BetaToolResultContentBlockParam>);
}
//# sourceMappingURL=ToolError.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ToolError.d.mts","sourceRoot":"","sources":["../../src/lib/tools/ToolError.ts"],"names":[],"mappings":"OAAO,EAAE,+BAA+B,EAAE;AAE1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,+BAA+B,CAAC,CAAC;gBAEtD,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,+BAA+B,CAAC;CAcrE"}

View File

@@ -0,0 +1,33 @@
import { BetaToolResultContentBlockParam } from "../../resources/beta.js";
/**
* 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 declare class ToolError extends Error {
/**
* The content to return as the tool result. This will be sent back to the model
* with `is_error: true`.
*/
readonly content: string | Array<BetaToolResultContentBlockParam>;
constructor(content: string | Array<BetaToolResultContentBlockParam>);
}
//# sourceMappingURL=ToolError.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ToolError.d.ts","sourceRoot":"","sources":["../../src/lib/tools/ToolError.ts"],"names":[],"mappings":"OAAO,EAAE,+BAA+B,EAAE;AAE1C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,+BAA+B,CAAC,CAAC;gBAEtD,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,+BAA+B,CAAC;CAcrE"}

View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToolError = void 0;
/**
* 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';
* },
* };
* ```
*/
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;
}
}
exports.ToolError = ToolError;
//# sourceMappingURL=ToolError.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ToolError.js","sourceRoot":"","sources":["../../src/lib/tools/ToolError.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAa,SAAU,SAAQ,KAAK;IAOlC,YAAY,OAAwD;QAClE,MAAM,OAAO,GACX,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CACtC,OAAO;aACJ,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACb,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,KAAK,CAAC,IAAI,CAAC;YAC7C,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC;QAC3B,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,CACb,CAAC;QACJ,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AArBD,8BAqBC"}

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

View File

@@ -0,0 +1 @@
{"version":3,"file":"ToolError.mjs","sourceRoot":"","sources":["../../src/lib/tools/ToolError.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAOlC,YAAY,OAAwD;QAClE,MAAM,OAAO,GACX,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CACtC,OAAO;aACJ,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACb,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,KAAK,CAAC,IAAI,CAAC;YAC7C,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,CAAC;QAC3B,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,CACb,CAAC;QACJ,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF"}

View File

@@ -0,0 +1,132 @@
import { BetaRunnableTool } from "./BetaRunnableTool.mjs";
import { Anthropic } from "../../index.mjs";
import { BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams } from "../../resources/beta.mjs";
import { BetaMessageStream } from "../BetaMessageStream.mjs";
/**
* 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 declare class BetaToolRunner<Stream extends boolean> {
#private;
private client;
constructor(client: Anthropic, params: BetaToolRunnerParams);
[Symbol.asyncIterator](): AsyncIterator<Stream extends true ? BetaMessageStream : Stream extends false ? BetaMessage : BetaMessage | BetaMessageStream>;
/**
* Update the parameters for the next API call. This invalidates any cached tool responses.
*
* @param paramsOrMutator - Either new parameters or a function to mutate existing parameters
*
* @example
* // Direct parameter update
* runner.setMessagesParams({
* model: 'claude-haiku-4-5',
* max_tokens: 500,
* });
*
* @example
* // Using a mutator function
* runner.setMessagesParams((params) => ({
* ...params,
* max_tokens: 100,
* }));
*/
setMessagesParams(params: BetaToolRunnerParams): void;
setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void;
/**
* 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);
* }
*/
generateToolResponse(): Promise<Anthropic.Beta.Messages.BetaMessageParam | null>;
/**
* 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(): Promise<BetaMessage>;
/**
* 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);
*/
runUntilDone(): Promise<BetaMessage>;
/**
* 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(): Readonly<BetaToolRunnerParams>;
/**
* 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: BetaMessageParam[]): void;
/**
* Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone()
* This allows using `await runner` instead of `await runner.runUntilDone()`
*/
then<TResult1 = BetaMessage, TResult2 = never>(onfulfilled?: ((value: BetaMessage) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
}
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
/**
* Parameters for creating a ToolRunner, extending MessageCreateParams with runnable tools.
*/
export type BetaToolRunnerParams = Simplify<Omit<MessageCreateParams, 'tools'> & {
tools: (BetaToolUnion | BetaRunnableTool<any>)[];
/**
* Maximum number of iterations (API requests) to make in the tool execution loop.
* Each iteration consists of: assistant response → tool execution → tool results.
* When exceeded, the loop will terminate even if tools are still being requested.
*/
max_iterations?: number;
}>;
export {};
//# sourceMappingURL=ToolRunner.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ToolRunner.d.mts","sourceRoot":"","sources":["../../src/lib/tools/ToolRunner.ts"],"names":[],"mappings":"OAAO,EAAE,gBAAgB,EAAE;OAEpB,EAAE,SAAS,EAAE;OAEb,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAE;OACrE,EAAE,iBAAiB,EAAE;AAmB5B;;;;;GAKG;AACH,qBAAa,cAAc,CAAC,MAAM,SAAS,OAAO;;IAqB9C,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS,EACzB,MAAM,EAAE,oBAAoB;IAevB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAC5C,MAAM,SAAS,IAAI,GAAG,iBAAiB,GACrC,MAAM,SAAS,KAAK,GAAG,WAAW,GAClC,WAAW,GAAG,iBAAiB,CAClC;IAyED;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IACrD,iBAAiB,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,oBAAoB,KAAK,oBAAoB,GAAG,IAAI;IAc5F;;;;;;;;;;;OAWG;IACG,oBAAoB;IAgB1B;;;;;;;;;;;;;;;OAeG;IACH,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAI5B;;;;;;;;;;;;OAYG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAY1C;;;;;;;;;OASG;IACH,IAAI,MAAM,IAAI,QAAQ,CAAC,oBAAoB,CAAC,CAE3C;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,GAAG,QAAQ,EAAE,gBAAgB,EAAE;IAO5C;;;OAGG;IACH,IAAI,CAAC,QAAQ,GAAG,WAAW,EAAE,QAAQ,GAAG,KAAK,EAC3C,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,EAC3F,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,GAClF,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;CAGhC;AAkED,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CACzC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,KAAK,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IACjD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CACF,CAAC"}

View File

@@ -0,0 +1,132 @@
import { BetaRunnableTool } from "./BetaRunnableTool.js";
import { Anthropic } from "../../index.js";
import { BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams } from "../../resources/beta.js";
import { BetaMessageStream } from "../BetaMessageStream.js";
/**
* 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 declare class BetaToolRunner<Stream extends boolean> {
#private;
private client;
constructor(client: Anthropic, params: BetaToolRunnerParams);
[Symbol.asyncIterator](): AsyncIterator<Stream extends true ? BetaMessageStream : Stream extends false ? BetaMessage : BetaMessage | BetaMessageStream>;
/**
* Update the parameters for the next API call. This invalidates any cached tool responses.
*
* @param paramsOrMutator - Either new parameters or a function to mutate existing parameters
*
* @example
* // Direct parameter update
* runner.setMessagesParams({
* model: 'claude-haiku-4-5',
* max_tokens: 500,
* });
*
* @example
* // Using a mutator function
* runner.setMessagesParams((params) => ({
* ...params,
* max_tokens: 100,
* }));
*/
setMessagesParams(params: BetaToolRunnerParams): void;
setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void;
/**
* 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);
* }
*/
generateToolResponse(): Promise<Anthropic.Beta.Messages.BetaMessageParam | null>;
/**
* 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(): Promise<BetaMessage>;
/**
* 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);
*/
runUntilDone(): Promise<BetaMessage>;
/**
* 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(): Readonly<BetaToolRunnerParams>;
/**
* 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: BetaMessageParam[]): void;
/**
* Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone()
* This allows using `await runner` instead of `await runner.runUntilDone()`
*/
then<TResult1 = BetaMessage, TResult2 = never>(onfulfilled?: ((value: BetaMessage) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
}
type Simplify<T> = {
[KeyType in keyof T]: T[KeyType];
} & {};
/**
* Parameters for creating a ToolRunner, extending MessageCreateParams with runnable tools.
*/
export type BetaToolRunnerParams = Simplify<Omit<MessageCreateParams, 'tools'> & {
tools: (BetaToolUnion | BetaRunnableTool<any>)[];
/**
* Maximum number of iterations (API requests) to make in the tool execution loop.
* Each iteration consists of: assistant response → tool execution → tool results.
* When exceeded, the loop will terminate even if tools are still being requested.
*/
max_iterations?: number;
}>;
export {};
//# sourceMappingURL=ToolRunner.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ToolRunner.d.ts","sourceRoot":"","sources":["../../src/lib/tools/ToolRunner.ts"],"names":[],"mappings":"OAAO,EAAE,gBAAgB,EAAE;OAEpB,EAAE,SAAS,EAAE;OAEb,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAE;OACrE,EAAE,iBAAiB,EAAE;AAmB5B;;;;;GAKG;AACH,qBAAa,cAAc,CAAC,MAAM,SAAS,OAAO;;IAqB9C,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS,EACzB,MAAM,EAAE,oBAAoB;IAevB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAC5C,MAAM,SAAS,IAAI,GAAG,iBAAiB,GACrC,MAAM,SAAS,KAAK,GAAG,WAAW,GAClC,WAAW,GAAG,iBAAiB,CAClC;IAyED;;;;;;;;;;;;;;;;;;OAkBG;IACH,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IACrD,iBAAiB,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE,oBAAoB,KAAK,oBAAoB,GAAG,IAAI;IAc5F;;;;;;;;;;;OAWG;IACG,oBAAoB;IAgB1B;;;;;;;;;;;;;;;OAeG;IACH,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAI5B;;;;;;;;;;;;OAYG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAY1C;;;;;;;;;OASG;IACH,IAAI,MAAM,IAAI,QAAQ,CAAC,oBAAoB,CAAC,CAE3C;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,GAAG,QAAQ,EAAE,gBAAgB,EAAE;IAO5C;;;OAGG;IACH,IAAI,CAAC,QAAQ,GAAG,WAAW,EAAE,QAAQ,GAAG,KAAK,EAC3C,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,EAC3F,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,KAAK,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,GAClF,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;CAGhC;AAkED,KAAK,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CACzC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,GAAG;IACnC,KAAK,EAAE,CAAC,aAAa,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IACjD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CACF,CAAC"}

View File

@@ -0,0 +1,294 @@
"use strict";
var _BetaToolRunner_instances, _BetaToolRunner_consumed, _BetaToolRunner_mutated, _BetaToolRunner_state, _BetaToolRunner_message, _BetaToolRunner_toolResponse, _BetaToolRunner_completion, _BetaToolRunner_iterationCount, _BetaToolRunner_generateToolResponse;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BetaToolRunner = void 0;
const tslib_1 = require("../../internal/tslib.js");
const ToolError_1 = require("./ToolError.js");
const error_1 = require("../../core/error.js");
/**
* 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.
*/
class BetaToolRunner {
constructor(client, params) {
_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);
/** 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);
tslib_1.__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");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
}
async *[(_BetaToolRunner_consumed = new WeakMap(), _BetaToolRunner_mutated = new WeakMap(), _BetaToolRunner_state = new WeakMap(), _BetaToolRunner_message = new WeakMap(), _BetaToolRunner_toolResponse = new WeakMap(), _BetaToolRunner_completion = new WeakMap(), _BetaToolRunner_iterationCount = new WeakMap(), _BetaToolRunner_instances = new WeakSet(), Symbol.asyncIterator)]() {
var _a;
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_consumed, "f")) {
throw new error_1.AnthropicError('Cannot iterate over a consumed stream');
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_consumed, true, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
try {
while (true) {
let stream;
try {
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations &&
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f") >= tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations) {
break;
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_mutated, false, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_message, undefined, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_iterationCount, (_a = tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f"), _a++, _a), "f");
const { max_iterations, ...params } = tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
if (params.stream) {
stream = this.client.beta.messages.stream({ ...params });
tslib_1.__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
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f").catch(() => { });
yield stream;
}
else {
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_message, this.client.beta.messages.create({ ...params, stream: false }), "f");
yield tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f");
}
if (!tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
const { role, content } = await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f");
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push({ role, content });
}
const toolMessage = await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_generateToolResponse).call(this, tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.at(-1));
if (toolMessage) {
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push(toolMessage);
}
if (!toolMessage && !tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
break;
}
}
finally {
if (stream) {
stream.abort();
}
}
}
if (!tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f")) {
throw new error_1.AnthropicError('ToolRunner concluded without a message from the server');
}
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").resolve(await tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f"));
}
catch (error) {
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_consumed, false, "f");
// Silence unhandled promise errors
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").promise.catch(() => { });
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").reject(error);
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
throw error;
}
}
setMessagesParams(paramsOrMutator) {
if (typeof paramsOrMutator === 'function') {
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator(tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params);
}
else {
tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator;
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
// Invalidate cached tool response since parameters changed
tslib_1.__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 tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_message, "f")) ?? this.params.messages.at(-1);
if (!message) {
return null;
}
return tslib_1.__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 tslib_1.__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 (!tslib_1.__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 tslib_1.__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);
}
}
exports.BetaToolRunner = BetaToolRunner;
_BetaToolRunner_generateToolResponse = async function _BetaToolRunner_generateToolResponse(lastMessage) {
if (tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f") !== undefined) {
return tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f");
}
tslib_1.__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, generateToolResponse(tslib_1.__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params, lastMessage), "f");
return tslib_1.__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_1.ToolError ?
error.content
: `Error: ${error instanceof Error ? error.message : String(error)}`,
is_error: true,
};
}
}));
return {
role: 'user',
content: toolResults,
};
}
//# sourceMappingURL=ToolRunner.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,290 @@
var _BetaToolRunner_instances, _BetaToolRunner_consumed, _BetaToolRunner_mutated, _BetaToolRunner_state, _BetaToolRunner_message, _BetaToolRunner_toolResponse, _BetaToolRunner_completion, _BetaToolRunner_iterationCount, _BetaToolRunner_generateToolResponse;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../../internal/tslib.mjs";
import { ToolError } from "./ToolError.mjs";
import { AnthropicError } from "../../core/error.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) {
_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);
/** 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");
__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
}
async *[(_BetaToolRunner_consumed = new WeakMap(), _BetaToolRunner_mutated = new WeakMap(), _BetaToolRunner_state = new WeakMap(), _BetaToolRunner_message = new WeakMap(), _BetaToolRunner_toolResponse = new WeakMap(), _BetaToolRunner_completion = new WeakMap(), _BetaToolRunner_iterationCount = new WeakMap(), _BetaToolRunner_instances = new WeakSet(), 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_message, undefined, "f");
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
__classPrivateFieldSet(this, _BetaToolRunner_iterationCount, (_a = __classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f"), _a++, _a), "f");
const { max_iterations, ...params } = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
if (params.stream) {
stream = this.client.beta.messages.stream({ ...params });
__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 }), "f");
yield __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
}
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);
}
if (!toolMessage && !__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=ToolRunner.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
export type JSONSchema = Record<string, any>;
export declare function transformJSONSchema(jsonSchema: JSONSchema): JSONSchema;
//# sourceMappingURL=transform-json-schema.d.mts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"transform-json-schema.d.mts","sourceRoot":"","sources":["../src/lib/transform-json-schema.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAM7C,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAGtE"}

View File

@@ -0,0 +1,3 @@
export type JSONSchema = Record<string, any>;
export declare function transformJSONSchema(jsonSchema: JSONSchema): JSONSchema;
//# sourceMappingURL=transform-json-schema.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"transform-json-schema.d.ts","sourceRoot":"","sources":["../src/lib/transform-json-schema.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAM7C,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAGtE"}

View File

@@ -0,0 +1,114 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformJSONSchema = transformJSONSchema;
const utils_1 = require("../internal/utils.js");
// Supported string formats
const SUPPORTED_STRING_FORMATS = new Set([
'date-time',
'time',
'date',
'duration',
'email',
'hostname',
'uri',
'ipv4',
'ipv6',
'uuid',
]);
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
function transformJSONSchema(jsonSchema) {
const workingCopy = deepClone(jsonSchema);
return _transformJSONSchema(workingCopy);
}
function _transformJSONSchema(jsonSchema) {
const strictSchema = {};
const ref = (0, utils_1.pop)(jsonSchema, '$ref');
if (ref !== undefined) {
strictSchema['$ref'] = ref;
return strictSchema;
}
const defs = (0, utils_1.pop)(jsonSchema, '$defs');
if (defs !== undefined) {
const strictDefs = {};
strictSchema['$defs'] = strictDefs;
for (const [name, defSchema] of Object.entries(defs)) {
strictDefs[name] = _transformJSONSchema(defSchema);
}
}
const type = (0, utils_1.pop)(jsonSchema, 'type');
const anyOf = (0, utils_1.pop)(jsonSchema, 'anyOf');
const oneOf = (0, utils_1.pop)(jsonSchema, 'oneOf');
const allOf = (0, utils_1.pop)(jsonSchema, 'allOf');
if (Array.isArray(anyOf)) {
strictSchema['anyOf'] = anyOf.map((variant) => _transformJSONSchema(variant));
}
else if (Array.isArray(oneOf)) {
strictSchema['anyOf'] = oneOf.map((variant) => _transformJSONSchema(variant));
}
else if (Array.isArray(allOf)) {
strictSchema['allOf'] = allOf.map((entry) => _transformJSONSchema(entry));
}
else {
if (type === undefined) {
throw new Error('JSON schema must have a type defined if anyOf/oneOf/allOf are not used');
}
strictSchema['type'] = type;
}
const description = (0, utils_1.pop)(jsonSchema, 'description');
if (description !== undefined) {
strictSchema['description'] = description;
}
const title = (0, utils_1.pop)(jsonSchema, 'title');
if (title !== undefined) {
strictSchema['title'] = title;
}
if (type === 'object') {
const properties = (0, utils_1.pop)(jsonSchema, 'properties') || {};
strictSchema['properties'] = Object.fromEntries(Object.entries(properties).map(([key, propSchema]) => [
key,
_transformJSONSchema(propSchema),
]));
(0, utils_1.pop)(jsonSchema, 'additionalProperties');
strictSchema['additionalProperties'] = false;
const required = (0, utils_1.pop)(jsonSchema, 'required');
if (required !== undefined) {
strictSchema['required'] = required;
}
}
else if (type === 'string') {
const format = (0, utils_1.pop)(jsonSchema, 'format');
if (format !== undefined && SUPPORTED_STRING_FORMATS.has(format)) {
strictSchema['format'] = format;
}
else if (format !== undefined) {
jsonSchema['format'] = format;
}
}
else if (type === 'array') {
const items = (0, utils_1.pop)(jsonSchema, 'items');
if (items !== undefined) {
strictSchema['items'] = _transformJSONSchema(items);
}
const minItems = (0, utils_1.pop)(jsonSchema, 'minItems');
if (minItems !== undefined && (minItems === 0 || minItems === 1)) {
strictSchema['minItems'] = minItems;
}
else if (minItems !== undefined) {
jsonSchema['minItems'] = minItems;
}
}
if (Object.keys(jsonSchema).length > 0) {
const existingDescription = strictSchema['description'];
strictSchema['description'] =
(existingDescription ? existingDescription + '\n\n' : '') +
'{' +
Object.entries(jsonSchema)
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
.join(', ') +
'}';
}
return strictSchema;
}
//# sourceMappingURL=transform-json-schema.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"transform-json-schema.js","sourceRoot":"","sources":["../src/lib/transform-json-schema.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,111 @@
import { pop } from "../internal/utils.mjs";
// Supported string formats
const SUPPORTED_STRING_FORMATS = new Set([
'date-time',
'time',
'date',
'duration',
'email',
'hostname',
'uri',
'ipv4',
'ipv6',
'uuid',
]);
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
export function transformJSONSchema(jsonSchema) {
const workingCopy = deepClone(jsonSchema);
return _transformJSONSchema(workingCopy);
}
function _transformJSONSchema(jsonSchema) {
const strictSchema = {};
const ref = pop(jsonSchema, '$ref');
if (ref !== undefined) {
strictSchema['$ref'] = ref;
return strictSchema;
}
const defs = pop(jsonSchema, '$defs');
if (defs !== undefined) {
const strictDefs = {};
strictSchema['$defs'] = strictDefs;
for (const [name, defSchema] of Object.entries(defs)) {
strictDefs[name] = _transformJSONSchema(defSchema);
}
}
const type = pop(jsonSchema, 'type');
const anyOf = pop(jsonSchema, 'anyOf');
const oneOf = pop(jsonSchema, 'oneOf');
const allOf = pop(jsonSchema, 'allOf');
if (Array.isArray(anyOf)) {
strictSchema['anyOf'] = anyOf.map((variant) => _transformJSONSchema(variant));
}
else if (Array.isArray(oneOf)) {
strictSchema['anyOf'] = oneOf.map((variant) => _transformJSONSchema(variant));
}
else if (Array.isArray(allOf)) {
strictSchema['allOf'] = allOf.map((entry) => _transformJSONSchema(entry));
}
else {
if (type === undefined) {
throw new Error('JSON schema must have a type defined if anyOf/oneOf/allOf are not used');
}
strictSchema['type'] = type;
}
const description = pop(jsonSchema, 'description');
if (description !== undefined) {
strictSchema['description'] = description;
}
const title = pop(jsonSchema, 'title');
if (title !== undefined) {
strictSchema['title'] = title;
}
if (type === 'object') {
const properties = pop(jsonSchema, 'properties') || {};
strictSchema['properties'] = Object.fromEntries(Object.entries(properties).map(([key, propSchema]) => [
key,
_transformJSONSchema(propSchema),
]));
pop(jsonSchema, 'additionalProperties');
strictSchema['additionalProperties'] = false;
const required = pop(jsonSchema, 'required');
if (required !== undefined) {
strictSchema['required'] = required;
}
}
else if (type === 'string') {
const format = pop(jsonSchema, 'format');
if (format !== undefined && SUPPORTED_STRING_FORMATS.has(format)) {
strictSchema['format'] = format;
}
else if (format !== undefined) {
jsonSchema['format'] = format;
}
}
else if (type === 'array') {
const items = pop(jsonSchema, 'items');
if (items !== undefined) {
strictSchema['items'] = _transformJSONSchema(items);
}
const minItems = pop(jsonSchema, 'minItems');
if (minItems !== undefined && (minItems === 0 || minItems === 1)) {
strictSchema['minItems'] = minItems;
}
else if (minItems !== undefined) {
jsonSchema['minItems'] = minItems;
}
}
if (Object.keys(jsonSchema).length > 0) {
const existingDescription = strictSchema['description'];
strictSchema['description'] =
(existingDescription ? existingDescription + '\n\n' : '') +
'{' +
Object.entries(jsonSchema)
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
.join(', ') +
'}';
}
return strictSchema;
}
//# sourceMappingURL=transform-json-schema.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"transform-json-schema.mjs","sourceRoot":"","sources":["../src/lib/transform-json-schema.ts"],"names":[],"mappings":"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"}