@opensearch-project/agent-health 0.1.0 → 0.2.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/README.md +108 -72
- package/cli/dist/index.js +1132 -351
- package/dist/assets/index-4BAkkFzo.js +267 -0
- package/dist/assets/index-C3K5cBQr.css +1 -0
- package/dist/index.html +2 -2
- package/dist/opensearch-logo-dark.svg +5 -0
- package/dist/opensearch-logo-light.svg +5 -0
- package/dist/test-first-run-improved.html +469 -0
- package/lib/dist/config/index.js +107 -107
- package/lib/dist/index.js +151 -13
- package/package.json +12 -4
- package/server/dist/app.js +12726 -7693
- package/server/dist/index.js +12728 -7697
- package/dist/assets/index-BheBjDce.css +0 -1
- package/dist/assets/index-aT-TLVpA.js +0 -244
package/lib/dist/config/index.js
CHANGED
|
@@ -8,25 +8,6 @@ import { existsSync } from "fs";
|
|
|
8
8
|
import { resolve } from "path";
|
|
9
9
|
import { pathToFileURL } from "url";
|
|
10
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
11
|
// lib/config.ts
|
|
31
12
|
var isServerSide = typeof window === "undefined";
|
|
32
13
|
var SERVER_PORT = isServerSide ? process.env?.VITE_BACKEND_PORT || process.env?.PORT || "4001" : "4001";
|
|
@@ -62,10 +43,8 @@ var ENV_CONFIG = {
|
|
|
62
43
|
openSearchLogsPassword: getEnvVar("OPENSEARCH_LOGS_PASSWORD", ""),
|
|
63
44
|
openSearchLogsTracesIndex: getEnvVar("OPENSEARCH_LOGS_TRACES_INDEX", "otel-v1-apm-span-*"),
|
|
64
45
|
openSearchLogsIndex: getEnvVar("OPENSEARCH_LOGS_INDEX", "ml-commons-logs-*"),
|
|
65
|
-
//
|
|
66
|
-
langgraphEndpoint: getEnvVar("LANGGRAPH_ENDPOINT", "http://localhost:3000"),
|
|
46
|
+
// ML-Commons agent endpoint
|
|
67
47
|
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
48
|
// ML-Commons agent headers
|
|
70
49
|
mlcommonsHeaderOpenSearchUrl: getEnvVar("MLCOMMONS_HEADER_OPENSEARCH_URL", ""),
|
|
71
50
|
mlcommonsHeaderAuthorization: getEnvVar("MLCOMMONS_HEADER_AUTHORIZATION", ""),
|
|
@@ -74,6 +53,11 @@ var ENV_CONFIG = {
|
|
|
74
53
|
mlcommonsHeaderAwsAccessKeyId: getEnvVar("MLCOMMONS_HEADER_AWS_ACCESS_KEY_ID", ""),
|
|
75
54
|
mlcommonsHeaderAwsSecretAccessKey: getEnvVar("MLCOMMONS_HEADER_AWS_SECRET_ACCESS_KEY", ""),
|
|
76
55
|
mlcommonsHeaderAwsSessionToken: getEnvVar("MLCOMMONS_HEADER_AWS_SESSION_TOKEN", ""),
|
|
56
|
+
// Travel Planner multi-agent endpoint (OTel Demo in Docker)
|
|
57
|
+
travelPlannerEndpoint: getEnvVar("TRAVEL_PLANNER_ENDPOINT", "http://localhost:3000"),
|
|
58
|
+
// OpenAI-compatible (optional - for OpenAI-compatible judge/agent endpoints)
|
|
59
|
+
openaiCompatibleApiKey: getEnvVar("OPENAI_COMPATIBLE_API_KEY", ""),
|
|
60
|
+
openaiCompatibleEndpoint: getEnvVar("OPENAI_COMPATIBLE_ENDPOINT", "http://localhost:4000/v1/chat/completions"),
|
|
77
61
|
// Claude Code Telemetry (optional - for OTEL traces from Claude Code)
|
|
78
62
|
claudeCodeTelemetryEnabled: getEnvVar("CLAUDE_CODE_TELEMETRY_ENABLED", "false") === "true",
|
|
79
63
|
otelExporterEndpoint: getEnvVar("OTEL_EXPORTER_OTLP_ENDPOINT", ""),
|
|
@@ -81,41 +65,47 @@ var ENV_CONFIG = {
|
|
|
81
65
|
otelExporterProtocol: getEnvVar("OTEL_EXPORTER_OTLP_PROTOCOL", ""),
|
|
82
66
|
otelExporterHeaders: getEnvVar("OTEL_EXPORTER_OTLP_HEADERS", "")
|
|
83
67
|
};
|
|
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
68
|
|
|
113
69
|
// lib/constants.ts
|
|
70
|
+
var CONNECTOR_TYPE_INFO = {
|
|
71
|
+
"agui-streaming": {
|
|
72
|
+
label: "AG-UI Streaming",
|
|
73
|
+
description: "AG-UI protocol over SSE. Use for ML-Commons and AG-UI compatible agents.",
|
|
74
|
+
serverOnly: false
|
|
75
|
+
},
|
|
76
|
+
"rest": {
|
|
77
|
+
label: "REST",
|
|
78
|
+
description: "Standard HTTP POST. Agent receives JSON, returns JSON. No streaming.",
|
|
79
|
+
serverOnly: false
|
|
80
|
+
},
|
|
81
|
+
"openai-compatible": {
|
|
82
|
+
label: "OpenAI Compatible",
|
|
83
|
+
description: "OpenAI chat completions format (POST /v1/chat/completions). Works with LiteLLM, Ollama, vLLM.",
|
|
84
|
+
serverOnly: false
|
|
85
|
+
},
|
|
86
|
+
"subprocess": {
|
|
87
|
+
label: "Subprocess",
|
|
88
|
+
description: "Runs a CLI command as a child process. Server-only \u2014 use the CLI or benchmark runner.",
|
|
89
|
+
serverOnly: true
|
|
90
|
+
},
|
|
91
|
+
"claude-code": {
|
|
92
|
+
label: "Claude Code",
|
|
93
|
+
description: "Invokes the Claude Code CLI. Server-only \u2014 use the CLI or benchmark runner.",
|
|
94
|
+
serverOnly: true
|
|
95
|
+
},
|
|
96
|
+
"mock": {
|
|
97
|
+
label: "Mock",
|
|
98
|
+
description: "Built-in demo agent for testing. No real endpoint needed.",
|
|
99
|
+
serverOnly: false
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var VALID_CONNECTOR_TYPES = Object.keys(CONNECTOR_TYPE_INFO);
|
|
103
|
+
var BROWSER_SAFE_CONNECTORS = Object.entries(CONNECTOR_TYPE_INFO).filter(([, info]) => !info.serverOnly).map(([type]) => type);
|
|
114
104
|
function getClaudeCodeConnectorEnv() {
|
|
115
105
|
const env = {
|
|
116
|
-
AWS_PROFILE:
|
|
106
|
+
AWS_PROFILE: ENV_CONFIG.awsProfile || "Bedrock",
|
|
117
107
|
CLAUDE_CODE_USE_BEDROCK: "1",
|
|
118
|
-
AWS_REGION:
|
|
108
|
+
AWS_REGION: ENV_CONFIG.awsRegion || "us-west-2",
|
|
119
109
|
DISABLE_PROMPT_CACHING: "1",
|
|
120
110
|
DISABLE_ERROR_REPORTING: "1"
|
|
121
111
|
};
|
|
@@ -142,70 +132,18 @@ var DEFAULT_CONFIG = {
|
|
|
142
132
|
endpoint: "mock://demo",
|
|
143
133
|
description: "Mock agent for testing (simulated responses)",
|
|
144
134
|
connectorType: "mock",
|
|
145
|
-
models: ["demo-model"],
|
|
146
135
|
headers: {},
|
|
147
136
|
useTraces: false
|
|
148
137
|
},
|
|
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
138
|
{
|
|
192
139
|
key: "claude-code",
|
|
193
140
|
name: "Claude Code",
|
|
194
141
|
endpoint: "claude",
|
|
195
|
-
// Command name, not URL
|
|
196
142
|
description: "Claude Code CLI agent (requires claude command installed)",
|
|
197
143
|
connectorType: "claude-code",
|
|
198
|
-
models: ["claude-sonnet-4"],
|
|
199
144
|
headers: {},
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
},
|
|
203
|
-
// connectorConfig env vars are evaluated at runtime by getClaudeCodeConnectorEnv()
|
|
204
|
-
get connectorConfig() {
|
|
205
|
-
return {
|
|
206
|
-
env: getClaudeCodeConnectorEnv()
|
|
207
|
-
};
|
|
208
|
-
}
|
|
145
|
+
useTraces: ENV_CONFIG.claudeCodeTelemetryEnabled && !!ENV_CONFIG.otelExporterEndpoint,
|
|
146
|
+
connectorConfig: { env: getClaudeCodeConnectorEnv() }
|
|
209
147
|
}
|
|
210
148
|
],
|
|
211
149
|
models: {
|
|
@@ -216,6 +154,48 @@ var DEFAULT_CONFIG = {
|
|
|
216
154
|
context_window: 2e5,
|
|
217
155
|
max_output_tokens: 4096
|
|
218
156
|
},
|
|
157
|
+
"claude-opus-4.6": {
|
|
158
|
+
model_id: "us.anthropic.claude-opus-4-6-v1",
|
|
159
|
+
display_name: "Claude Opus 4.6",
|
|
160
|
+
provider: "bedrock",
|
|
161
|
+
context_window: 2e5,
|
|
162
|
+
max_output_tokens: 128e3
|
|
163
|
+
},
|
|
164
|
+
"claude-sonnet-4.6": {
|
|
165
|
+
model_id: "us.anthropic.claude-sonnet-4-6",
|
|
166
|
+
display_name: "Claude Sonnet 4.6",
|
|
167
|
+
provider: "bedrock",
|
|
168
|
+
context_window: 2e5,
|
|
169
|
+
max_output_tokens: 64e3
|
|
170
|
+
},
|
|
171
|
+
"claude-haiku-4.5": {
|
|
172
|
+
model_id: "us.anthropic.claude-haiku-4-5-20251001-v1:0",
|
|
173
|
+
display_name: "Claude Haiku 4.5",
|
|
174
|
+
provider: "bedrock",
|
|
175
|
+
context_window: 2e5,
|
|
176
|
+
max_output_tokens: 64e3
|
|
177
|
+
},
|
|
178
|
+
"claude-opus-4.5": {
|
|
179
|
+
model_id: "us.anthropic.claude-opus-4-5-20251101-v1:0",
|
|
180
|
+
display_name: "Claude Opus 4.5",
|
|
181
|
+
provider: "bedrock",
|
|
182
|
+
context_window: 2e5,
|
|
183
|
+
max_output_tokens: 64e3
|
|
184
|
+
},
|
|
185
|
+
"claude-opus-4.1": {
|
|
186
|
+
model_id: "us.anthropic.claude-opus-4-1-20250805-v1:0",
|
|
187
|
+
display_name: "Claude Opus 4.1",
|
|
188
|
+
provider: "bedrock",
|
|
189
|
+
context_window: 2e5,
|
|
190
|
+
max_output_tokens: 32e3
|
|
191
|
+
},
|
|
192
|
+
"claude-opus-4": {
|
|
193
|
+
model_id: "us.anthropic.claude-opus-4-20250514-v1:0",
|
|
194
|
+
display_name: "Claude Opus 4",
|
|
195
|
+
provider: "bedrock",
|
|
196
|
+
context_window: 2e5,
|
|
197
|
+
max_output_tokens: 32e3
|
|
198
|
+
},
|
|
219
199
|
"claude-sonnet-4.5": {
|
|
220
200
|
model_id: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
|
|
221
201
|
display_name: "Claude Sonnet 4.5",
|
|
@@ -236,6 +216,27 @@ var DEFAULT_CONFIG = {
|
|
|
236
216
|
provider: "bedrock",
|
|
237
217
|
context_window: 2e5,
|
|
238
218
|
max_output_tokens: 4096
|
|
219
|
+
},
|
|
220
|
+
"gpt-4o": {
|
|
221
|
+
model_id: "gpt-4o",
|
|
222
|
+
display_name: "GPT-4o",
|
|
223
|
+
provider: "openai-compatible",
|
|
224
|
+
context_window: 128e3,
|
|
225
|
+
max_output_tokens: 4096
|
|
226
|
+
},
|
|
227
|
+
"deepseek-r1:8b": {
|
|
228
|
+
model_id: "deepseek-r1:8b",
|
|
229
|
+
display_name: "DeepSeek R1 8B (Ollama)",
|
|
230
|
+
provider: "openai-compatible",
|
|
231
|
+
context_window: 128e3,
|
|
232
|
+
max_output_tokens: 8192
|
|
233
|
+
},
|
|
234
|
+
"gemma3:12b": {
|
|
235
|
+
model_id: "gemma3:12b",
|
|
236
|
+
display_name: "Gemma 3 12B (Ollama)",
|
|
237
|
+
provider: "openai-compatible",
|
|
238
|
+
context_window: 128e3,
|
|
239
|
+
max_output_tokens: 8192
|
|
239
240
|
}
|
|
240
241
|
},
|
|
241
242
|
defaults: {
|
|
@@ -272,7 +273,6 @@ function toAgentConfig(userAgent) {
|
|
|
272
273
|
endpoint: userAgent.endpoint,
|
|
273
274
|
description: userAgent.description,
|
|
274
275
|
enabled: userAgent.enabled ?? true,
|
|
275
|
-
models: userAgent.models,
|
|
276
276
|
headers: userAgent.headers ?? {},
|
|
277
277
|
useTraces: userAgent.useTraces ?? false,
|
|
278
278
|
connectorType: userAgent.connectorType,
|
package/lib/dist/index.js
CHANGED
|
@@ -4,8 +4,27 @@ function defineConfig(config) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
// lib/debug.ts
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import path from "path";
|
|
7
9
|
var isBrowser = typeof window !== "undefined";
|
|
8
|
-
var
|
|
10
|
+
var CONFIG_FILENAME = "agent-health.config.json";
|
|
11
|
+
var serverDebugEnabled = false;
|
|
12
|
+
if (!isBrowser) {
|
|
13
|
+
try {
|
|
14
|
+
const configPath = path.join(process.cwd(), CONFIG_FILENAME);
|
|
15
|
+
if (fs.existsSync(configPath)) {
|
|
16
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
17
|
+
const config = JSON.parse(content) || {};
|
|
18
|
+
serverDebugEnabled = config.debug === true;
|
|
19
|
+
} else if (process.env?.DEBUG === "true") {
|
|
20
|
+
serverDebugEnabled = true;
|
|
21
|
+
}
|
|
22
|
+
} catch (err) {
|
|
23
|
+
if (process.env?.DEBUG === "true") {
|
|
24
|
+
serverDebugEnabled = true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
9
28
|
function isDebugEnabled() {
|
|
10
29
|
if (isBrowser) {
|
|
11
30
|
try {
|
|
@@ -152,9 +171,11 @@ var SSEClient = class {
|
|
|
152
171
|
this.abortController = new AbortController();
|
|
153
172
|
debug("SSE", "Connecting to", url);
|
|
154
173
|
debug("SSE", "Method:", method);
|
|
155
|
-
debug("SSE", "
|
|
174
|
+
debug("SSE", "Headers:", headers);
|
|
175
|
+
debug("SSE", "Payload:", body ? JSON.stringify(body, null, 2).substring(0, 500) : "none");
|
|
176
|
+
debug("SSE", "Timeout:", idleTimeoutMs, "ms");
|
|
156
177
|
try {
|
|
157
|
-
const
|
|
178
|
+
const requestConfig = {
|
|
158
179
|
method,
|
|
159
180
|
headers: {
|
|
160
181
|
"Content-Type": "application/json",
|
|
@@ -163,17 +184,28 @@ var SSEClient = class {
|
|
|
163
184
|
},
|
|
164
185
|
body: body ? JSON.stringify(body) : void 0,
|
|
165
186
|
signal: this.abortController.signal
|
|
166
|
-
}
|
|
187
|
+
};
|
|
188
|
+
debug("SSE", "Request config:", JSON.stringify(requestConfig, null, 2).substring(0, 500));
|
|
189
|
+
const response = await fetch(url, requestConfig);
|
|
190
|
+
debug("SSE", "Response received:", response.status, response.statusText);
|
|
167
191
|
if (!response.ok) {
|
|
168
|
-
|
|
192
|
+
let errorBody = "";
|
|
193
|
+
try {
|
|
194
|
+
errorBody = await response.text();
|
|
195
|
+
debug("SSE", "Error response body:", errorBody.substring(0, 500));
|
|
196
|
+
} catch {
|
|
197
|
+
debug("SSE", "Could not read error response body");
|
|
198
|
+
}
|
|
199
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}${errorBody ? ` - ${errorBody}` : ""}`);
|
|
169
200
|
}
|
|
170
201
|
if (!response.body) {
|
|
171
202
|
throw new Error("Response body is null");
|
|
172
203
|
}
|
|
173
|
-
|
|
204
|
+
console.info("[SSE] Connected to agent endpoint, streaming events...");
|
|
174
205
|
debug("SSE", "Response status:", response.status);
|
|
175
206
|
debug("SSE", "Content-Type:", response.headers.get("content-type"));
|
|
176
207
|
const completionReason = await this.processStream(response.body, onEvent, completeOnRunEnd, idleTimeoutMs);
|
|
208
|
+
console.info(`[SSE] Stream completed: ${completionReason}`);
|
|
177
209
|
debug("SSE", `Stream completed: ${completionReason}`);
|
|
178
210
|
onComplete?.();
|
|
179
211
|
} catch (error) {
|
|
@@ -183,9 +215,36 @@ var SSEClient = class {
|
|
|
183
215
|
onComplete?.();
|
|
184
216
|
} else {
|
|
185
217
|
console.error("[SSE] Stream error:", error.message);
|
|
218
|
+
console.error("[SSE] Debug mode is:", isDebugEnabled() ? "ENABLED \u2705" : "DISABLED \u274C");
|
|
219
|
+
const errorDetails = {
|
|
220
|
+
name: error.name,
|
|
221
|
+
message: error.message,
|
|
222
|
+
stack: error.stack,
|
|
223
|
+
cause: error.cause,
|
|
224
|
+
url,
|
|
225
|
+
method,
|
|
226
|
+
headers
|
|
227
|
+
};
|
|
228
|
+
debug("SSE", "Error details:", errorDetails);
|
|
229
|
+
if (error.message.includes("fetch failed")) {
|
|
230
|
+
debug("SSE", '\u{1F4A1} Diagnostic: "fetch failed" typically means:');
|
|
231
|
+
debug("SSE", " - Connection refused (endpoint not running)");
|
|
232
|
+
debug("SSE", " - DNS resolution failed (invalid hostname)");
|
|
233
|
+
debug("SSE", " - Network unreachable (firewall/VPN issues)");
|
|
234
|
+
debug("SSE", " - SSL/TLS certificate issues (self-signed cert)");
|
|
235
|
+
debug("SSE", ` Check if ${url} is accessible`);
|
|
236
|
+
} else if (error.message.includes("timeout")) {
|
|
237
|
+
debug("SSE", "\u{1F4A1} Diagnostic: Request timed out - endpoint may be slow or unresponsive");
|
|
238
|
+
} else if (error.message.includes("ENOTFOUND")) {
|
|
239
|
+
debug("SSE", "\u{1F4A1} Diagnostic: DNS lookup failed - hostname not found");
|
|
240
|
+
} else if (error.message.includes("ECONNREFUSED")) {
|
|
241
|
+
debug("SSE", "\u{1F4A1} Diagnostic: Connection refused - service not listening on this port");
|
|
242
|
+
}
|
|
186
243
|
onError?.(error);
|
|
187
244
|
}
|
|
188
245
|
} else {
|
|
246
|
+
console.error("[SSE] Unknown error:", error);
|
|
247
|
+
debug("SSE", "Unknown error details:", error);
|
|
189
248
|
onError?.(new Error("Unknown error occurred"));
|
|
190
249
|
}
|
|
191
250
|
}
|
|
@@ -229,8 +288,11 @@ var SSEClient = class {
|
|
|
229
288
|
debug("SSE", "Raw event:", data.substring(0, 200) + (data.length > 200 ? "..." : ""));
|
|
230
289
|
try {
|
|
231
290
|
const event = JSON.parse(data);
|
|
232
|
-
debug("SSE", "Parsed:", event.type);
|
|
291
|
+
debug("SSE", "Parsed event:", event.type);
|
|
233
292
|
eventCount++;
|
|
293
|
+
if (eventCount % 10 === 0) {
|
|
294
|
+
console.info(`[SSE] Processed ${eventCount} events...`);
|
|
295
|
+
}
|
|
234
296
|
onEvent(event);
|
|
235
297
|
if (completeOnRunEnd && (event.type === AGUIEventType.RUN_FINISHED || event.type === AGUIEventType.RUN_ERROR)) {
|
|
236
298
|
debug("SSE", `Received ${event.type}, completing stream`);
|
|
@@ -1282,7 +1344,39 @@ var ClaudeCodeConnector = class extends SubprocessConnector {
|
|
|
1282
1344
|
this.isInThinking = false;
|
|
1283
1345
|
}
|
|
1284
1346
|
/**
|
|
1285
|
-
*
|
|
1347
|
+
* Build CLI args from ClaudeCodeConnectorConfig
|
|
1348
|
+
*/
|
|
1349
|
+
buildConfigArgs(config) {
|
|
1350
|
+
const args = [];
|
|
1351
|
+
if (config.dangerouslySkipPermissions) {
|
|
1352
|
+
args.push("--dangerously-skip-permissions");
|
|
1353
|
+
}
|
|
1354
|
+
if (config.systemPrompt) {
|
|
1355
|
+
args.push("--system-prompt", config.systemPrompt);
|
|
1356
|
+
} else if (config.appendSystemPrompt) {
|
|
1357
|
+
args.push("--append-system-prompt", config.appendSystemPrompt);
|
|
1358
|
+
}
|
|
1359
|
+
if (config.allowedTools?.length) {
|
|
1360
|
+
args.push("--allowed-tools", ...config.allowedTools);
|
|
1361
|
+
}
|
|
1362
|
+
if (config.disallowedTools?.length) {
|
|
1363
|
+
args.push("--disallowed-tools", ...config.disallowedTools);
|
|
1364
|
+
}
|
|
1365
|
+
if (config.mcpConfigPath) {
|
|
1366
|
+
args.push("--mcp-config", config.mcpConfigPath);
|
|
1367
|
+
} else if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {
|
|
1368
|
+
args.push("--mcp-config", JSON.stringify({ mcpServers: config.mcpServers }));
|
|
1369
|
+
}
|
|
1370
|
+
if (config.strictMcpConfig) {
|
|
1371
|
+
args.push("--strict-mcp-config");
|
|
1372
|
+
}
|
|
1373
|
+
if (config.additionalArgs) {
|
|
1374
|
+
args.push(...config.additionalArgs);
|
|
1375
|
+
}
|
|
1376
|
+
return args;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Override execute to reset state and apply connectorConfig
|
|
1286
1380
|
*/
|
|
1287
1381
|
async execute(endpoint, request, auth, onProgress, onRawEvent) {
|
|
1288
1382
|
this.debug("========== execute() STARTED ==========");
|
|
@@ -1290,11 +1384,55 @@ var ClaudeCodeConnector = class extends SubprocessConnector {
|
|
|
1290
1384
|
this.debug("Test case:", request.testCase.name);
|
|
1291
1385
|
this.debug("Config:", this["config"]);
|
|
1292
1386
|
this.resetState();
|
|
1293
|
-
this.
|
|
1294
|
-
const
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1387
|
+
const originalEnv = this.config.env ? structuredClone(this.config.env) : {};
|
|
1388
|
+
const originalArgs = this.config.args ? [...this.config.args] : [];
|
|
1389
|
+
const originalInputMode = this.config.inputMode;
|
|
1390
|
+
const originalTimeout = this.config.timeout;
|
|
1391
|
+
const originalWorkingDir = this.config.workingDir;
|
|
1392
|
+
const ccConfig = request.connectorConfig;
|
|
1393
|
+
if (ccConfig) {
|
|
1394
|
+
this.debug("Applying connectorConfig:", Object.keys(ccConfig));
|
|
1395
|
+
if (ccConfig.env) {
|
|
1396
|
+
this.config.env = { ...this.config.env, ...ccConfig.env };
|
|
1397
|
+
}
|
|
1398
|
+
if (ccConfig.usePromptArg) {
|
|
1399
|
+
this.config.inputMode = "arg";
|
|
1400
|
+
}
|
|
1401
|
+
if (ccConfig.timeout !== void 0) {
|
|
1402
|
+
this.config.timeout = ccConfig.timeout;
|
|
1403
|
+
}
|
|
1404
|
+
if (ccConfig.workingDir) {
|
|
1405
|
+
this.config.workingDir = ccConfig.workingDir;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
if (this.config.env?.CLAUDE_CODE_USE_BEDROCK === "1") {
|
|
1409
|
+
this.config.env = { ...this.config.env, ANTHROPIC_API_KEY: "" };
|
|
1410
|
+
this.debug("Bedrock mode: cleared ANTHROPIC_API_KEY to bypass credit check");
|
|
1411
|
+
}
|
|
1412
|
+
if (request.modelId) {
|
|
1413
|
+
this.config.args = [...this.config.args || [], "--model", request.modelId];
|
|
1414
|
+
this.debug("Model flag added:", request.modelId);
|
|
1415
|
+
}
|
|
1416
|
+
if (ccConfig) {
|
|
1417
|
+
const configArgs = this.buildConfigArgs(ccConfig);
|
|
1418
|
+
if (configArgs.length > 0) {
|
|
1419
|
+
this.config.args = [...this.config.args || [], ...configArgs];
|
|
1420
|
+
this.debug("Config args added:", configArgs);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
try {
|
|
1424
|
+
this.debug("State reset, calling super.execute()...");
|
|
1425
|
+
const result = await super.execute(endpoint, request, auth, onProgress, onRawEvent);
|
|
1426
|
+
this.debug("super.execute() returned with", result.trajectory.length, "steps");
|
|
1427
|
+
this.debug("========== execute() COMPLETED ==========");
|
|
1428
|
+
return result;
|
|
1429
|
+
} finally {
|
|
1430
|
+
this.config.env = originalEnv;
|
|
1431
|
+
this.config.args = originalArgs;
|
|
1432
|
+
this.config.inputMode = originalInputMode;
|
|
1433
|
+
this.config.timeout = originalTimeout;
|
|
1434
|
+
this.config.workingDir = originalWorkingDir;
|
|
1435
|
+
}
|
|
1298
1436
|
}
|
|
1299
1437
|
/**
|
|
1300
1438
|
* Health check - verify claude command exists
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensearch-project/agent-health",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent Evaluation and Observability Framework",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -70,8 +70,9 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@ag-ui/core": "^0.0.41",
|
|
73
|
-
"@aws-sdk/client-bedrock
|
|
74
|
-
"@aws-sdk/
|
|
73
|
+
"@aws-sdk/client-bedrock": "^3.1000.0",
|
|
74
|
+
"@aws-sdk/client-bedrock-runtime": "^3.1000.0",
|
|
75
|
+
"@aws-sdk/credential-providers": "^3.1000.0",
|
|
75
76
|
"@opensearch-project/opensearch": "^3.5.1",
|
|
76
77
|
"@opentelemetry/semantic-conventions": "^1.38.0",
|
|
77
78
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
@@ -116,8 +117,12 @@
|
|
|
116
117
|
"tailwind-merge": "^3.4.0",
|
|
117
118
|
"tailwindcss-animate": "^1.0.7",
|
|
118
119
|
"uuid": "^10.0.0",
|
|
120
|
+
"yaml": "^2.8.2",
|
|
119
121
|
"zod": "^3.24.0"
|
|
120
122
|
},
|
|
123
|
+
"optionalDependencies": {
|
|
124
|
+
"puppeteer": "^24.37.4"
|
|
125
|
+
},
|
|
121
126
|
"devDependencies": {
|
|
122
127
|
"@playwright/test": "^1.57.0",
|
|
123
128
|
"@tailwindcss/typography": "^0.5.19",
|
|
@@ -130,6 +135,7 @@
|
|
|
130
135
|
"@types/node": "^24.10.1",
|
|
131
136
|
"@types/react": "^19.2.0",
|
|
132
137
|
"@types/react-dom": "^19.2.0",
|
|
138
|
+
"@types/supertest": "^6.0.3",
|
|
133
139
|
"@types/uuid": "^10.0.0",
|
|
134
140
|
"@vitejs/plugin-react": "^4.2.1",
|
|
135
141
|
"autoprefixer": "^10.4.16",
|
|
@@ -139,6 +145,7 @@
|
|
|
139
145
|
"jest-environment-jsdom": "^30.2.0",
|
|
140
146
|
"postcss": "^8.4.32",
|
|
141
147
|
"shadcn": "^3.5.1",
|
|
148
|
+
"supertest": "^7.2.2",
|
|
142
149
|
"tailwindcss": "^3.4.0",
|
|
143
150
|
"ts-jest": "^29.4.6",
|
|
144
151
|
"ts-node": "^10.9.2",
|
|
@@ -148,6 +155,7 @@
|
|
|
148
155
|
"vite": "^7.3.1"
|
|
149
156
|
},
|
|
150
157
|
"overrides": {
|
|
151
|
-
"minimatch": "^10.2.
|
|
158
|
+
"minimatch": "^10.2.4",
|
|
159
|
+
"fast-xml-parser": "5.5.10"
|
|
152
160
|
}
|
|
153
161
|
}
|