@opensearch-project/agent-health 0.0.1 → 0.1.0
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.txt +201 -0
- package/README.md +363 -0
- package/bin/cli.js +32 -0
- package/cli/dist/index.js +4293 -0
- package/dist/06363ae0dcb276526e56d844ae57f1eb2e16d1dc.svg +5 -0
- package/dist/17cc03b81ececabf3c8b3c3bf4b8203cd3028613.svg +5 -0
- package/dist/25f48f7350a1cb261d7ab5492972b53a075f1716.svg +5 -0
- package/dist/3d66ad340959f7e4ae00687e9f14adbd930abe01.svg +5 -0
- package/dist/621824624feb2bb70de09132809d9cce164b8bcb.svg +5 -0
- package/dist/81a42dbbd00769e7d823c228f5193c23f6c35e20.svg +5 -0
- package/dist/agent-health-style-guide.html +415 -0
- package/dist/assets/index-BheBjDce.css +1 -0
- package/dist/assets/index-aT-TLVpA.js +244 -0
- package/dist/assets/opensearch-logo-DV6ruVFq.svg +5 -0
- package/dist/index.html +22 -0
- package/dist/optimize-loop.svg +48 -0
- package/lib/dist/config/index.js +404 -0
- package/lib/dist/index.js +1527 -0
- package/package.json +142 -11
- package/server/dist/app.js +10449 -0
- package/server/dist/index.js +10476 -0
- package/index.js +0 -13
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<path d="M61.7374 23.5C60.4878 23.5 59.4748 24.513 59.4748 25.7626C59.4748 44.3813 44.3814 59.4748 25.7626 59.4748C24.513 59.4748 23.5 60.4878 23.5 61.7374C23.5 62.987 24.513 64 25.7626 64C46.8805 64 64 46.8805 64 25.7626C64 24.513 62.987 23.5 61.7374 23.5Z" fill="#00A3E0"/>
|
|
3
|
+
<path d="M48.0814 38C50.2572 34.4505 52.3615 29.7178 51.9475 23.0921C51.0899 9.36725 38.6589 -1.04463 26.9206 0.0837327C22.3253 0.525465 17.6068 4.2712 18.026 10.9805C18.2082 13.8961 19.6352 15.6169 21.9544 16.9399C24.1618 18.1992 26.9978 18.9969 30.2128 19.9011C34.0962 20.9934 38.6009 22.2203 42.0631 24.7717C46.2125 27.8295 49.0491 31.3743 48.0814 38Z" fill="#B9D9EB"/>
|
|
4
|
+
<path d="M3.91861 14C1.74276 17.5495 -0.361506 22.2822 0.0524931 28.9079C0.910072 42.6327 13.3411 53.0446 25.0794 51.9163C29.6747 51.4745 34.3932 47.7288 33.974 41.0195C33.7918 38.1039 32.3647 36.3831 30.0456 35.0601C27.8382 33.8008 25.0022 33.0031 21.7872 32.0989C17.9038 31.0066 13.3991 29.7797 9.93695 27.2283C5.78747 24.1704 2.95092 20.6257 3.91861 14Z" fill="#00A3E0"/>
|
|
5
|
+
</svg>
|
package/dist/index.html
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<!--
|
|
3
|
+
* Copyright OpenSearch Contributors
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
<html lang="en" class="dark h-full">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8" />
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
11
|
+
<title>Agent Health</title>
|
|
12
|
+
<link rel="icon" type="image/svg+xml" href="/assets/opensearch-logo-DV6ruVFq.svg" />
|
|
13
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
14
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
15
|
+
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&family=Source+Code+Pro:wght@400;500;600&display=swap" rel="stylesheet">
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-aT-TLVpA.js"></script>
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BheBjDce.css">
|
|
18
|
+
</head>
|
|
19
|
+
<body class="bg-background text-foreground antialiased h-full">
|
|
20
|
+
<div id="root" class="h-full"></div>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Simplified gradient for arrows -->
|
|
4
|
+
<linearGradient id="arrowGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
5
|
+
<stop offset="0%" stop-color="#3B82F6"/>
|
|
6
|
+
<stop offset="50%" stop-color="#8B5CF6"/>
|
|
7
|
+
<stop offset="100%" stop-color="#A855F7"/>
|
|
8
|
+
</linearGradient>
|
|
9
|
+
</defs>
|
|
10
|
+
|
|
11
|
+
<!-- Circular arrow path - simplified and bolder -->
|
|
12
|
+
<g opacity="0.9">
|
|
13
|
+
<!-- Top to Right -->
|
|
14
|
+
<path d="M 66 24 Q 90 36 90 60" stroke="url(#arrowGrad)" stroke-width="4" fill="none" stroke-linecap="round"/>
|
|
15
|
+
<polygon points="90,60 87,54 93,54" fill="#8B5CF6"/>
|
|
16
|
+
|
|
17
|
+
<!-- Right to Bottom -->
|
|
18
|
+
<path d="M 90 66 Q 90 90 66 96" stroke="url(#arrowGrad)" stroke-width="4" fill="none" stroke-linecap="round"/>
|
|
19
|
+
<polygon points="66,96 71,94 69,100" fill="#A855F7"/>
|
|
20
|
+
|
|
21
|
+
<!-- Bottom to Left -->
|
|
22
|
+
<path d="M 54 96 Q 30 90 30 66" stroke="url(#arrowGrad)" stroke-width="4" fill="none" stroke-linecap="round"/>
|
|
23
|
+
<polygon points="30,66 33,72 27,72" fill="#8B5CF6"/>
|
|
24
|
+
|
|
25
|
+
<!-- Left to Top -->
|
|
26
|
+
<path d="M 30 54 Q 30 30 54 24" stroke="url(#arrowGrad)" stroke-width="4" fill="none" stroke-linecap="round"/>
|
|
27
|
+
<polygon points="54,24 49,26 51,20" fill="#3B82F6"/>
|
|
28
|
+
</g>
|
|
29
|
+
|
|
30
|
+
<!-- Trace node - Top (Activity/waveform) -->
|
|
31
|
+
<g transform="translate(60, 21)">
|
|
32
|
+
<circle cx="0" cy="0" r="12" fill="#3B82F6"/>
|
|
33
|
+
<polyline points="-5,1.5 -3,-3 -1,1.5 1,-4.5 3,1.5 5,1.5" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
34
|
+
</g>
|
|
35
|
+
|
|
36
|
+
<!-- Evaluate node - Right (CheckCircle) -->
|
|
37
|
+
<g transform="translate(99, 81)">
|
|
38
|
+
<circle cx="0" cy="0" r="12" fill="#8B5CF6"/>
|
|
39
|
+
<circle cx="0" cy="0" r="5" stroke="white" stroke-width="2" fill="none"/>
|
|
40
|
+
<polyline points="-2,0 -0.5,2 3,-3" stroke="white" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
41
|
+
</g>
|
|
42
|
+
|
|
43
|
+
<!-- Improve node - Left (Shield) -->
|
|
44
|
+
<g transform="translate(21, 81)">
|
|
45
|
+
<circle cx="0" cy="0" r="12" fill="#A855F7"/>
|
|
46
|
+
<path d="M0 -5 L4 -3 L4 1.5 C4 3.5 2 5 0 5.5 C-2 5 -4 3.5 -4 1.5 L-4 -3 Z" fill="white"/>
|
|
47
|
+
</g>
|
|
48
|
+
</svg>
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
// lib/config/defineConfig.ts
|
|
2
|
+
function defineConfig(config) {
|
|
3
|
+
return config;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// lib/config/loader.ts
|
|
7
|
+
import { existsSync } from "fs";
|
|
8
|
+
import { resolve } from "path";
|
|
9
|
+
import { pathToFileURL } from "url";
|
|
10
|
+
|
|
11
|
+
// lib/debug.ts
|
|
12
|
+
var isBrowser = typeof window !== "undefined";
|
|
13
|
+
var serverDebugEnabled = !isBrowser && typeof process !== "undefined" && process.env?.DEBUG === "true";
|
|
14
|
+
function isDebugEnabled() {
|
|
15
|
+
if (isBrowser) {
|
|
16
|
+
try {
|
|
17
|
+
return localStorage.getItem("agenteval_debug") === "true";
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return serverDebugEnabled;
|
|
23
|
+
}
|
|
24
|
+
function debug(module, ...args) {
|
|
25
|
+
if (isDebugEnabled()) {
|
|
26
|
+
console.debug(`[${module}]`, ...args);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// lib/config.ts
|
|
31
|
+
var isServerSide = typeof window === "undefined";
|
|
32
|
+
var SERVER_PORT = isServerSide ? process.env?.VITE_BACKEND_PORT || process.env?.PORT || "4001" : "4001";
|
|
33
|
+
var BACKEND_URL = isServerSide ? `http://localhost:${SERVER_PORT}` : "";
|
|
34
|
+
var browserEnv = {};
|
|
35
|
+
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
36
|
+
try {
|
|
37
|
+
browserEnv = import.meta?.env || {};
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
var getEnvVar = (key, defaultValue) => {
|
|
42
|
+
if (isServerSide) {
|
|
43
|
+
return process.env?.[key] || defaultValue || "";
|
|
44
|
+
}
|
|
45
|
+
return browserEnv[key] || defaultValue || "";
|
|
46
|
+
};
|
|
47
|
+
var ENV_CONFIG = {
|
|
48
|
+
// Backend server - empty string means relative URLs
|
|
49
|
+
backendUrl: BACKEND_URL,
|
|
50
|
+
// API endpoints (derived from backend URL)
|
|
51
|
+
judgeApiUrl: `${BACKEND_URL}/api/judge`,
|
|
52
|
+
storageApiUrl: `${BACKEND_URL}/api/storage`,
|
|
53
|
+
agentProxyUrl: `${BACKEND_URL}/api/agent`,
|
|
54
|
+
openSearchProxyUrl: `${BACKEND_URL}/api/opensearch/logs`,
|
|
55
|
+
// AWS/Bedrock
|
|
56
|
+
awsRegion: getEnvVar("AWS_REGION", "us-east-1"),
|
|
57
|
+
awsProfile: getEnvVar("AWS_PROFILE", "default"),
|
|
58
|
+
bedrockModelId: getEnvVar("BEDROCK_MODEL_ID", "anthropic.claude-3-5-sonnet-20241022-v2:0"),
|
|
59
|
+
// OpenSearch Logs (for fetching agent observability data)
|
|
60
|
+
openSearchLogsEndpoint: getEnvVar("OPENSEARCH_LOGS_ENDPOINT", ""),
|
|
61
|
+
openSearchLogsUsername: getEnvVar("OPENSEARCH_LOGS_USERNAME", ""),
|
|
62
|
+
openSearchLogsPassword: getEnvVar("OPENSEARCH_LOGS_PASSWORD", ""),
|
|
63
|
+
openSearchLogsTracesIndex: getEnvVar("OPENSEARCH_LOGS_TRACES_INDEX", "otel-v1-apm-span-*"),
|
|
64
|
+
openSearchLogsIndex: getEnvVar("OPENSEARCH_LOGS_INDEX", "ml-commons-logs-*"),
|
|
65
|
+
// Per-agent endpoints
|
|
66
|
+
langgraphEndpoint: getEnvVar("LANGGRAPH_ENDPOINT", "http://localhost:3000"),
|
|
67
|
+
mlcommonsEndpoint: getEnvVar("MLCOMMONS_ENDPOINT", "http://localhost:9200/_plugins/_ml/agents/{agent_id}/_execute/stream"),
|
|
68
|
+
holmesGptEndpoint: getEnvVar("HOLMESGPT_ENDPOINT", "http://localhost:5050/api/agui/chat"),
|
|
69
|
+
// ML-Commons agent headers
|
|
70
|
+
mlcommonsHeaderOpenSearchUrl: getEnvVar("MLCOMMONS_HEADER_OPENSEARCH_URL", ""),
|
|
71
|
+
mlcommonsHeaderAuthorization: getEnvVar("MLCOMMONS_HEADER_AUTHORIZATION", ""),
|
|
72
|
+
mlcommonsHeaderAwsRegion: getEnvVar("MLCOMMONS_HEADER_AWS_REGION", ""),
|
|
73
|
+
mlcommonsHeaderAwsServiceName: getEnvVar("MLCOMMONS_HEADER_AWS_SERVICE_NAME", "es"),
|
|
74
|
+
mlcommonsHeaderAwsAccessKeyId: getEnvVar("MLCOMMONS_HEADER_AWS_ACCESS_KEY_ID", ""),
|
|
75
|
+
mlcommonsHeaderAwsSecretAccessKey: getEnvVar("MLCOMMONS_HEADER_AWS_SECRET_ACCESS_KEY", ""),
|
|
76
|
+
mlcommonsHeaderAwsSessionToken: getEnvVar("MLCOMMONS_HEADER_AWS_SESSION_TOKEN", ""),
|
|
77
|
+
// Claude Code Telemetry (optional - for OTEL traces from Claude Code)
|
|
78
|
+
claudeCodeTelemetryEnabled: getEnvVar("CLAUDE_CODE_TELEMETRY_ENABLED", "false") === "true",
|
|
79
|
+
otelExporterEndpoint: getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT", ""),
|
|
80
|
+
otelServiceName: getEnvVar("OTEL_SERVICE_NAME", "claude-code-agent"),
|
|
81
|
+
otelExporterProtocol: getEnvVar("OTEL_EXPORTER_OTLP_PROTOCOL", ""),
|
|
82
|
+
otelExporterHeaders: getEnvVar("OTEL_EXPORTER_OTLP_HEADERS", "")
|
|
83
|
+
};
|
|
84
|
+
function buildMLCommonsHeaders() {
|
|
85
|
+
debug("Config", "Building ML-Commons headers");
|
|
86
|
+
const headers = {};
|
|
87
|
+
if (ENV_CONFIG.mlcommonsHeaderOpenSearchUrl) {
|
|
88
|
+
headers["opensearch-url"] = ENV_CONFIG.mlcommonsHeaderOpenSearchUrl;
|
|
89
|
+
}
|
|
90
|
+
if (ENV_CONFIG.mlcommonsHeaderAwsRegion) {
|
|
91
|
+
headers["aws-region"] = ENV_CONFIG.mlcommonsHeaderAwsRegion;
|
|
92
|
+
}
|
|
93
|
+
if (ENV_CONFIG.mlcommonsHeaderAuthorization) {
|
|
94
|
+
headers["Authorization"] = ENV_CONFIG.mlcommonsHeaderAuthorization;
|
|
95
|
+
} else {
|
|
96
|
+
if (ENV_CONFIG.mlcommonsHeaderAwsServiceName) {
|
|
97
|
+
headers["aws-service-name"] = ENV_CONFIG.mlcommonsHeaderAwsServiceName;
|
|
98
|
+
}
|
|
99
|
+
if (ENV_CONFIG.mlcommonsHeaderAwsAccessKeyId) {
|
|
100
|
+
headers["aws-access-key-id"] = ENV_CONFIG.mlcommonsHeaderAwsAccessKeyId;
|
|
101
|
+
}
|
|
102
|
+
if (ENV_CONFIG.mlcommonsHeaderAwsSecretAccessKey) {
|
|
103
|
+
headers["aws-secret-access-key"] = ENV_CONFIG.mlcommonsHeaderAwsSecretAccessKey;
|
|
104
|
+
}
|
|
105
|
+
if (ENV_CONFIG.mlcommonsHeaderAwsSessionToken) {
|
|
106
|
+
headers["aws-session-token"] = ENV_CONFIG.mlcommonsHeaderAwsSessionToken;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
debug("Config", "ML-Commons headers built, keys:", Object.keys(headers));
|
|
110
|
+
return headers;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// lib/constants.ts
|
|
114
|
+
function getClaudeCodeConnectorEnv() {
|
|
115
|
+
const env = {
|
|
116
|
+
AWS_PROFILE: process.env.AWS_PROFILE || "Bedrock",
|
|
117
|
+
CLAUDE_CODE_USE_BEDROCK: "1",
|
|
118
|
+
AWS_REGION: process.env.AWS_REGION || "us-west-2",
|
|
119
|
+
DISABLE_PROMPT_CACHING: "1",
|
|
120
|
+
DISABLE_ERROR_REPORTING: "1"
|
|
121
|
+
};
|
|
122
|
+
if (ENV_CONFIG.claudeCodeTelemetryEnabled && ENV_CONFIG.otelExporterEndpoint) {
|
|
123
|
+
env.CLAUDE_CODE_ENABLE_TELEMETRY = "1";
|
|
124
|
+
env.OTEL_EXPORTER_OTLP_ENDPOINT = ENV_CONFIG.otelExporterEndpoint;
|
|
125
|
+
env.OTEL_SERVICE_NAME = ENV_CONFIG.otelServiceName;
|
|
126
|
+
if (ENV_CONFIG.otelExporterProtocol) {
|
|
127
|
+
env.OTEL_EXPORTER_OTLP_PROTOCOL = ENV_CONFIG.otelExporterProtocol;
|
|
128
|
+
}
|
|
129
|
+
if (ENV_CONFIG.otelExporterHeaders) {
|
|
130
|
+
env.OTEL_EXPORTER_OTLP_HEADERS = ENV_CONFIG.otelExporterHeaders;
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
env.DISABLE_TELEMETRY = "1";
|
|
134
|
+
}
|
|
135
|
+
return env;
|
|
136
|
+
}
|
|
137
|
+
var DEFAULT_CONFIG = {
|
|
138
|
+
agents: [
|
|
139
|
+
{
|
|
140
|
+
key: "demo",
|
|
141
|
+
name: "Demo Agent",
|
|
142
|
+
endpoint: "mock://demo",
|
|
143
|
+
description: "Mock agent for testing (simulated responses)",
|
|
144
|
+
connectorType: "mock",
|
|
145
|
+
models: ["demo-model"],
|
|
146
|
+
headers: {},
|
|
147
|
+
useTraces: false
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
key: "langgraph",
|
|
151
|
+
name: "Langgraph",
|
|
152
|
+
endpoint: ENV_CONFIG.langgraphEndpoint,
|
|
153
|
+
description: "Langgraph AG-UI agent server",
|
|
154
|
+
connectorType: "agui-streaming",
|
|
155
|
+
models: [
|
|
156
|
+
"claude-sonnet-4.5",
|
|
157
|
+
"claude-sonnet-4",
|
|
158
|
+
"claude-haiku-3.5"
|
|
159
|
+
],
|
|
160
|
+
headers: {},
|
|
161
|
+
useTraces: true
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
key: "mlcommons-local",
|
|
165
|
+
name: "ML-Commons (Localhost)",
|
|
166
|
+
endpoint: ENV_CONFIG.mlcommonsEndpoint,
|
|
167
|
+
description: "Local OpenSearch ML-Commons conversational agent",
|
|
168
|
+
connectorType: "agui-streaming",
|
|
169
|
+
models: [
|
|
170
|
+
"claude-sonnet-4.5",
|
|
171
|
+
"claude-sonnet-4",
|
|
172
|
+
"claude-haiku-3.5"
|
|
173
|
+
],
|
|
174
|
+
headers: buildMLCommonsHeaders(),
|
|
175
|
+
useTraces: true
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
key: "holmesgpt",
|
|
179
|
+
name: "HolmesGPT",
|
|
180
|
+
endpoint: ENV_CONFIG.holmesGptEndpoint,
|
|
181
|
+
description: "HolmesGPT AI-powered RCA agent (AG-UI)",
|
|
182
|
+
connectorType: "agui-streaming",
|
|
183
|
+
models: [
|
|
184
|
+
"claude-sonnet-4.5",
|
|
185
|
+
"claude-sonnet-4",
|
|
186
|
+
"claude-haiku-3.5"
|
|
187
|
+
],
|
|
188
|
+
headers: {},
|
|
189
|
+
useTraces: true
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
key: "claude-code",
|
|
193
|
+
name: "Claude Code",
|
|
194
|
+
endpoint: "claude",
|
|
195
|
+
// Command name, not URL
|
|
196
|
+
description: "Claude Code CLI agent (requires claude command installed)",
|
|
197
|
+
connectorType: "claude-code",
|
|
198
|
+
models: ["claude-sonnet-4"],
|
|
199
|
+
headers: {},
|
|
200
|
+
get useTraces() {
|
|
201
|
+
return !!(ENV_CONFIG.claudeCodeTelemetryEnabled && ENV_CONFIG.otelExporterEndpoint);
|
|
202
|
+
},
|
|
203
|
+
// connectorConfig env vars are evaluated at runtime by getClaudeCodeConnectorEnv()
|
|
204
|
+
get connectorConfig() {
|
|
205
|
+
return {
|
|
206
|
+
env: getClaudeCodeConnectorEnv()
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
models: {
|
|
212
|
+
"demo-model": {
|
|
213
|
+
model_id: "mock://demo-model",
|
|
214
|
+
display_name: "Demo Model",
|
|
215
|
+
provider: "demo",
|
|
216
|
+
context_window: 2e5,
|
|
217
|
+
max_output_tokens: 4096
|
|
218
|
+
},
|
|
219
|
+
"claude-sonnet-4.5": {
|
|
220
|
+
model_id: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
221
|
+
display_name: "Claude Sonnet 4.5",
|
|
222
|
+
provider: "bedrock",
|
|
223
|
+
context_window: 2e5,
|
|
224
|
+
max_output_tokens: 4096
|
|
225
|
+
},
|
|
226
|
+
"claude-sonnet-4": {
|
|
227
|
+
model_id: "us.anthropic.claude-sonnet-4-20250514-v1:0",
|
|
228
|
+
display_name: "Claude Sonnet 4",
|
|
229
|
+
provider: "bedrock",
|
|
230
|
+
context_window: 2e5,
|
|
231
|
+
max_output_tokens: 4096
|
|
232
|
+
},
|
|
233
|
+
"claude-haiku-3.5": {
|
|
234
|
+
model_id: "us.anthropic.claude-3-5-haiku-20241022-v1:0",
|
|
235
|
+
display_name: "Claude Haiku 3.5",
|
|
236
|
+
provider: "bedrock",
|
|
237
|
+
context_window: 2e5,
|
|
238
|
+
max_output_tokens: 4096
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
defaults: {
|
|
242
|
+
retry_attempts: 2,
|
|
243
|
+
retry_delay_ms: 1e3
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// lib/config/loader.ts
|
|
248
|
+
var DEFAULT_SERVER_CONFIG = {
|
|
249
|
+
port: 4001,
|
|
250
|
+
reuseExistingServer: !process.env.CI,
|
|
251
|
+
startTimeout: 3e4
|
|
252
|
+
};
|
|
253
|
+
var CONFIG_FILE_NAMES = [
|
|
254
|
+
"agent-health.config.ts",
|
|
255
|
+
"agent-health.config.js",
|
|
256
|
+
"agent-health.config.mjs"
|
|
257
|
+
];
|
|
258
|
+
function findConfigFile(cwd = process.cwd()) {
|
|
259
|
+
for (const fileName of CONFIG_FILE_NAMES) {
|
|
260
|
+
const filePath = resolve(cwd, fileName);
|
|
261
|
+
if (existsSync(filePath)) {
|
|
262
|
+
const format = fileName.endsWith(".ts") ? "typescript" : "javascript";
|
|
263
|
+
return { path: filePath, format, exists: true };
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
function toAgentConfig(userAgent) {
|
|
269
|
+
return {
|
|
270
|
+
key: userAgent.key,
|
|
271
|
+
name: userAgent.name,
|
|
272
|
+
endpoint: userAgent.endpoint,
|
|
273
|
+
description: userAgent.description,
|
|
274
|
+
enabled: userAgent.enabled ?? true,
|
|
275
|
+
models: userAgent.models,
|
|
276
|
+
headers: userAgent.headers ?? {},
|
|
277
|
+
useTraces: userAgent.useTraces ?? false,
|
|
278
|
+
connectorType: userAgent.connectorType,
|
|
279
|
+
connectorConfig: userAgent.connectorConfig,
|
|
280
|
+
hooks: userAgent.hooks
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function toModelConfig(userModel) {
|
|
284
|
+
return [
|
|
285
|
+
userModel.key,
|
|
286
|
+
{
|
|
287
|
+
model_id: userModel.model_id,
|
|
288
|
+
display_name: userModel.display_name,
|
|
289
|
+
provider: userModel.provider ?? "bedrock",
|
|
290
|
+
context_window: userModel.context_window ?? 2e5,
|
|
291
|
+
max_output_tokens: userModel.max_output_tokens ?? 4096
|
|
292
|
+
}
|
|
293
|
+
];
|
|
294
|
+
}
|
|
295
|
+
function mergeConfigs(userConfig, defaultConfig) {
|
|
296
|
+
const shouldExtend = userConfig.extends !== false;
|
|
297
|
+
let agents;
|
|
298
|
+
if (shouldExtend) {
|
|
299
|
+
const agentMap = /* @__PURE__ */ new Map();
|
|
300
|
+
for (const agent of defaultConfig.agents) {
|
|
301
|
+
agentMap.set(agent.key, agent);
|
|
302
|
+
}
|
|
303
|
+
for (const userAgent of userConfig.agents ?? []) {
|
|
304
|
+
agentMap.set(userAgent.key, toAgentConfig(userAgent));
|
|
305
|
+
}
|
|
306
|
+
agents = Array.from(agentMap.values());
|
|
307
|
+
} else {
|
|
308
|
+
agents = (userConfig.agents ?? []).map(toAgentConfig);
|
|
309
|
+
}
|
|
310
|
+
let models;
|
|
311
|
+
if (shouldExtend) {
|
|
312
|
+
models = { ...defaultConfig.models };
|
|
313
|
+
for (const userModel of userConfig.models ?? []) {
|
|
314
|
+
const [key, config] = toModelConfig(userModel);
|
|
315
|
+
models[key] = config;
|
|
316
|
+
}
|
|
317
|
+
} else {
|
|
318
|
+
models = {};
|
|
319
|
+
for (const userModel of userConfig.models ?? []) {
|
|
320
|
+
const [key, config] = toModelConfig(userModel);
|
|
321
|
+
models[key] = config;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const connectors = userConfig.connectors ?? [];
|
|
325
|
+
const testCases = userConfig.testCases ? Array.isArray(userConfig.testCases) ? userConfig.testCases : [userConfig.testCases] : [];
|
|
326
|
+
const reporters = userConfig.reporters ?? [["console"]];
|
|
327
|
+
const judge = userConfig.judge ?? {
|
|
328
|
+
provider: "bedrock",
|
|
329
|
+
model: "claude-sonnet-4"
|
|
330
|
+
};
|
|
331
|
+
const server = {
|
|
332
|
+
...DEFAULT_SERVER_CONFIG,
|
|
333
|
+
...userConfig.server
|
|
334
|
+
};
|
|
335
|
+
return {
|
|
336
|
+
server,
|
|
337
|
+
agents,
|
|
338
|
+
models,
|
|
339
|
+
connectors,
|
|
340
|
+
testCases,
|
|
341
|
+
reporters,
|
|
342
|
+
judge
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
async function loadUserConfig(configPath) {
|
|
346
|
+
try {
|
|
347
|
+
const fileUrl = pathToFileURL(configPath).href;
|
|
348
|
+
const module = await import(fileUrl);
|
|
349
|
+
return module.default ?? module;
|
|
350
|
+
} catch (error) {
|
|
351
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
352
|
+
throw new Error(`Failed to load config file ${configPath}: ${message}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
var cachedConfig = null;
|
|
356
|
+
var cachedConfigPath = null;
|
|
357
|
+
async function loadConfig(cwd = process.cwd(), force = false) {
|
|
358
|
+
const configFile = findConfigFile(cwd);
|
|
359
|
+
if (!force && cachedConfig && cachedConfigPath === configFile?.path) {
|
|
360
|
+
return cachedConfig;
|
|
361
|
+
}
|
|
362
|
+
let userConfig = {};
|
|
363
|
+
if (configFile) {
|
|
364
|
+
console.log(`[Config] Loading ${configFile.path}`);
|
|
365
|
+
userConfig = await loadUserConfig(configFile.path);
|
|
366
|
+
} else {
|
|
367
|
+
console.log("[Config] No config file found, using defaults + environment variables");
|
|
368
|
+
}
|
|
369
|
+
const resolved = mergeConfigs(userConfig, DEFAULT_CONFIG);
|
|
370
|
+
cachedConfig = resolved;
|
|
371
|
+
cachedConfigPath = configFile?.path ?? null;
|
|
372
|
+
console.log(`[Config] Loaded ${resolved.agents.length} agents, ${Object.keys(resolved.models).length} models`);
|
|
373
|
+
return resolved;
|
|
374
|
+
}
|
|
375
|
+
function loadConfigSync(cwd = process.cwd()) {
|
|
376
|
+
if (cachedConfig) {
|
|
377
|
+
return cachedConfig;
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
server: DEFAULT_SERVER_CONFIG,
|
|
381
|
+
agents: DEFAULT_CONFIG.agents,
|
|
382
|
+
models: DEFAULT_CONFIG.models,
|
|
383
|
+
connectors: [],
|
|
384
|
+
testCases: [],
|
|
385
|
+
reporters: [["console"]],
|
|
386
|
+
judge: { provider: "bedrock", model: "claude-sonnet-4" }
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function clearConfigCache() {
|
|
390
|
+
cachedConfig = null;
|
|
391
|
+
cachedConfigPath = null;
|
|
392
|
+
}
|
|
393
|
+
function getConfigFileInfo(cwd = process.cwd()) {
|
|
394
|
+
return findConfigFile(cwd);
|
|
395
|
+
}
|
|
396
|
+
export {
|
|
397
|
+
DEFAULT_SERVER_CONFIG,
|
|
398
|
+
clearConfigCache,
|
|
399
|
+
defineConfig,
|
|
400
|
+
findConfigFile,
|
|
401
|
+
getConfigFileInfo,
|
|
402
|
+
loadConfig,
|
|
403
|
+
loadConfigSync
|
|
404
|
+
};
|