@anthropic-ai/sdk
Version:
The official TypeScript library for the Anthropic API
144 lines • 6.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setAnthropicSpanAttributes = setAnthropicSpanAttributes;
exports.messagesCreateSpanSettings = messagesCreateSpanSettings;
exports.recordMessagesCreateRequest = recordMessagesCreateRequest;
exports.recordMessagesCreateResponse = recordMessagesCreateResponse;
exports.recordCountTokensResponse = recordCountTokensResponse;
exports.recordSessionsCreateResponse = recordSessionsCreateResponse;
const error_1 = require("../../../core/error.js");
const streaming_1 = require("../../../core/streaming.js");
const headers_1 = require("../../../internal/headers.js");
const log_1 = require("../../../internal/utils/log.js");
const attributes_1 = require("./attributes.js");
const content_1 = require("./content.js");
const response_1 = require("./response.js");
/**
* Sets the IDs in the response headers of `result` on `span`, the call span of any API call.
* A failure to record, here and below, is logged and never fails the API call.
*/
function setAnthropicSpanAttributes(client, span, result) {
if (!span.isRecording()) {
return;
}
try {
const error = result.status === 'error' ? result.error : undefined;
const headers = result.response?.headers ?? (error instanceof error_1.APIError ? error.headers : undefined);
for (const [attribute, header] of attributes_1.RESPONSE_HEADER_ATTRIBUTES) {
const value = headers?.get(header);
if (value) {
span.setAttribute(attribute, value);
}
}
}
catch (problem) {
(0, log_1.loggerFor)(client).debug('could not record the API call on its span', problem);
}
}
/**
* The attributes that a `messages.create` span starts with, from the request's `body` and
* `headers`. A sampler sees only the attributes that a span starts with.
*/
function messagesCreateSpanSettings(client, body, headers) {
const attributes = {
[attributes_1.ATTR_GEN_AI_OPERATION_NAME]: attributes_1.GEN_AI_OPERATION_NAME_VALUE_CHAT,
[attributes_1.ATTR_GEN_AI_REQUEST_MODEL]: body.model,
};
try {
// The client sends its default headers with the method's, which replace those of the same name.
const betas = ((0, headers_1.buildHeaders)([client._options.defaultHeaders, headers]).values.get('anthropic-beta') ?? '')
.split(',')
.map((beta) => beta.trim())
.filter(Boolean);
if (betas.length) {
attributes[attributes_1.ATTR_ANTHROPIC_BETA] = betas;
}
attributes[attributes_1.ATTR_GEN_AI_REQUEST_MAX_TOKENS] = body.max_tokens;
if (body.stream === true) {
attributes[attributes_1.ATTR_GEN_AI_REQUEST_STREAM] = true;
}
// The beta method has already moved a deprecated `output_format` here.
if (body.output_config?.format?.type === 'json_schema') {
attributes[attributes_1.ATTR_GEN_AI_OUTPUT_TYPE] = attributes_1.GEN_AI_OUTPUT_TYPE_VALUE_JSON;
}
const effort = body.output_config?.effort;
if (effort != null) {
attributes[attributes_1.ATTR_GEN_AI_REQUEST_REASONING_LEVEL] = effort;
}
if (body.service_tier != null) {
attributes[attributes_1.ATTR_ANTHROPIC_REQUEST_SERVICE_TIER] = body.service_tier;
}
const thinking = body.thinking;
if (thinking != null) {
attributes[attributes_1.ATTR_ANTHROPIC_THINKING_TYPE] = thinking.type;
}
if (thinking?.type === 'enabled') {
attributes[attributes_1.ATTR_ANTHROPIC_THINKING_BUDGET_TOKENS] = thinking.budget_tokens;
}
}
catch (problem) {
(0, log_1.loggerFor)(client).debug('could not record the request on its span', problem);
}
return { route: '/v1/messages', attributes };
}
/**
* In content mode, sets the request's content on `call`. The span does not start with it, because
* the size limit counts it together with the response's content. Returns `call`.
*/
function recordMessagesCreateRequest(client, call, body) {
if (!call?.span.isRecording()) {
return call;
}
try {
const { contentMode, maxContentBytes } = client.openTelemetry.traces;
if (contentMode === 'content') {
(0, content_1.setMessageContentAttributes)(call, body, undefined, maxContentBytes);
}
}
catch (problem) {
(0, log_1.loggerFor)(client).debug('could not record the request on its span', problem);
}
return call;
}
/**
* Sets the response attributes and, in content mode, the response's content on `call`. A streamed
* response is recorded as the application reads it (`endAnthropicApiCallSpanWhenStreamEnds`).
*/
function recordMessagesCreateResponse(client, call, body, data) {
if (!call?.span.isRecording() || data instanceof streaming_1.Stream) {
return;
}
const span = call.span;
try {
(0, response_1.setResponseAttributes)(span, data, data.usage, true);
const { contentMode, maxContentBytes } = client.openTelemetry.traces;
if (contentMode === 'content') {
(0, content_1.setMessageContentAttributes)(call, body, data.content, maxContentBytes);
}
}
catch (problem) {
(0, log_1.loggerFor)(client).debug('could not record the response on its span', problem);
}
}
/** Sets the token count of a `messages.countTokens` response on `call`. */
function recordCountTokensResponse(client, call, count) {
try {
call?.span.setAttribute(attributes_1.ATTR_ANTHROPIC_MESSAGE_COUNT_TOKENS_INPUT_TOKENS, count.input_tokens);
}
catch (problem) {
(0, log_1.loggerFor)(client).debug('could not record the response on its span', problem);
}
}
/** Sets the Agent's name and model on `call`, as the created `session` resolved them. */
function recordSessionsCreateResponse(client, call, session) {
try {
call?.span.setAttributes({
[attributes_1.ATTR_GEN_AI_AGENT_NAME]: session.agent.name,
[attributes_1.ATTR_GEN_AI_REQUEST_MODEL]: session.agent.model.id,
});
}
catch (problem) {
(0, log_1.loggerFor)(client).debug('could not record the response on its span', problem);
}
}
//# sourceMappingURL=api-call.js.map