@use-lattice/litmus 0.121.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/dist/src/accounts-Bt1oJb1Z.cjs +219 -0
- package/dist/src/accounts-DjOU8Rm3.js +178 -0
- package/dist/src/agentic-utils-D03IiXQc.js +153 -0
- package/dist/src/agentic-utils-Dh7xaMQM.cjs +180 -0
- package/dist/src/agents-C6BIMlZa.js +231 -0
- package/dist/src/agents-DvIpNX1L.cjs +666 -0
- package/dist/src/agents-ZP0RP9vV.cjs +231 -0
- package/dist/src/agents-maJXdjbR.js +665 -0
- package/dist/src/aimlapi-BTbQjG2E.cjs +30 -0
- package/dist/src/aimlapi-CwMxqfXP.js +30 -0
- package/dist/src/audio-BBUdvsde.cjs +97 -0
- package/dist/src/audio-D5DPZ7I-.js +97 -0
- package/dist/src/base-BEysXrkq.cjs +222 -0
- package/dist/src/base-C451JQfq.js +193 -0
- package/dist/src/blobs-BY8MDmpo.js +230 -0
- package/dist/src/blobs-BgcNn97m.cjs +256 -0
- package/dist/src/cache-BBE_lsTA.cjs +4 -0
- package/dist/src/cache-BkrqU5Ba.js +237 -0
- package/dist/src/cache-DsCxFlsZ.cjs +297 -0
- package/dist/src/chat-CPJWDP6a.cjs +289 -0
- package/dist/src/chat-CXX3xzkk.cjs +811 -0
- package/dist/src/chat-CcDgZFJ4.js +787 -0
- package/dist/src/chat-Dz5ZeGO2.js +289 -0
- package/dist/src/chatkit-Dw0mKkML.cjs +1158 -0
- package/dist/src/chatkit-swAIVuea.js +1157 -0
- package/dist/src/chunk-DEq-mXcV.js +15 -0
- package/dist/src/claude-agent-sdk-BXZJtOg6.js +379 -0
- package/dist/src/claude-agent-sdk-CkfyjDoG.cjs +383 -0
- package/dist/src/cloudflare-ai-BzpJcqUH.js +161 -0
- package/dist/src/cloudflare-ai-Cmy_R1y2.cjs +161 -0
- package/dist/src/cloudflare-gateway-B9tVQKok.cjs +272 -0
- package/dist/src/cloudflare-gateway-DrD3ew3H.js +272 -0
- package/dist/src/codex-sdk-Dezj9Nwm.js +1056 -0
- package/dist/src/codex-sdk-Dl9D4k5B.cjs +1060 -0
- package/dist/src/cometapi-C-9YvCHC.js +54 -0
- package/dist/src/cometapi-DHgDKoO2.cjs +54 -0
- package/dist/src/completion-B8Ctyxpr.js +120 -0
- package/dist/src/completion-Cxrt08sj.cjs +131 -0
- package/dist/src/createHash-BwgE13yv.cjs +27 -0
- package/dist/src/createHash-DmPQkvBh.js +15 -0
- package/dist/src/docker-BiqcTwLv.js +80 -0
- package/dist/src/docker-C7tEJnP-.cjs +80 -0
- package/dist/src/esm-C62Zofr1.cjs +409 -0
- package/dist/src/esm-DMVc93eh.js +379 -0
- package/dist/src/evalResult-C3NJPQOo.cjs +301 -0
- package/dist/src/evalResult-C7JJAPBb.js +295 -0
- package/dist/src/evalResult-DoVTZZWI.cjs +2 -0
- package/dist/src/extractor-DnMD3fwt.cjs +391 -0
- package/dist/src/extractor-DtlL28vL.js +374 -0
- package/dist/src/fetch-BTxakTSg.cjs +1133 -0
- package/dist/src/fetch-DQckpUFz.js +928 -0
- package/dist/src/fileExtensions-DnqA1y9x.js +85 -0
- package/dist/src/fileExtensions-bYh77CN8.cjs +114 -0
- package/dist/src/genaiTracer-CyZrmaK0.cjs +268 -0
- package/dist/src/genaiTracer-D3fD9dNV.js +256 -0
- package/dist/src/graders-BNscxFrU.js +13644 -0
- package/dist/src/graders-D2oE9Msq.js +2 -0
- package/dist/src/graders-c0Ez_w-9.cjs +2 -0
- package/dist/src/graders-d0F2M3e9.cjs +14056 -0
- package/dist/src/image-0ZhE0VlR.cjs +280 -0
- package/dist/src/image-CWE1pdNv.js +257 -0
- package/dist/src/image-D9ZK6hwL.js +163 -0
- package/dist/src/image-DKZgZITg.cjs +163 -0
- package/dist/src/index.cjs +11366 -0
- package/dist/src/index.d.cts +19640 -0
- package/dist/src/index.d.ts +19641 -0
- package/dist/src/index.js +11306 -0
- package/dist/src/invariant-Ddh24eXh.js +25 -0
- package/dist/src/invariant-kfQ8Bu82.cjs +30 -0
- package/dist/src/knowledgeBase-BgPyGFUd.cjs +122 -0
- package/dist/src/knowledgeBase-DyHilYaP.js +122 -0
- package/dist/src/litellm-CyMeneHS.js +135 -0
- package/dist/src/litellm-DWDF73yF.cjs +135 -0
- package/dist/src/logger-C40ZGil9.js +717 -0
- package/dist/src/logger-DyfK9PBt.cjs +917 -0
- package/dist/src/luma-ray-BAU9X_ep.cjs +315 -0
- package/dist/src/luma-ray-nwVseBbv.js +313 -0
- package/dist/src/messages-B5ADWTTv.js +245 -0
- package/dist/src/messages-BCnZfqrS.cjs +257 -0
- package/dist/src/meteor-DLZZ3osF.cjs +134 -0
- package/dist/src/meteor-DUiCJRC-.js +134 -0
- package/dist/src/modelslab-00cveB8L.cjs +163 -0
- package/dist/src/modelslab-D9sCU_L7.js +163 -0
- package/dist/src/nova-reel-CTapvqYH.js +276 -0
- package/dist/src/nova-reel-DlWuuroF.cjs +278 -0
- package/dist/src/nova-sonic-5UPWfeMv.cjs +363 -0
- package/dist/src/nova-sonic-BhSwQNym.js +363 -0
- package/dist/src/openai-BWrJK9d8.cjs +52 -0
- package/dist/src/openai-DumO8WQn.js +47 -0
- package/dist/src/openclaw-B8brrjC_.cjs +577 -0
- package/dist/src/openclaw-Bkayww9q.js +571 -0
- package/dist/src/opencode-sdk-7xjoDNiM.cjs +562 -0
- package/dist/src/opencode-sdk-SGwAPxht.js +558 -0
- package/dist/src/otlpReceiver-CoAHfAN9.cjs +15 -0
- package/dist/src/otlpReceiver-oO3EQwI9.js +14 -0
- package/dist/src/providerRegistry-4yjhaEM8.js +45 -0
- package/dist/src/providerRegistry-DhV4rJIc.cjs +50 -0
- package/dist/src/providers-B5RJVG-7.cjs +33609 -0
- package/dist/src/providers-BdmZCLzV.js +33262 -0
- package/dist/src/providers-CxtRxn8e.js +2 -0
- package/dist/src/providers-DnQLNbx1.cjs +3 -0
- package/dist/src/pythonUtils-BD0druiM.cjs +275 -0
- package/dist/src/pythonUtils-IBhn5YGR.js +249 -0
- package/dist/src/quiverai-BDOwZBsM.cjs +213 -0
- package/dist/src/quiverai-D3JTF5lD.js +213 -0
- package/dist/src/responses-B2LCDCXZ.js +667 -0
- package/dist/src/responses-BvNm4Xv9.cjs +685 -0
- package/dist/src/rubyUtils-B0NwnfpY.cjs +245 -0
- package/dist/src/rubyUtils-BroxzZ7c.cjs +2 -0
- package/dist/src/rubyUtils-hqVw5UvJ.js +222 -0
- package/dist/src/sagemaker-Cno2V-Sx.js +689 -0
- package/dist/src/sagemaker-fV_KUgs5.cjs +691 -0
- package/dist/src/server-BOuAXb06.cjs +238 -0
- package/dist/src/server-CtI-EWzm.cjs +2 -0
- package/dist/src/server-Cy3DZymt.js +189 -0
- package/dist/src/slack-CP8xBePa.js +135 -0
- package/dist/src/slack-DSQ1yXVb.cjs +135 -0
- package/dist/src/store-BwDDaBjb.cjs +246 -0
- package/dist/src/store-DcbLC593.cjs +2 -0
- package/dist/src/store-IGpqMIkv.js +240 -0
- package/dist/src/tables-3Q2cL7So.cjs +373 -0
- package/dist/src/tables-Bi2fjr4W.js +288 -0
- package/dist/src/telemetry-Bg2WqF79.js +161 -0
- package/dist/src/telemetry-D0x6u5kX.cjs +166 -0
- package/dist/src/telemetry-DXNimrI0.cjs +2 -0
- package/dist/src/text-B_UCRPp2.js +22 -0
- package/dist/src/text-CW1cyrwj.cjs +33 -0
- package/dist/src/tokenUsageUtils-NYT-WKS6.js +138 -0
- package/dist/src/tokenUsageUtils-bVa1ga6f.cjs +173 -0
- package/dist/src/transcription-Cl_W16Pr.js +122 -0
- package/dist/src/transcription-yt1EecY8.cjs +124 -0
- package/dist/src/transform-BCtGrl_W.cjs +228 -0
- package/dist/src/transform-Bv6gG2MJ.cjs +1688 -0
- package/dist/src/transform-CY1wbpRy.js +1507 -0
- package/dist/src/transform-DU8rUL9P.cjs +2 -0
- package/dist/src/transform-yWaShiKr.js +216 -0
- package/dist/src/transformersAvailability-BGkzavwb.js +35 -0
- package/dist/src/transformersAvailability-DKoRtQLy.cjs +35 -0
- package/dist/src/types-5aqHpBwE.cjs +3769 -0
- package/dist/src/types-Bn6D9c4U.js +3300 -0
- package/dist/src/util-BkKlTkI2.js +293 -0
- package/dist/src/util-CTh0bfOm.cjs +1119 -0
- package/dist/src/util-D17oBwo7.cjs +328 -0
- package/dist/src/util-DsS_-v4p.js +613 -0
- package/dist/src/util-DuntT1Ga.js +951 -0
- package/dist/src/util-aWjdCYMI.cjs +667 -0
- package/dist/src/utils-CisQwpjA.js +94 -0
- package/dist/src/utils-yWamDvmz.cjs +123 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/drizzle/0000_lush_hellion.sql +36 -0
- package/drizzle/0001_wide_calypso.sql +3 -0
- package/drizzle/0002_tidy_juggernaut.sql +1 -0
- package/drizzle/0003_lively_naoko.sql +8 -0
- package/drizzle/0004_minor_peter_quill.sql +19 -0
- package/drizzle/0005_silky_millenium_guard.sql +2 -0
- package/drizzle/0006_harsh_caretaker.sql +42 -0
- package/drizzle/0007_cloudy_wong.sql +1 -0
- package/drizzle/0008_broad_boomer.sql +2 -0
- package/drizzle/0009_strong_marten_broadcloak.sql +19 -0
- package/drizzle/0010_needy_bishop.sql +11 -0
- package/drizzle/0011_moaning_millenium_guard.sql +1 -0
- package/drizzle/0012_late_marten_broadcloak.sql +2 -0
- package/drizzle/0013_previous_dormammu.sql +9 -0
- package/drizzle/0014_lazy_captain_universe.sql +2 -0
- package/drizzle/0015_zippy_wallop.sql +29 -0
- package/drizzle/0016_jazzy_zemo.sql +2 -0
- package/drizzle/0017_reflective_praxagora.sql +4 -0
- package/drizzle/0018_fat_vanisher.sql +22 -0
- package/drizzle/0019_new_clint_barton.sql +8 -0
- package/drizzle/0020_skinny_maverick.sql +1 -0
- package/drizzle/0021_mysterious_madelyne_pryor.sql +13 -0
- package/drizzle/0022_sleepy_ultimo.sql +25 -0
- package/drizzle/0023_wooden_mandrill.sql +2 -0
- package/drizzle/AGENTS.md +68 -0
- package/drizzle/CLAUDE.md +1 -0
- package/drizzle/meta/0000_snapshot.json +221 -0
- package/drizzle/meta/0001_snapshot.json +214 -0
- package/drizzle/meta/0002_snapshot.json +221 -0
- package/drizzle/meta/0005_snapshot.json +369 -0
- package/drizzle/meta/0006_snapshot.json +638 -0
- package/drizzle/meta/0007_snapshot.json +640 -0
- package/drizzle/meta/0008_snapshot.json +649 -0
- package/drizzle/meta/0009_snapshot.json +554 -0
- package/drizzle/meta/0010_snapshot.json +619 -0
- package/drizzle/meta/0011_snapshot.json +627 -0
- package/drizzle/meta/0012_snapshot.json +639 -0
- package/drizzle/meta/0013_snapshot.json +717 -0
- package/drizzle/meta/0014_snapshot.json +717 -0
- package/drizzle/meta/0015_snapshot.json +897 -0
- package/drizzle/meta/0016_snapshot.json +1031 -0
- package/drizzle/meta/0018_snapshot.json +1210 -0
- package/drizzle/meta/0019_snapshot.json +1165 -0
- package/drizzle/meta/0020_snapshot.json +1232 -0
- package/drizzle/meta/0021_snapshot.json +1311 -0
- package/drizzle/meta/0022_snapshot.json +1481 -0
- package/drizzle/meta/0023_snapshot.json +1496 -0
- package/drizzle/meta/_journal.json +174 -0
- package/package.json +240 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { b as getEnvInt, r as logger, x as getEnvString, y as getEnvFloat } from "./logger-C40ZGil9.js";
|
|
2
|
+
import { d as maybeLoadToolsFromExternalFile, u as maybeLoadResponseFormatFromExternalFile } from "./util-DuntT1Ga.js";
|
|
3
|
+
import { T as transformTools, w as transformToolChoice } from "./fetch-DQckpUFz.js";
|
|
4
|
+
import { a as isCacheEnabled, i as getCache } from "./cache-BkrqU5Ba.js";
|
|
5
|
+
import { n as withGenAISpan } from "./genaiTracer-D3fD9dNV.js";
|
|
6
|
+
import { i as normalizeFinishReason, n as MCPClient } from "./chat-CcDgZFJ4.js";
|
|
7
|
+
import { a as createEmptyTokenUsage } from "./tokenUsageUtils-NYT-WKS6.js";
|
|
8
|
+
import { n as transformMCPToolsToAnthropic } from "./transform-CY1wbpRy.js";
|
|
9
|
+
import { a as parseMessages, i as outputFromMessage, n as calculateAnthropicCost, o as processAnthropicTools, r as getTokenUsage, t as ANTHROPIC_MODELS } from "./util-BkKlTkI2.js";
|
|
10
|
+
import Anthropic, { APIError } from "@anthropic-ai/sdk";
|
|
11
|
+
//#region src/providers/anthropic/generic.ts
|
|
12
|
+
/**
|
|
13
|
+
* Generic provider class for Anthropic APIs
|
|
14
|
+
* Serves as a base class with shared functionality for all Anthropic providers
|
|
15
|
+
*/
|
|
16
|
+
var AnthropicGenericProvider = class {
|
|
17
|
+
modelName;
|
|
18
|
+
config;
|
|
19
|
+
env;
|
|
20
|
+
apiKey;
|
|
21
|
+
anthropic;
|
|
22
|
+
constructor(modelName, options = {}) {
|
|
23
|
+
const { config, id, env } = options;
|
|
24
|
+
this.env = env;
|
|
25
|
+
this.modelName = modelName;
|
|
26
|
+
this.config = config || {};
|
|
27
|
+
this.apiKey = this.getApiKey();
|
|
28
|
+
this.anthropic = new Anthropic({
|
|
29
|
+
apiKey: this.apiKey,
|
|
30
|
+
baseURL: this.getApiBaseUrl()
|
|
31
|
+
});
|
|
32
|
+
this.id = id ? () => id : this.id;
|
|
33
|
+
}
|
|
34
|
+
id() {
|
|
35
|
+
return `anthropic:${this.modelName}`;
|
|
36
|
+
}
|
|
37
|
+
toString() {
|
|
38
|
+
return `[Anthropic Provider ${this.modelName}]`;
|
|
39
|
+
}
|
|
40
|
+
requiresApiKey() {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
getApiKey() {
|
|
44
|
+
return this.config?.apiKey || this.env?.ANTHROPIC_API_KEY || getEnvString("ANTHROPIC_API_KEY");
|
|
45
|
+
}
|
|
46
|
+
getApiBaseUrl() {
|
|
47
|
+
return this.config?.apiBaseUrl || this.env?.ANTHROPIC_BASE_URL || getEnvString("ANTHROPIC_BASE_URL");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Base implementation - should be overridden by specific provider implementations
|
|
51
|
+
*/
|
|
52
|
+
async callApi(_prompt, _context) {
|
|
53
|
+
throw new Error("Not implemented: callApi must be implemented by subclasses");
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/providers/anthropic/messages.ts
|
|
58
|
+
function parseEnvFloat(value) {
|
|
59
|
+
if (value === void 0) return;
|
|
60
|
+
const parsed = Number.parseFloat(value);
|
|
61
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
62
|
+
}
|
|
63
|
+
var AnthropicMessagesProvider = class AnthropicMessagesProvider extends AnthropicGenericProvider {
|
|
64
|
+
mcpClient = null;
|
|
65
|
+
initializationPromise = null;
|
|
66
|
+
static ANTHROPIC_MODELS = ANTHROPIC_MODELS;
|
|
67
|
+
static ANTHROPIC_MODELS_NAMES = ANTHROPIC_MODELS.map((model) => model.id);
|
|
68
|
+
constructor(modelName, options = {}) {
|
|
69
|
+
if (!AnthropicMessagesProvider.ANTHROPIC_MODELS_NAMES.includes(modelName)) logger.warn(`Using unknown Anthropic model: ${modelName}`);
|
|
70
|
+
super(modelName, options);
|
|
71
|
+
const { id } = options;
|
|
72
|
+
this.id = id ? () => id : this.id;
|
|
73
|
+
if (this.config.mcp?.enabled) this.initializationPromise = this.initializeMCP();
|
|
74
|
+
}
|
|
75
|
+
async initializeMCP() {
|
|
76
|
+
this.mcpClient = new MCPClient(this.config.mcp);
|
|
77
|
+
await this.mcpClient.initialize();
|
|
78
|
+
}
|
|
79
|
+
async cleanup() {
|
|
80
|
+
if (this.mcpClient) {
|
|
81
|
+
await this.initializationPromise;
|
|
82
|
+
await this.mcpClient.cleanup();
|
|
83
|
+
this.mcpClient = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
toString() {
|
|
87
|
+
if (!this.modelName) throw new Error("Anthropic model name is not set. Please provide a valid model name.");
|
|
88
|
+
return `[Anthropic Messages Provider ${this.modelName}]`;
|
|
89
|
+
}
|
|
90
|
+
async callApi(prompt, context) {
|
|
91
|
+
if (this.initializationPromise != null) await this.initializationPromise;
|
|
92
|
+
if (!this.apiKey) throw new Error("Anthropic API key is not set. Set the ANTHROPIC_API_KEY environment variable or add `apiKey` to the provider config.");
|
|
93
|
+
if (!this.modelName) throw new Error("Anthropic model name is not set. Please provide a valid model name.");
|
|
94
|
+
const spanContext = {
|
|
95
|
+
system: "anthropic",
|
|
96
|
+
operationName: "chat",
|
|
97
|
+
model: this.modelName,
|
|
98
|
+
providerId: this.id(),
|
|
99
|
+
maxTokens: this.config.max_tokens,
|
|
100
|
+
temperature: this.config.temperature,
|
|
101
|
+
testIndex: context?.test?.vars?.__testIdx,
|
|
102
|
+
promptLabel: context?.prompt?.label,
|
|
103
|
+
traceparent: context?.traceparent,
|
|
104
|
+
requestBody: prompt
|
|
105
|
+
};
|
|
106
|
+
const resultExtractor = (response) => {
|
|
107
|
+
const result = {};
|
|
108
|
+
if (response.tokenUsage) result.tokenUsage = {
|
|
109
|
+
prompt: response.tokenUsage.prompt,
|
|
110
|
+
completion: response.tokenUsage.completion,
|
|
111
|
+
total: response.tokenUsage.total,
|
|
112
|
+
cached: response.tokenUsage.cached
|
|
113
|
+
};
|
|
114
|
+
if (response.finishReason) result.finishReasons = [response.finishReason];
|
|
115
|
+
if (response.cached !== void 0) result.cacheHit = response.cached;
|
|
116
|
+
if (response.output !== void 0) result.responseBody = typeof response.output === "string" ? response.output : JSON.stringify(response.output);
|
|
117
|
+
return result;
|
|
118
|
+
};
|
|
119
|
+
return withGenAISpan(spanContext, () => this.callApiInternal(prompt, context), resultExtractor);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Internal implementation of callApi without tracing wrapper.
|
|
123
|
+
*/
|
|
124
|
+
async callApiInternal(prompt, context) {
|
|
125
|
+
const config = {
|
|
126
|
+
...this.config,
|
|
127
|
+
...context?.prompt?.config
|
|
128
|
+
};
|
|
129
|
+
const { system, extractedMessages, thinking } = parseMessages(prompt);
|
|
130
|
+
let mcpTools = [];
|
|
131
|
+
if (this.mcpClient) mcpTools = transformMCPToolsToAnthropic(this.mcpClient.getAllTools());
|
|
132
|
+
const { processedTools: processedConfigTools, requiredBetaFeatures } = processAnthropicTools(transformTools(await maybeLoadToolsFromExternalFile(config.tools, context?.vars) || [], "anthropic"));
|
|
133
|
+
const allTools = [...mcpTools, ...processedConfigTools];
|
|
134
|
+
const processedOutputFormat = maybeLoadResponseFormatFromExternalFile(config.output_format, context?.vars);
|
|
135
|
+
const shouldStream = config.stream ?? false;
|
|
136
|
+
const params = {
|
|
137
|
+
model: this.modelName,
|
|
138
|
+
...system ? { system } : {},
|
|
139
|
+
max_tokens: config?.max_tokens || getEnvInt("ANTHROPIC_MAX_TOKENS", config.thinking || thinking ? 2048 : 1024),
|
|
140
|
+
messages: extractedMessages,
|
|
141
|
+
stream: shouldStream,
|
|
142
|
+
temperature: config.thinking || thinking ? config.temperature : config.temperature ?? parseEnvFloat(this.env?.ANTHROPIC_TEMPERATURE) ?? getEnvFloat("ANTHROPIC_TEMPERATURE", 0),
|
|
143
|
+
...allTools.length > 0 ? { tools: allTools } : {},
|
|
144
|
+
...config.tool_choice ? { tool_choice: transformToolChoice(config.tool_choice, "anthropic") } : {},
|
|
145
|
+
...config.thinking || thinking ? { thinking: config.thinking || thinking } : {},
|
|
146
|
+
...processedOutputFormat || config.effort ? { output_config: {
|
|
147
|
+
...processedOutputFormat ? { format: processedOutputFormat } : {},
|
|
148
|
+
...config.effort ? { effort: config.effort } : {}
|
|
149
|
+
} } : {},
|
|
150
|
+
...typeof config?.extra_body === "object" && config.extra_body ? config.extra_body : {}
|
|
151
|
+
};
|
|
152
|
+
logger.debug("Calling Anthropic Messages API", { params });
|
|
153
|
+
const headers = { ...config.headers || {} };
|
|
154
|
+
let allBetaFeatures = [...config.beta || [], ...requiredBetaFeatures];
|
|
155
|
+
if (processedOutputFormat && !allBetaFeatures.includes("structured-outputs-2025-11-13")) allBetaFeatures.push("structured-outputs-2025-11-13");
|
|
156
|
+
allBetaFeatures = [...new Set(allBetaFeatures)];
|
|
157
|
+
if (allBetaFeatures.length > 0) headers["anthropic-beta"] = allBetaFeatures.join(",");
|
|
158
|
+
const cache = await getCache();
|
|
159
|
+
const cacheKey = `anthropic:${JSON.stringify(params)}`;
|
|
160
|
+
if (isCacheEnabled()) {
|
|
161
|
+
const cachedResponse = await cache.get(cacheKey);
|
|
162
|
+
if (cachedResponse) {
|
|
163
|
+
logger.debug(`Returning cached response for ${prompt}: ${cachedResponse}`);
|
|
164
|
+
try {
|
|
165
|
+
const parsedCachedResponse = JSON.parse(cachedResponse);
|
|
166
|
+
const finishReason = normalizeFinishReason(parsedCachedResponse.stop_reason);
|
|
167
|
+
let output = outputFromMessage(parsedCachedResponse, config.showThinking ?? true);
|
|
168
|
+
if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
|
|
169
|
+
output = JSON.parse(output);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
output,
|
|
175
|
+
tokenUsage: getTokenUsage(parsedCachedResponse, true),
|
|
176
|
+
...finishReason && { finishReason },
|
|
177
|
+
cost: calculateAnthropicCost(this.modelName, config, parsedCachedResponse.usage?.input_tokens, parsedCachedResponse.usage?.output_tokens),
|
|
178
|
+
cached: true
|
|
179
|
+
};
|
|
180
|
+
} catch {
|
|
181
|
+
return {
|
|
182
|
+
output: cachedResponse,
|
|
183
|
+
tokenUsage: createEmptyTokenUsage()
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
if (shouldStream) {
|
|
190
|
+
const finalMessage = await (await this.anthropic.messages.stream(params, { ...typeof headers === "object" && Object.keys(headers).length > 0 ? { headers } : {} })).finalMessage();
|
|
191
|
+
logger.debug(`Anthropic Messages API streaming complete`, { finalMessage });
|
|
192
|
+
if (isCacheEnabled()) try {
|
|
193
|
+
await cache.set(cacheKey, JSON.stringify(finalMessage));
|
|
194
|
+
} catch (err) {
|
|
195
|
+
logger.error(`Failed to cache response: ${String(err)}`);
|
|
196
|
+
}
|
|
197
|
+
const finishReason = normalizeFinishReason(finalMessage.stop_reason);
|
|
198
|
+
let output = outputFromMessage(finalMessage, config.showThinking ?? true);
|
|
199
|
+
if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
|
|
200
|
+
output = JSON.parse(output);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
output,
|
|
206
|
+
tokenUsage: getTokenUsage(finalMessage, false),
|
|
207
|
+
...finishReason && { finishReason },
|
|
208
|
+
cost: calculateAnthropicCost(this.modelName, config, finalMessage.usage?.input_tokens, finalMessage.usage?.output_tokens)
|
|
209
|
+
};
|
|
210
|
+
} else {
|
|
211
|
+
const response = await this.anthropic.messages.create(params, { ...typeof headers === "object" && Object.keys(headers).length > 0 ? { headers } : {} });
|
|
212
|
+
logger.debug(`Anthropic Messages API response`, { response });
|
|
213
|
+
if (isCacheEnabled()) try {
|
|
214
|
+
await cache.set(cacheKey, JSON.stringify(response));
|
|
215
|
+
} catch (err) {
|
|
216
|
+
logger.error(`Failed to cache response: ${String(err)}`);
|
|
217
|
+
}
|
|
218
|
+
const finishReason = normalizeFinishReason(response.stop_reason);
|
|
219
|
+
let output = outputFromMessage(response, config.showThinking ?? true);
|
|
220
|
+
if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
|
|
221
|
+
output = JSON.parse(output);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
output,
|
|
227
|
+
tokenUsage: getTokenUsage(response, false),
|
|
228
|
+
...finishReason && { finishReason },
|
|
229
|
+
cost: calculateAnthropicCost(this.modelName, config, response.usage?.input_tokens, response.usage?.output_tokens)
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
} catch (err) {
|
|
233
|
+
logger.error(`Anthropic Messages API call error: ${err instanceof Error ? err.message : String(err)}`);
|
|
234
|
+
if (err instanceof APIError && err.error) {
|
|
235
|
+
const errorDetails = err.error;
|
|
236
|
+
return { error: `API call error: ${errorDetails.error.message}, status ${err.status}, type ${errorDetails.error.type}` };
|
|
237
|
+
}
|
|
238
|
+
return { error: `API call error: ${err instanceof Error ? err.message : String(err)}` };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
//#endregion
|
|
243
|
+
export { AnthropicGenericProvider as n, AnthropicMessagesProvider as t };
|
|
244
|
+
|
|
245
|
+
//# sourceMappingURL=messages-B5ADWTTv.js.map
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const require_logger = require("./logger-DyfK9PBt.cjs");
|
|
2
|
+
const require_util = require("./util-CTh0bfOm.cjs");
|
|
3
|
+
const require_fetch = require("./fetch-BTxakTSg.cjs");
|
|
4
|
+
const require_cache = require("./cache-DsCxFlsZ.cjs");
|
|
5
|
+
const require_genaiTracer = require("./genaiTracer-CyZrmaK0.cjs");
|
|
6
|
+
const require_chat = require("./chat-CXX3xzkk.cjs");
|
|
7
|
+
const require_tokenUsageUtils = require("./tokenUsageUtils-bVa1ga6f.cjs");
|
|
8
|
+
const require_transform = require("./transform-Bv6gG2MJ.cjs");
|
|
9
|
+
const require_util$1 = require("./util-D17oBwo7.cjs");
|
|
10
|
+
let _anthropic_ai_sdk = require("@anthropic-ai/sdk");
|
|
11
|
+
_anthropic_ai_sdk = require_logger.__toESM(_anthropic_ai_sdk);
|
|
12
|
+
//#region src/providers/anthropic/generic.ts
|
|
13
|
+
/**
|
|
14
|
+
* Generic provider class for Anthropic APIs
|
|
15
|
+
* Serves as a base class with shared functionality for all Anthropic providers
|
|
16
|
+
*/
|
|
17
|
+
var AnthropicGenericProvider = class {
|
|
18
|
+
modelName;
|
|
19
|
+
config;
|
|
20
|
+
env;
|
|
21
|
+
apiKey;
|
|
22
|
+
anthropic;
|
|
23
|
+
constructor(modelName, options = {}) {
|
|
24
|
+
const { config, id, env } = options;
|
|
25
|
+
this.env = env;
|
|
26
|
+
this.modelName = modelName;
|
|
27
|
+
this.config = config || {};
|
|
28
|
+
this.apiKey = this.getApiKey();
|
|
29
|
+
this.anthropic = new _anthropic_ai_sdk.default({
|
|
30
|
+
apiKey: this.apiKey,
|
|
31
|
+
baseURL: this.getApiBaseUrl()
|
|
32
|
+
});
|
|
33
|
+
this.id = id ? () => id : this.id;
|
|
34
|
+
}
|
|
35
|
+
id() {
|
|
36
|
+
return `anthropic:${this.modelName}`;
|
|
37
|
+
}
|
|
38
|
+
toString() {
|
|
39
|
+
return `[Anthropic Provider ${this.modelName}]`;
|
|
40
|
+
}
|
|
41
|
+
requiresApiKey() {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
getApiKey() {
|
|
45
|
+
return this.config?.apiKey || this.env?.ANTHROPIC_API_KEY || require_logger.getEnvString("ANTHROPIC_API_KEY");
|
|
46
|
+
}
|
|
47
|
+
getApiBaseUrl() {
|
|
48
|
+
return this.config?.apiBaseUrl || this.env?.ANTHROPIC_BASE_URL || require_logger.getEnvString("ANTHROPIC_BASE_URL");
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Base implementation - should be overridden by specific provider implementations
|
|
52
|
+
*/
|
|
53
|
+
async callApi(_prompt, _context) {
|
|
54
|
+
throw new Error("Not implemented: callApi must be implemented by subclasses");
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/providers/anthropic/messages.ts
|
|
59
|
+
function parseEnvFloat(value) {
|
|
60
|
+
if (value === void 0) return;
|
|
61
|
+
const parsed = Number.parseFloat(value);
|
|
62
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
63
|
+
}
|
|
64
|
+
var AnthropicMessagesProvider = class AnthropicMessagesProvider extends AnthropicGenericProvider {
|
|
65
|
+
mcpClient = null;
|
|
66
|
+
initializationPromise = null;
|
|
67
|
+
static ANTHROPIC_MODELS = require_util$1.ANTHROPIC_MODELS;
|
|
68
|
+
static ANTHROPIC_MODELS_NAMES = require_util$1.ANTHROPIC_MODELS.map((model) => model.id);
|
|
69
|
+
constructor(modelName, options = {}) {
|
|
70
|
+
if (!AnthropicMessagesProvider.ANTHROPIC_MODELS_NAMES.includes(modelName)) require_logger.logger.warn(`Using unknown Anthropic model: ${modelName}`);
|
|
71
|
+
super(modelName, options);
|
|
72
|
+
const { id } = options;
|
|
73
|
+
this.id = id ? () => id : this.id;
|
|
74
|
+
if (this.config.mcp?.enabled) this.initializationPromise = this.initializeMCP();
|
|
75
|
+
}
|
|
76
|
+
async initializeMCP() {
|
|
77
|
+
this.mcpClient = new require_chat.MCPClient(this.config.mcp);
|
|
78
|
+
await this.mcpClient.initialize();
|
|
79
|
+
}
|
|
80
|
+
async cleanup() {
|
|
81
|
+
if (this.mcpClient) {
|
|
82
|
+
await this.initializationPromise;
|
|
83
|
+
await this.mcpClient.cleanup();
|
|
84
|
+
this.mcpClient = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
toString() {
|
|
88
|
+
if (!this.modelName) throw new Error("Anthropic model name is not set. Please provide a valid model name.");
|
|
89
|
+
return `[Anthropic Messages Provider ${this.modelName}]`;
|
|
90
|
+
}
|
|
91
|
+
async callApi(prompt, context) {
|
|
92
|
+
if (this.initializationPromise != null) await this.initializationPromise;
|
|
93
|
+
if (!this.apiKey) throw new Error("Anthropic API key is not set. Set the ANTHROPIC_API_KEY environment variable or add `apiKey` to the provider config.");
|
|
94
|
+
if (!this.modelName) throw new Error("Anthropic model name is not set. Please provide a valid model name.");
|
|
95
|
+
const spanContext = {
|
|
96
|
+
system: "anthropic",
|
|
97
|
+
operationName: "chat",
|
|
98
|
+
model: this.modelName,
|
|
99
|
+
providerId: this.id(),
|
|
100
|
+
maxTokens: this.config.max_tokens,
|
|
101
|
+
temperature: this.config.temperature,
|
|
102
|
+
testIndex: context?.test?.vars?.__testIdx,
|
|
103
|
+
promptLabel: context?.prompt?.label,
|
|
104
|
+
traceparent: context?.traceparent,
|
|
105
|
+
requestBody: prompt
|
|
106
|
+
};
|
|
107
|
+
const resultExtractor = (response) => {
|
|
108
|
+
const result = {};
|
|
109
|
+
if (response.tokenUsage) result.tokenUsage = {
|
|
110
|
+
prompt: response.tokenUsage.prompt,
|
|
111
|
+
completion: response.tokenUsage.completion,
|
|
112
|
+
total: response.tokenUsage.total,
|
|
113
|
+
cached: response.tokenUsage.cached
|
|
114
|
+
};
|
|
115
|
+
if (response.finishReason) result.finishReasons = [response.finishReason];
|
|
116
|
+
if (response.cached !== void 0) result.cacheHit = response.cached;
|
|
117
|
+
if (response.output !== void 0) result.responseBody = typeof response.output === "string" ? response.output : JSON.stringify(response.output);
|
|
118
|
+
return result;
|
|
119
|
+
};
|
|
120
|
+
return require_genaiTracer.withGenAISpan(spanContext, () => this.callApiInternal(prompt, context), resultExtractor);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Internal implementation of callApi without tracing wrapper.
|
|
124
|
+
*/
|
|
125
|
+
async callApiInternal(prompt, context) {
|
|
126
|
+
const config = {
|
|
127
|
+
...this.config,
|
|
128
|
+
...context?.prompt?.config
|
|
129
|
+
};
|
|
130
|
+
const { system, extractedMessages, thinking } = require_util$1.parseMessages(prompt);
|
|
131
|
+
let mcpTools = [];
|
|
132
|
+
if (this.mcpClient) mcpTools = require_transform.transformMCPToolsToAnthropic(this.mcpClient.getAllTools());
|
|
133
|
+
const { processedTools: processedConfigTools, requiredBetaFeatures } = require_util$1.processAnthropicTools(require_fetch.transformTools(await require_util.maybeLoadToolsFromExternalFile(config.tools, context?.vars) || [], "anthropic"));
|
|
134
|
+
const allTools = [...mcpTools, ...processedConfigTools];
|
|
135
|
+
const processedOutputFormat = require_util.maybeLoadResponseFormatFromExternalFile(config.output_format, context?.vars);
|
|
136
|
+
const shouldStream = config.stream ?? false;
|
|
137
|
+
const params = {
|
|
138
|
+
model: this.modelName,
|
|
139
|
+
...system ? { system } : {},
|
|
140
|
+
max_tokens: config?.max_tokens || require_logger.getEnvInt("ANTHROPIC_MAX_TOKENS", config.thinking || thinking ? 2048 : 1024),
|
|
141
|
+
messages: extractedMessages,
|
|
142
|
+
stream: shouldStream,
|
|
143
|
+
temperature: config.thinking || thinking ? config.temperature : config.temperature ?? parseEnvFloat(this.env?.ANTHROPIC_TEMPERATURE) ?? require_logger.getEnvFloat("ANTHROPIC_TEMPERATURE", 0),
|
|
144
|
+
...allTools.length > 0 ? { tools: allTools } : {},
|
|
145
|
+
...config.tool_choice ? { tool_choice: require_fetch.transformToolChoice(config.tool_choice, "anthropic") } : {},
|
|
146
|
+
...config.thinking || thinking ? { thinking: config.thinking || thinking } : {},
|
|
147
|
+
...processedOutputFormat || config.effort ? { output_config: {
|
|
148
|
+
...processedOutputFormat ? { format: processedOutputFormat } : {},
|
|
149
|
+
...config.effort ? { effort: config.effort } : {}
|
|
150
|
+
} } : {},
|
|
151
|
+
...typeof config?.extra_body === "object" && config.extra_body ? config.extra_body : {}
|
|
152
|
+
};
|
|
153
|
+
require_logger.logger.debug("Calling Anthropic Messages API", { params });
|
|
154
|
+
const headers = { ...config.headers || {} };
|
|
155
|
+
let allBetaFeatures = [...config.beta || [], ...requiredBetaFeatures];
|
|
156
|
+
if (processedOutputFormat && !allBetaFeatures.includes("structured-outputs-2025-11-13")) allBetaFeatures.push("structured-outputs-2025-11-13");
|
|
157
|
+
allBetaFeatures = [...new Set(allBetaFeatures)];
|
|
158
|
+
if (allBetaFeatures.length > 0) headers["anthropic-beta"] = allBetaFeatures.join(",");
|
|
159
|
+
const cache = await require_cache.getCache();
|
|
160
|
+
const cacheKey = `anthropic:${JSON.stringify(params)}`;
|
|
161
|
+
if (require_cache.isCacheEnabled()) {
|
|
162
|
+
const cachedResponse = await cache.get(cacheKey);
|
|
163
|
+
if (cachedResponse) {
|
|
164
|
+
require_logger.logger.debug(`Returning cached response for ${prompt}: ${cachedResponse}`);
|
|
165
|
+
try {
|
|
166
|
+
const parsedCachedResponse = JSON.parse(cachedResponse);
|
|
167
|
+
const finishReason = require_chat.normalizeFinishReason(parsedCachedResponse.stop_reason);
|
|
168
|
+
let output = require_util$1.outputFromMessage(parsedCachedResponse, config.showThinking ?? true);
|
|
169
|
+
if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
|
|
170
|
+
output = JSON.parse(output);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
require_logger.logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
output,
|
|
176
|
+
tokenUsage: require_util$1.getTokenUsage(parsedCachedResponse, true),
|
|
177
|
+
...finishReason && { finishReason },
|
|
178
|
+
cost: require_util$1.calculateAnthropicCost(this.modelName, config, parsedCachedResponse.usage?.input_tokens, parsedCachedResponse.usage?.output_tokens),
|
|
179
|
+
cached: true
|
|
180
|
+
};
|
|
181
|
+
} catch {
|
|
182
|
+
return {
|
|
183
|
+
output: cachedResponse,
|
|
184
|
+
tokenUsage: require_tokenUsageUtils.createEmptyTokenUsage()
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
if (shouldStream) {
|
|
191
|
+
const finalMessage = await (await this.anthropic.messages.stream(params, { ...typeof headers === "object" && Object.keys(headers).length > 0 ? { headers } : {} })).finalMessage();
|
|
192
|
+
require_logger.logger.debug(`Anthropic Messages API streaming complete`, { finalMessage });
|
|
193
|
+
if (require_cache.isCacheEnabled()) try {
|
|
194
|
+
await cache.set(cacheKey, JSON.stringify(finalMessage));
|
|
195
|
+
} catch (err) {
|
|
196
|
+
require_logger.logger.error(`Failed to cache response: ${String(err)}`);
|
|
197
|
+
}
|
|
198
|
+
const finishReason = require_chat.normalizeFinishReason(finalMessage.stop_reason);
|
|
199
|
+
let output = require_util$1.outputFromMessage(finalMessage, config.showThinking ?? true);
|
|
200
|
+
if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
|
|
201
|
+
output = JSON.parse(output);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
require_logger.logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
output,
|
|
207
|
+
tokenUsage: require_util$1.getTokenUsage(finalMessage, false),
|
|
208
|
+
...finishReason && { finishReason },
|
|
209
|
+
cost: require_util$1.calculateAnthropicCost(this.modelName, config, finalMessage.usage?.input_tokens, finalMessage.usage?.output_tokens)
|
|
210
|
+
};
|
|
211
|
+
} else {
|
|
212
|
+
const response = await this.anthropic.messages.create(params, { ...typeof headers === "object" && Object.keys(headers).length > 0 ? { headers } : {} });
|
|
213
|
+
require_logger.logger.debug(`Anthropic Messages API response`, { response });
|
|
214
|
+
if (require_cache.isCacheEnabled()) try {
|
|
215
|
+
await cache.set(cacheKey, JSON.stringify(response));
|
|
216
|
+
} catch (err) {
|
|
217
|
+
require_logger.logger.error(`Failed to cache response: ${String(err)}`);
|
|
218
|
+
}
|
|
219
|
+
const finishReason = require_chat.normalizeFinishReason(response.stop_reason);
|
|
220
|
+
let output = require_util$1.outputFromMessage(response, config.showThinking ?? true);
|
|
221
|
+
if (processedOutputFormat?.type === "json_schema" && typeof output === "string") try {
|
|
222
|
+
output = JSON.parse(output);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
require_logger.logger.error(`Failed to parse JSON output from structured outputs: ${error}`);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
output,
|
|
228
|
+
tokenUsage: require_util$1.getTokenUsage(response, false),
|
|
229
|
+
...finishReason && { finishReason },
|
|
230
|
+
cost: require_util$1.calculateAnthropicCost(this.modelName, config, response.usage?.input_tokens, response.usage?.output_tokens)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
} catch (err) {
|
|
234
|
+
require_logger.logger.error(`Anthropic Messages API call error: ${err instanceof Error ? err.message : String(err)}`);
|
|
235
|
+
if (err instanceof _anthropic_ai_sdk.APIError && err.error) {
|
|
236
|
+
const errorDetails = err.error;
|
|
237
|
+
return { error: `API call error: ${errorDetails.error.message}, status ${err.status}, type ${errorDetails.error.type}` };
|
|
238
|
+
}
|
|
239
|
+
return { error: `API call error: ${err instanceof Error ? err.message : String(err)}` };
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
//#endregion
|
|
244
|
+
Object.defineProperty(exports, "AnthropicGenericProvider", {
|
|
245
|
+
enumerable: true,
|
|
246
|
+
get: function() {
|
|
247
|
+
return AnthropicGenericProvider;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
Object.defineProperty(exports, "AnthropicMessagesProvider", {
|
|
251
|
+
enumerable: true,
|
|
252
|
+
get: function() {
|
|
253
|
+
return AnthropicMessagesProvider;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
//# sourceMappingURL=messages-BCnZfqrS.cjs.map
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const require_invariant = require("./invariant-kfQ8Bu82.cjs");
|
|
2
|
+
//#region src/assertions/meteor.ts
|
|
3
|
+
let PorterStemmer;
|
|
4
|
+
let WordNet;
|
|
5
|
+
async function ensureNaturalPackage() {
|
|
6
|
+
if (PorterStemmer && WordNet) return;
|
|
7
|
+
try {
|
|
8
|
+
const natural = await import("natural");
|
|
9
|
+
PorterStemmer = natural.PorterStemmer;
|
|
10
|
+
WordNet = natural.WordNet;
|
|
11
|
+
} catch (_err) {
|
|
12
|
+
throw new Error("The \"natural\" package is required for METEOR assertions. Install it with: npm install natural@^8.1.0");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function preprocessWord(word) {
|
|
16
|
+
return word.toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function generateEnums(candidate, reference, preprocess = preprocessWord) {
|
|
19
|
+
if (typeof candidate === "string") throw new TypeError(`"candidate" expects pre-tokenized candidate (string[]): ${candidate}`);
|
|
20
|
+
if (typeof reference === "string") throw new TypeError(`"reference" expects pre-tokenized reference (string[]): ${reference}`);
|
|
21
|
+
return [candidate.map((word, idx) => [idx, preprocess(word)]), reference.map((word, idx) => [idx, preprocess(word)])];
|
|
22
|
+
}
|
|
23
|
+
function matchExactEnums(enumCandidateList, enumReferenceList) {
|
|
24
|
+
const wordMatch = [];
|
|
25
|
+
const candidateCopy = [...enumCandidateList];
|
|
26
|
+
const referenceCopy = [...enumReferenceList];
|
|
27
|
+
for (let i = candidateCopy.length - 1; i >= 0; i--) for (let j = referenceCopy.length - 1; j >= 0; j--) if (candidateCopy[i][1] === referenceCopy[j][1]) {
|
|
28
|
+
wordMatch.push([candidateCopy[i][0], referenceCopy[j][0]]);
|
|
29
|
+
candidateCopy.splice(i, 1);
|
|
30
|
+
referenceCopy.splice(j, 1);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
return [
|
|
34
|
+
wordMatch,
|
|
35
|
+
candidateCopy,
|
|
36
|
+
referenceCopy
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
async function matchStemEnums(enumCandidateList, enumReferenceList, stemmer) {
|
|
40
|
+
await ensureNaturalPackage();
|
|
41
|
+
require_invariant.invariant(PorterStemmer, "PorterStemmer should be loaded");
|
|
42
|
+
const actualStemmer = stemmer || PorterStemmer;
|
|
43
|
+
const candidateCopy = [...enumCandidateList];
|
|
44
|
+
const referenceCopy = [...enumReferenceList];
|
|
45
|
+
const candidateStems = candidateCopy.map(([idx, word]) => [idx, actualStemmer.stem(word)]);
|
|
46
|
+
const referenceStems = referenceCopy.map(([idx, word]) => [idx, actualStemmer.stem(word)]);
|
|
47
|
+
return matchExactEnums(candidateStems.map(([idx, stem]) => [idx, stem]), referenceStems.map(([idx, stem]) => [idx, stem]));
|
|
48
|
+
}
|
|
49
|
+
async function matchSynonymEnums(enumCandidateList, enumReferenceList, wordnet) {
|
|
50
|
+
await ensureNaturalPackage();
|
|
51
|
+
require_invariant.invariant(WordNet, "WordNet should be loaded");
|
|
52
|
+
const actualWordNet = wordnet || new WordNet();
|
|
53
|
+
const wordMatch = [];
|
|
54
|
+
const candidateCopy = [...enumCandidateList];
|
|
55
|
+
const referenceCopy = [...enumReferenceList];
|
|
56
|
+
for (let i = candidateCopy.length - 1; i >= 0; i--) {
|
|
57
|
+
const candidateWord = candidateCopy[i][1];
|
|
58
|
+
const candidateSynsets = await new Promise((resolve) => {
|
|
59
|
+
actualWordNet.lookup(candidateWord, (results) => resolve(results));
|
|
60
|
+
});
|
|
61
|
+
const candidateSynonymSet = new Set([candidateWord, ...candidateSynsets.flatMap((synset) => synset.synonyms.filter((syn) => !syn.includes("_")))]);
|
|
62
|
+
for (let j = referenceCopy.length - 1; j >= 0; j--) {
|
|
63
|
+
const referenceWord = referenceCopy[j][1];
|
|
64
|
+
if (candidateSynonymSet.has(referenceWord)) {
|
|
65
|
+
wordMatch.push([candidateCopy[i][0], referenceCopy[j][0]]);
|
|
66
|
+
candidateCopy.splice(i, 1);
|
|
67
|
+
referenceCopy.splice(j, 1);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return [
|
|
73
|
+
wordMatch,
|
|
74
|
+
candidateCopy,
|
|
75
|
+
referenceCopy
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
function countChunks(matches) {
|
|
79
|
+
if (matches.length === 0) return 0;
|
|
80
|
+
let chunks = 1;
|
|
81
|
+
for (let i = 0; i < matches.length - 1; i++) if (matches[i + 1][0] !== matches[i][0] + 1 || matches[i + 1][1] !== matches[i][1] + 1) chunks++;
|
|
82
|
+
return chunks;
|
|
83
|
+
}
|
|
84
|
+
async function calculateSingleMeteorScore(reference, candidate, alpha = .9, beta = 3, gamma = .5) {
|
|
85
|
+
const [enumCandidate, enumReference] = generateEnums(candidate, reference);
|
|
86
|
+
const translationLength = enumCandidate.length;
|
|
87
|
+
const referenceLength = enumReference.length;
|
|
88
|
+
const [exactMatches, remainingCandidate, remainingReference] = matchExactEnums(enumCandidate, enumReference);
|
|
89
|
+
const [stemMatches, remainingCandidateAfterStem, remainingReferenceAfterStem] = await matchStemEnums(remainingCandidate, remainingReference);
|
|
90
|
+
const [synonymMatches, ,] = await matchSynonymEnums(remainingCandidateAfterStem, remainingReferenceAfterStem);
|
|
91
|
+
const allMatches = [
|
|
92
|
+
...exactMatches,
|
|
93
|
+
...stemMatches,
|
|
94
|
+
...synonymMatches
|
|
95
|
+
].sort((a, b) => a[0] - b[0]);
|
|
96
|
+
const matchesCount = allMatches.length;
|
|
97
|
+
if (matchesCount === 0) return 0;
|
|
98
|
+
let fragFrac = 0;
|
|
99
|
+
let fmean = 0;
|
|
100
|
+
if (translationLength === 0 || referenceLength === 0 || matchesCount === 0) return 0;
|
|
101
|
+
const precision = matchesCount / translationLength;
|
|
102
|
+
const recall = matchesCount / referenceLength;
|
|
103
|
+
const denominator = alpha * precision + (1 - alpha) * recall;
|
|
104
|
+
if (denominator === 0) return 0;
|
|
105
|
+
fmean = precision * recall / denominator;
|
|
106
|
+
fragFrac = countChunks(allMatches) / matchesCount;
|
|
107
|
+
return (1 - gamma * Math.pow(fragFrac, beta)) * fmean;
|
|
108
|
+
}
|
|
109
|
+
async function calculateMeteorScore(candidate, references, alpha = .9, beta = 3, gamma = .5) {
|
|
110
|
+
if (!candidate || references.length === 0) throw new Error("Invalid inputs");
|
|
111
|
+
const scores = await Promise.all(references.map((reference) => calculateSingleMeteorScore(reference.split(/\s+/).map((word) => word.replace(/\.+$/, "")), candidate.split(/\s+/).map((word) => word.replace(/\.+$/, "")), alpha, beta, gamma)));
|
|
112
|
+
return Math.max(...scores);
|
|
113
|
+
}
|
|
114
|
+
async function handleMeteorAssertion({ assertion, inverse, outputString, renderedValue }) {
|
|
115
|
+
require_invariant.invariant(typeof renderedValue === "string" || Array.isArray(renderedValue) && renderedValue.every((v) => typeof v === "string"), "\"meteor\" assertion must have a string or array of strings value");
|
|
116
|
+
const references = Array.isArray(renderedValue) ? renderedValue : [renderedValue];
|
|
117
|
+
const meteorAssertion = assertion;
|
|
118
|
+
const alpha = meteorAssertion.alpha ?? .9;
|
|
119
|
+
const beta = meteorAssertion.beta ?? 3;
|
|
120
|
+
const gamma = meteorAssertion.gamma ?? .5;
|
|
121
|
+
const threshold = meteorAssertion.threshold ?? .5;
|
|
122
|
+
const score = await calculateMeteorScore(outputString, references, alpha, beta, gamma);
|
|
123
|
+
const pass = inverse ? score < threshold : score >= threshold;
|
|
124
|
+
return {
|
|
125
|
+
pass,
|
|
126
|
+
score: inverse ? 1 - score : score,
|
|
127
|
+
reason: pass ? "METEOR assertion passed" : `METEOR score ${score.toFixed(4)} did not meet threshold ${threshold}`,
|
|
128
|
+
assertion
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
exports.handleMeteorAssertion = handleMeteorAssertion;
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=meteor-DLZZ3osF.cjs.map
|