ralph-hero-mcp-server 2.5.149 → 2.5.171

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/dist/index.js CHANGED
@@ -33,6 +33,7 @@ import { registerPlanGraphTools } from "./tools/plan-graph-tools.js";
33
33
  import { registerActivityTools } from "./tools/activity-tools.js";
34
34
  import { registerDelegationTools } from "./tools/delegation-tools.js";
35
35
  import { registerTrendsTools } from "./tools/trends-tools.js";
36
+ import { registerSreTools } from "./tools/sre-tools.js";
36
37
  /**
37
38
  * Initialize the GitHub client from environment variables.
38
39
  */
@@ -450,6 +451,8 @@ async function main() {
450
451
  registerDelegationTools(server);
451
452
  // Trends tools (capture_snapshot — JSONL persistence under ~/.ralph-hero/snapshots/)
452
453
  registerTrendsTools(server, client, fieldCache);
454
+ // SRE operation tools (kubectl autoremediation — typed argv, no-shell invariant)
455
+ registerSreTools(server, client, fieldCache);
453
456
  // Debug tools (only when RALPH_DEBUG=true)
454
457
  if (process.env.RALPH_DEBUG === 'true') {
455
458
  registerDebugTools(server, client);
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared kubectl execution helper for all SRE operation tools.
3
+ *
4
+ * INVARIANT: This module NEVER invokes a shell. All kubectl calls go through
5
+ * `child_process.execFile` with `shell: false` (the execFile default), which
6
+ * passes argv directly to execve(2). String-interpolated shell commands and
7
+ * `exec()` are explicitly forbidden here.
8
+ *
9
+ * The {@link FORBIDDEN_FLAGS} list provides a defense-in-depth check on top of
10
+ * the typed Zod schemas in sre-tools.ts. The typed schemas should already make
11
+ * these flags unreachable, but the helper enforces a hard floor so a future
12
+ * regression (e.g., a new typed param that happens to produce a forbidden flag)
13
+ * is caught at the exec layer, not silently allowed.
14
+ */
15
+ import { execFile as _execFile } from "node:child_process";
16
+ import { promisify } from "node:util";
17
+ const execFileAsync = promisify(_execFile);
18
+ /**
19
+ * Flags that are unconditionally forbidden in kubectl argv.
20
+ *
21
+ * These represent destructive or resource-exhausting operations that the
22
+ * sre-fixit agent must never perform. They are defense-in-depth: the typed
23
+ * Zod schemas in sre-tools.ts make them structurally unreachable, but this
24
+ * list catches future regressions where a new typed param happens to produce
25
+ * one of these strings.
26
+ */
27
+ export const FORBIDDEN_FLAGS = [
28
+ "--force",
29
+ "--cascade=foreground",
30
+ "--grace-period=0",
31
+ "--delete-emptydir-data",
32
+ ];
33
+ /**
34
+ * Execute kubectl with the given argv array.
35
+ *
36
+ * Uses `child_process.execFile` (shell: false by default) so the argv is
37
+ * passed directly to execve(2) — no shell interpretation, no metacharacter
38
+ * expansion, no glob expansion.
39
+ *
40
+ * @param args - Typed argv array (e.g. `["scale", "--namespace", "default", ...]`).
41
+ * Never accepts a string command.
42
+ * @throws {Error} If any element of `args` matches a {@link FORBIDDEN_FLAGS} entry.
43
+ * @returns A typed result with `stdout`, `stderr`, and `exitCode`.
44
+ */
45
+ export async function runKubectl(args) {
46
+ // Defense-in-depth: reject any argv element that matches a forbidden flag.
47
+ for (const arg of args) {
48
+ if (FORBIDDEN_FLAGS.includes(arg)) {
49
+ throw new Error(`kubectl argv contains forbidden flag: ${arg}. ` +
50
+ `Forbidden flags: ${FORBIDDEN_FLAGS.join(", ")}`);
51
+ }
52
+ }
53
+ try {
54
+ const { stdout, stderr } = await execFileAsync("kubectl", args, {
55
+ shell: false,
56
+ });
57
+ return { stdout, stderr, exitCode: 0 };
58
+ }
59
+ catch (err) {
60
+ // execFile rejects when the process exits with a non-zero code.
61
+ // The error object carries stdout/stderr from the failed run.
62
+ const e = err;
63
+ return {
64
+ stdout: e.stdout ?? "",
65
+ stderr: e.stderr ?? "",
66
+ exitCode: typeof e.code === "number" ? e.code : 1,
67
+ };
68
+ }
69
+ }
70
+ //# sourceMappingURL=kubectl-exec.js.map
@@ -132,16 +132,16 @@ export async function initTelemetry() {
132
132
  // is unset, none of these modules are loaded into memory.
133
133
  const { NodeSDK } = await import("@opentelemetry/sdk-node");
134
134
  const { OTLPTraceExporter } = await import("@opentelemetry/exporter-trace-otlp-http");
135
- const { Resource } = await import("@opentelemetry/resources");
136
- const { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_VERSION, } = await import("@opentelemetry/semantic-conventions");
135
+ const { resourceFromAttributes } = await import("@opentelemetry/resources");
136
+ const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, } = await import("@opentelemetry/semantic-conventions");
137
137
  const { BatchSpanProcessor } = await import("@opentelemetry/sdk-trace-base");
138
138
  const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ??
139
139
  "http://localhost:3100/api/public/otel/v1/traces";
140
140
  const exporter = new OTLPTraceExporter({ url: endpoint });
141
141
  const sdk = new NodeSDK({
142
- resource: new Resource({
143
- [SEMRESATTRS_SERVICE_NAME]: "ralph-hero",
144
- [SEMRESATTRS_SERVICE_VERSION]: resolveServiceVersion(),
142
+ resource: resourceFromAttributes({
143
+ [ATTR_SERVICE_NAME]: "ralph-hero",
144
+ [ATTR_SERVICE_VERSION]: resolveServiceVersion(),
145
145
  }),
146
146
  spanProcessors: [
147
147
  new TokenScrubbingSpanProcessor(),
@@ -0,0 +1,334 @@
1
+ /**
2
+ * SRE operation tools for kubectl autoremediation.
3
+ *
4
+ * This module registers the `ralph_hero__sre__*` family of typed MCP tools.
5
+ * Each tool accepts explicit, narrowly-typed parameters and delegates to the
6
+ * shared {@link runKubectl} helper from `../lib/kubectl-exec.ts`.
7
+ *
8
+ * INVARIANT (no-shell): All kubectl invocations go through `runKubectl`, which
9
+ * uses `child_process.execFile` with `shell: false`. There are NO string-
10
+ * interpolated shell commands, NO `exec()` calls, and NO `Bash` tool usage in
11
+ * this module or the agent that consumes it. Argv is always a plain array
12
+ * literal — never built via template strings, string concat, or user-controlled
13
+ * flag pass-through.
14
+ *
15
+ * Phases 2-5 of the GH-1285 plan add the four operation tool registrations
16
+ * (sre__scale, sre__rollout_restart, sre__delete_pod, sre__drain) inside
17
+ * `registerSreTools`. Phase 1 (GH-1287) establishes the module skeleton and
18
+ * wires the registration call in index.ts.
19
+ */
20
+ import { z } from "zod";
21
+ import { runKubectl } from "../lib/kubectl-exec.js";
22
+ import { toolSuccess, toolError } from "../types.js";
23
+ // ---------------------------------------------------------------------------
24
+ // Shared Zod field schemas
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * RFC 1123 label regex for Kubernetes namespace and deployment names.
28
+ * Intentionally rejects shell metacharacters, slashes, newlines, and empty
29
+ * strings as a single Zod check.
30
+ */
31
+ const k8sLabelSchema = z.string().min(1).regex(/^[a-z0-9-]+$/);
32
+ /**
33
+ * Bounded replica count. Ceiling is 50 — configurable in a follow-up; the
34
+ * explicit ceiling prevents runaway scale-out from an LLM miscalculation.
35
+ */
36
+ export const REPLICA_CEILING = 50;
37
+ const replicasSchema = z.number().int().min(0).max(REPLICA_CEILING);
38
+ // ---------------------------------------------------------------------------
39
+ // sre__scale schemas
40
+ // ---------------------------------------------------------------------------
41
+ /**
42
+ * Raw Zod shape for the sre__scale tool.
43
+ * Passed to `server.tool()` which expects a `ZodRawShape` (plain object of
44
+ * Zod field schemas).
45
+ */
46
+ const sreScaleShape = {
47
+ namespace: k8sLabelSchema.describe("Kubernetes namespace (RFC 1123 label: lowercase alphanumeric and hyphens only)."),
48
+ deployment: k8sLabelSchema.describe("Deployment name (RFC 1123 label: lowercase alphanumeric and hyphens only)."),
49
+ replicas: replicasSchema.describe(`Target replica count (integer, 0–${REPLICA_CEILING}).`),
50
+ };
51
+ /**
52
+ * Strict Zod object schema for sre__scale parameters.
53
+ *
54
+ * Exported so adversarial-input tests (sre-tools.test.ts) can call
55
+ * `.safeParse()` directly. `.strict()` ensures unknown keys are rejected —
56
+ * any attempt to pass extra fields (e.g., a `flags` bypass) is caught at
57
+ * the schema level.
58
+ */
59
+ export const sreScaleSchema = z.object(sreScaleShape).strict();
60
+ /**
61
+ * Build the kubectl argv array for a scale operation.
62
+ *
63
+ * Exported for unit-testing the argv shape independently of the MCP server.
64
+ * The argv is a plain array literal — no string interpolation, no concat.
65
+ *
66
+ * @param namespace - Validated Kubernetes namespace.
67
+ * @param deployment - Validated deployment name.
68
+ * @param replicas - Validated replica count.
69
+ */
70
+ export function buildScaleArgv(namespace, deployment, replicas) {
71
+ return [
72
+ "scale",
73
+ "--namespace",
74
+ namespace,
75
+ "deployment",
76
+ deployment,
77
+ "--replicas",
78
+ String(replicas),
79
+ ];
80
+ }
81
+ // ---------------------------------------------------------------------------
82
+ // sre__rollout_restart schemas (Phase 3 / GH-1289)
83
+ // ---------------------------------------------------------------------------
84
+ /**
85
+ * Raw Zod shape for the sre__rollout_restart tool.
86
+ */
87
+ const sreRolloutRestartShape = {
88
+ namespace: k8sLabelSchema.describe("Kubernetes namespace (RFC 1123 label: lowercase alphanumeric and hyphens only)."),
89
+ deployment: k8sLabelSchema.describe("Deployment name (RFC 1123 label: lowercase alphanumeric and hyphens only)."),
90
+ };
91
+ /**
92
+ * Strict Zod object schema for sre__rollout_restart parameters.
93
+ *
94
+ * Exported so adversarial-input tests (sre-tools.test.ts) can call
95
+ * `.safeParse()` directly. `.strict()` ensures unknown keys are rejected.
96
+ */
97
+ export const sreRolloutRestartSchema = z.object(sreRolloutRestartShape).strict();
98
+ /**
99
+ * Build the kubectl argv array for a rollout restart operation.
100
+ *
101
+ * Exported for unit-testing the argv shape independently of the MCP server.
102
+ *
103
+ * NOTE — deliberate template-literal exception: This is the only argv builder
104
+ * in the sre__* family that uses a template literal. The `deployment/<name>`
105
+ * form is specific to `kubectl rollout restart`'s resource-qualified argument
106
+ * syntax. The interpolation is safe by construction: the `deployment` Zod
107
+ * schema (`/^[a-z0-9-]+$/`) forbids `/`, newlines, and shell metacharacters —
108
+ * the only characters that could escape the literal prefix. Do NOT generalise
109
+ * this pattern to other phases; phases 2, 4, and 5 keep plain array literals.
110
+ *
111
+ * @param namespace - Validated Kubernetes namespace.
112
+ * @param deployment - Validated deployment name.
113
+ */
114
+ export function buildRolloutRestartArgv(namespace, deployment) {
115
+ return [
116
+ "rollout",
117
+ "restart",
118
+ "--namespace",
119
+ namespace,
120
+ `deployment/${deployment}`,
121
+ ];
122
+ }
123
+ // ---------------------------------------------------------------------------
124
+ // sre__delete_pod schemas (Phase 4 / GH-1290)
125
+ // ---------------------------------------------------------------------------
126
+ /**
127
+ * Raw Zod shape for the sre__delete_pod tool.
128
+ *
129
+ * The schema has exactly two fields — `namespace` and `pod`. There is no
130
+ * label-selector field, no `--force` field, and no `--grace-period` field.
131
+ * The absence of these fields is the primary typed-surface guarantee: there is
132
+ * no way to express bulk deletion, forced deletion, or grace-period override
133
+ * through this schema. `.strict()` rejects any extra keys the caller might
134
+ * try to pass.
135
+ */
136
+ const sreDeletePodShape = {
137
+ namespace: k8sLabelSchema.describe("Kubernetes namespace (RFC 1123 label: lowercase alphanumeric and hyphens only)."),
138
+ pod: k8sLabelSchema.describe("Pod name to delete (RFC 1123 label: lowercase alphanumeric and hyphens only). " +
139
+ "Single pod only — no label selector, no wildcard."),
140
+ };
141
+ /**
142
+ * Strict Zod object schema for sre__delete_pod parameters.
143
+ *
144
+ * Exported so adversarial-input tests (sre-tools.test.ts) can call
145
+ * `.safeParse()` directly, including the `.strict()` no-label-selector
146
+ * assertion. `.strict()` ensures unknown keys (e.g., `selector: "app=foo"`)
147
+ * are rejected at the schema level.
148
+ */
149
+ export const sreDeletePodSchema = z.object(sreDeletePodShape).strict();
150
+ /**
151
+ * Build the kubectl argv array for a delete-pod operation.
152
+ *
153
+ * Exported for unit-testing the argv shape independently of the MCP server.
154
+ * The argv is a plain array literal — no string interpolation, no concat.
155
+ *
156
+ * @param namespace - Validated Kubernetes namespace.
157
+ * @param pod - Validated pod name (single pod, no label selector).
158
+ */
159
+ export function buildDeletePodArgv(namespace, pod) {
160
+ return ["delete", "pod", "--namespace", namespace, pod];
161
+ }
162
+ // ---------------------------------------------------------------------------
163
+ // sre__drain schemas (Phase 5 / GH-1291)
164
+ // ---------------------------------------------------------------------------
165
+ /**
166
+ * Node name regex — slightly looser than the RFC 1123 label regex because
167
+ * Kubernetes node names can be in FQDN form (e.g., "node-1.us-east-1.example.com").
168
+ * The dot (`.`) is the only addition over the namespace/deployment regex.
169
+ * Intentionally rejects shell metacharacters, slashes, newlines, and empty
170
+ * strings as a single Zod check.
171
+ */
172
+ const k8sNodeNameSchema = z.string().min(1).regex(/^[a-z0-9.-]+$/);
173
+ /**
174
+ * Bounded grace period in seconds. Minimum is 1 — gracePeriodSeconds=0 is
175
+ * equivalent to --force (immediate kill) and is explicitly forbidden by the
176
+ * plan's Shared Constraint #3. Maximum is 3600 (one hour).
177
+ */
178
+ const gracePeriodSecondsSchema = z.number().int().min(1).max(3600);
179
+ /**
180
+ * Bounded timeout in seconds. Minimum is 1. Maximum is 3600 (one hour).
181
+ */
182
+ const timeoutSecondsSchema = z.number().int().min(1).max(3600);
183
+ /**
184
+ * Raw Zod shape for the sre__drain tool.
185
+ *
186
+ * `--namespace` is intentionally absent: `kubectl drain` targets a node, which
187
+ * is a cluster-scoped resource. Do not add a namespace field — its absence is
188
+ * correct per the plan's Phase 5 note.
189
+ *
190
+ * `--ignore-daemonsets` is hard-coded into argv by the builder; it is NOT a
191
+ * user-controllable parameter. `--force` and `--delete-emptydir-data` are
192
+ * structurally unreachable through this schema.
193
+ */
194
+ const sreDrainShape = {
195
+ node: k8sNodeNameSchema.describe("Node name to drain (RFC 1123 / FQDN form: lowercase alphanumeric, hyphens, and dots only)."),
196
+ gracePeriodSeconds: gracePeriodSecondsSchema.optional().describe("Grace period for evicting pods in seconds (integer, 1–3600). " +
197
+ "Omit to use the pod's default. " +
198
+ "0 is explicitly forbidden (equivalent to --force)."),
199
+ timeoutSeconds: timeoutSecondsSchema.optional().describe("Timeout for the drain operation in seconds (integer, 1–3600). " +
200
+ "Omit to use kubectl's default."),
201
+ };
202
+ /**
203
+ * Strict Zod object schema for sre__drain parameters.
204
+ *
205
+ * Exported so adversarial-input tests (sre-tools.test.ts) can call
206
+ * `.safeParse()` directly. `.strict()` ensures unknown keys are rejected —
207
+ * any attempt to pass extra fields (e.g., a `force` bypass) is caught at
208
+ * the schema level.
209
+ */
210
+ export const sreDrainSchema = z.object(sreDrainShape).strict();
211
+ /**
212
+ * Build the kubectl argv array for a drain operation.
213
+ *
214
+ * Exported for unit-testing the argv shape independently of the MCP server.
215
+ * The argv is a plain array literal — no string interpolation, no concat
216
+ * (drain follows the same plain-array-literal pattern as phases 2 and 4).
217
+ *
218
+ * INVARIANTS (enforced by construction):
219
+ * - `--ignore-daemonsets` is always present (hard-coded, not user-controlled).
220
+ * - `--force` is never present (no schema field; helper also rejects it).
221
+ * - `--delete-emptydir-data` is never present (no schema field).
222
+ * - `--grace-period=0` is never present (gracePeriodSeconds min is 1 via Zod).
223
+ *
224
+ * @param node - Validated node name.
225
+ * @param gracePeriodSeconds - Optional validated grace period (seconds, >= 1).
226
+ * @param timeoutSeconds - Optional validated timeout (seconds, >= 1).
227
+ */
228
+ export function buildDrainArgv(node, gracePeriodSeconds, timeoutSeconds) {
229
+ const argv = ["drain", node, "--ignore-daemonsets"];
230
+ if (gracePeriodSeconds !== undefined) {
231
+ argv.push("--grace-period", String(gracePeriodSeconds));
232
+ }
233
+ if (timeoutSeconds !== undefined) {
234
+ argv.push("--timeout", `${timeoutSeconds}s`);
235
+ }
236
+ return argv;
237
+ }
238
+ // ---------------------------------------------------------------------------
239
+ /**
240
+ * Register all SRE operation tools on the MCP server.
241
+ *
242
+ * The `client` and `fieldCache` parameters are accepted for API consistency
243
+ * with other `register*Tools` functions. They are unused in Phase 1 (scaffold
244
+ * only); Phases 2-5 may use `client` for issue context lookups if needed.
245
+ *
246
+ * @param server - The MCP server instance to register tools on.
247
+ * @param client - GitHub client (reserved for future phases).
248
+ * @param fieldCache - Field option cache (reserved for future phases).
249
+ */
250
+ export function registerSreTools(server,
251
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
252
+ _client,
253
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
254
+ _fieldCache) {
255
+ // -------------------------------------------------------------------------
256
+ // ralph_hero__sre__scale (Phase 2 / GH-1288)
257
+ // -------------------------------------------------------------------------
258
+ server.tool("ralph_hero__sre__scale", "Scale a Kubernetes deployment to a specified replica count. " +
259
+ "Typed parameters only — no shell, no flag pass-through. " +
260
+ `Replica ceiling: ${REPLICA_CEILING}.`, sreScaleShape, async ({ namespace, deployment, replicas }) => {
261
+ const argv = buildScaleArgv(namespace, deployment, replicas);
262
+ try {
263
+ const result = await runKubectl(argv);
264
+ if (result.exitCode !== 0) {
265
+ return toolError(`kubectl scale failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
266
+ }
267
+ return toolSuccess(result);
268
+ }
269
+ catch (err) {
270
+ const message = err instanceof Error ? err.message : String(err);
271
+ return toolError(`kubectl scale failed: ${message}`);
272
+ }
273
+ });
274
+ // -------------------------------------------------------------------------
275
+ // ralph_hero__sre__rollout_restart (Phase 3 / GH-1289)
276
+ // -------------------------------------------------------------------------
277
+ server.tool("ralph_hero__sre__rollout_restart", "Trigger a rolling restart of a Kubernetes deployment. " +
278
+ "Typed parameters only — no shell, no flag pass-through. " +
279
+ "Equivalent to: kubectl rollout restart deployment/<name> -n <namespace>.", sreRolloutRestartShape, async ({ namespace, deployment }) => {
280
+ const argv = buildRolloutRestartArgv(namespace, deployment);
281
+ try {
282
+ const result = await runKubectl(argv);
283
+ if (result.exitCode !== 0) {
284
+ return toolError(`kubectl rollout restart failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
285
+ }
286
+ return toolSuccess(result);
287
+ }
288
+ catch (err) {
289
+ const message = err instanceof Error ? err.message : String(err);
290
+ return toolError(`kubectl rollout restart failed: ${message}`);
291
+ }
292
+ });
293
+ // -------------------------------------------------------------------------
294
+ // ralph_hero__sre__delete_pod (Phase 4 / GH-1290)
295
+ // -------------------------------------------------------------------------
296
+ server.tool("ralph_hero__sre__delete_pod", "Delete a single named pod in a Kubernetes namespace. " +
297
+ "Single pod by name only — no label selector, no --force, no --grace-period=0. " +
298
+ "Typed parameters only — no shell, no flag pass-through.", sreDeletePodShape, async ({ namespace, pod }) => {
299
+ const argv = buildDeletePodArgv(namespace, pod);
300
+ try {
301
+ const result = await runKubectl(argv);
302
+ if (result.exitCode !== 0) {
303
+ return toolError(`kubectl delete pod failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
304
+ }
305
+ return toolSuccess(result);
306
+ }
307
+ catch (err) {
308
+ const message = err instanceof Error ? err.message : String(err);
309
+ return toolError(`kubectl delete pod failed: ${message}`);
310
+ }
311
+ });
312
+ // -------------------------------------------------------------------------
313
+ // ralph_hero__sre__drain (Phase 5 / GH-1291)
314
+ // -------------------------------------------------------------------------
315
+ server.tool("ralph_hero__sre__drain", "Drain a Kubernetes node by evicting all non-daemonset pods. " +
316
+ "--ignore-daemonsets is hard-coded on (always present). " +
317
+ "--force, --delete-emptydir-data, and --grace-period=0 are structurally unreachable. " +
318
+ "Cluster-scoped operation — no --namespace flag. " +
319
+ "Typed parameters only — no shell, no flag pass-through.", sreDrainShape, async ({ node, gracePeriodSeconds, timeoutSeconds }) => {
320
+ const argv = buildDrainArgv(node, gracePeriodSeconds, timeoutSeconds);
321
+ try {
322
+ const result = await runKubectl(argv);
323
+ if (result.exitCode !== 0) {
324
+ return toolError(`kubectl drain failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
325
+ }
326
+ return toolSuccess(result);
327
+ }
328
+ catch (err) {
329
+ const message = err instanceof Error ? err.message : String(err);
330
+ return toolError(`kubectl drain failed: ${message}`);
331
+ }
332
+ });
333
+ }
334
+ //# sourceMappingURL=sre-tools.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-hero-mcp-server",
3
- "version": "2.5.149",
3
+ "version": "2.5.171",
4
4
  "description": "MCP server for GitHub Projects V2 - Ralph workflow automation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,11 +21,11 @@
21
21
  "@octokit/graphql": "^9.0.3",
22
22
  "@octokit/plugin-paginate-graphql": "^6.0.0",
23
23
  "@opentelemetry/api": "^1.9.0",
24
- "@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
25
- "@opentelemetry/resources": "^1.30.0",
26
- "@opentelemetry/sdk-node": "^0.57.0",
27
- "@opentelemetry/sdk-trace-base": "^1.30.0",
28
- "@opentelemetry/semantic-conventions": "^1.28.0",
24
+ "@opentelemetry/exporter-trace-otlp-http": "^0.218.0",
25
+ "@opentelemetry/resources": "^2.7.1",
26
+ "@opentelemetry/sdk-node": "^0.218.0",
27
+ "@opentelemetry/sdk-trace-base": "^2.7.1",
28
+ "@opentelemetry/semantic-conventions": "^1.41.1",
29
29
  "yaml": "^2.7.0",
30
30
  "zod": "^3.25.0"
31
31
  },