From 9b06edfef87d6fead07b74282c61cf0d474fab58 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 May 2026 15:38:09 -0700 Subject: [PATCH 1/5] feat: Add Firebase `genkit` instrumentation --- e2e/config/pr-comment-scenarios.json | 6 + .../genkit-v1-33-0-auto.span-events.json | 117 + .../genkit-v1-33-0-wrapped.span-events.json | 185 + .../genkit-instrumentation/assertions.ts | 220 + .../genkit-instrumentation/constants.mjs | 2 + .../genkit-instrumentation/package.json | 16 + .../genkit-instrumentation/pnpm-lock.yaml | 4317 +++++++++++++++++ .../genkit-instrumentation/scenario.impl.mjs | 231 + .../genkit-instrumentation/scenario.mjs | 4 + .../genkit-instrumentation/scenario.test.ts | 50 + .../genkit-instrumentation/scenario.ts | 4 + .../auto-instrumentations/bundler/plugin.ts | 2 + .../bundler/webpack-loader.ts | 2 + .../auto-instrumentations/configs/genkit.ts | 144 + js/src/auto-instrumentations/hook.mts | 4 + js/src/auto-instrumentations/index.ts | 1 + js/src/exports.ts | 1 + js/src/instrumentation/braintrust-plugin.ts | 13 + .../plugins/genkit-channels.ts | 53 + .../instrumentation/plugins/genkit-plugin.ts | 516 ++ js/src/instrumentation/registry.ts | 8 + js/src/vendor-sdk-types/genkit.ts | 150 + js/src/wrappers/genkit.ts | 237 + 23 files changed, 6283 insertions(+) create mode 100644 e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json create mode 100644 e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json create mode 100644 e2e/scenarios/genkit-instrumentation/assertions.ts create mode 100644 e2e/scenarios/genkit-instrumentation/constants.mjs create mode 100644 e2e/scenarios/genkit-instrumentation/package.json create mode 100644 e2e/scenarios/genkit-instrumentation/pnpm-lock.yaml create mode 100644 e2e/scenarios/genkit-instrumentation/scenario.impl.mjs create mode 100644 e2e/scenarios/genkit-instrumentation/scenario.mjs create mode 100644 e2e/scenarios/genkit-instrumentation/scenario.test.ts create mode 100644 e2e/scenarios/genkit-instrumentation/scenario.ts create mode 100644 js/src/auto-instrumentations/configs/genkit.ts create mode 100644 js/src/instrumentation/plugins/genkit-channels.ts create mode 100644 js/src/instrumentation/plugins/genkit-plugin.ts create mode 100644 js/src/vendor-sdk-types/genkit.ts create mode 100644 js/src/wrappers/genkit.ts diff --git a/e2e/config/pr-comment-scenarios.json b/e2e/config/pr-comment-scenarios.json index 0108b9e78..c96d50f6f 100644 --- a/e2e/config/pr-comment-scenarios.json +++ b/e2e/config/pr-comment-scenarios.json @@ -42,6 +42,12 @@ { "variantKey": "google-genai-v1460", "label": "v1.46.0" } ] }, + { + "scenarioDirName": "genkit-instrumentation", + "label": "Genkit Instrumentation", + "metadataScenario": "genkit-instrumentation", + "variants": [{ "variantKey": "genkit-v1-33-0", "label": "v1.33.0" }] + }, { "scenarioDirName": "groq-instrumentation", "label": "Groq Instrumentation", diff --git a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json new file mode 100644 index 000000000..d3cf1fba3 --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json @@ -0,0 +1,117 @@ +[ + { + "has_input": false, + "has_output": false, + "metadata": { + "scenario": "genkit-instrumentation" + }, + "metric_keys": [], + "name": "genkit-instrumentation-root", + "root_span_id": "", + "span_id": "", + "span_parents": [], + "type": "task" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "generate" + }, + "metric_keys": [], + "name": "genkit-generate-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-2.5-flash-lite", + "provider": "genkit" + }, + "metric_keys": [ + "completion_tokens", + "prompt_tokens", + "tokens" + ], + "name": "genkit.generate", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "stream" + }, + "metric_keys": [], + "name": "genkit-stream-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-2.5-flash-lite", + "provider": "genkit" + }, + "metric_keys": [ + "completion_tokens", + "prompt_tokens", + "time_to_first_token", + "tokens" + ], + "name": "genkit.generateStream", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "embed" + }, + "metric_keys": [], + "name": "genkit-embed-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-embedding-001", + "provider": "genkit" + }, + "metric_keys": [], + "name": "genkit.embed", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + } +] diff --git a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json new file mode 100644 index 000000000..0637aba1a --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json @@ -0,0 +1,185 @@ +[ + { + "has_input": false, + "has_output": false, + "metadata": { + "scenario": "genkit-instrumentation" + }, + "metric_keys": [], + "name": "genkit-instrumentation-root", + "root_span_id": "", + "span_id": "", + "span_parents": [], + "type": "task" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "generate" + }, + "metric_keys": [], + "name": "genkit-generate-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-2.5-flash-lite", + "provider": "genkit" + }, + "metric_keys": [ + "completion_tokens", + "prompt_tokens", + "tokens" + ], + "name": "genkit.generate", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "stream" + }, + "metric_keys": [], + "name": "genkit-stream-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-2.5-flash-lite", + "provider": "genkit" + }, + "metric_keys": [ + "completion_tokens", + "prompt_tokens", + "time_to_first_token", + "tokens" + ], + "name": "genkit.generateStream", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "embed" + }, + "metric_keys": [], + "name": "genkit-embed-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-embedding-001", + "provider": "genkit" + }, + "metric_keys": [], + "name": "genkit.embed", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "tool" + }, + "metric_keys": [], + "name": "genkit-tool-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "genkit.action_name": "summarizeCity", + "genkit.action_type": "tool", + "provider": "genkit" + }, + "metric_keys": [ + "duration" + ], + "name": "genkit.tool: summarizeCity", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "tool" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "flow" + }, + "metric_keys": [], + "name": "genkit-flow-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "genkit.action_name": "recipeFlow", + "genkit.action_type": "flow", + "provider": "genkit" + }, + "metric_keys": [ + "duration" + ], + "name": "genkit.flow: recipeFlow", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "task" + } +] diff --git a/e2e/scenarios/genkit-instrumentation/assertions.ts b/e2e/scenarios/genkit-instrumentation/assertions.ts new file mode 100644 index 000000000..4b311a1cb --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/assertions.ts @@ -0,0 +1,220 @@ +import { beforeAll, describe, expect, test } from "vitest"; +import type { Json } from "../../helpers/normalize"; +import type { CapturedLogEvent } from "../../helpers/mock-braintrust-server"; +import { + formatJsonFileSnapshot, + resolveFileSnapshotPath, +} from "../../helpers/file-snapshot"; +import { withScenarioHarness } from "../../helpers/scenario-harness"; +import { E2E_TAGS } from "../../helpers/tags"; +import { findChildSpans, findLatestSpan } from "../../helpers/trace-selectors"; +import { summarizeWrapperContract } from "../../helpers/wrapper-contract"; +import { ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; + +type RunGenkitScenario = (harness: { + runNodeScenarioDir: (options: { + entry: string; + nodeArgs: string[]; + runContext?: { variantKey: string }; + scenarioDir: string; + timeoutMs: number; + }) => Promise; + runScenarioDir: (options: { + entry: string; + runContext?: { variantKey: string }; + scenarioDir: string; + timeoutMs: number; + }) => Promise; +}) => Promise; + +function findGenkitSpan( + events: CapturedLogEvent[], + parentId: string | undefined, + spanName: string, +) { + const spans = findChildSpans(events, spanName, parentId); + return spans.find((candidate) => candidate.output !== undefined) ?? spans[0]; +} + +function buildSpanSummary( + events: CapturedLogEvent[], + supportsActionSpans: boolean, +): Json { + const generateOperation = findLatestSpan(events, "genkit-generate-operation"); + const streamOperation = findLatestSpan(events, "genkit-stream-operation"); + const embedOperation = findLatestSpan(events, "genkit-embed-operation"); + + const summary = [ + findLatestSpan(events, ROOT_NAME), + generateOperation, + findGenkitSpan(events, generateOperation?.span.id, "genkit.generate"), + streamOperation, + findGenkitSpan(events, streamOperation?.span.id, "genkit.generateStream"), + embedOperation, + findGenkitSpan(events, embedOperation?.span.id, "genkit.embed"), + ]; + + if (supportsActionSpans) { + const toolOperation = findLatestSpan(events, "genkit-tool-operation"); + const flowOperation = findLatestSpan(events, "genkit-flow-operation"); + summary.push( + toolOperation, + findGenkitSpan( + events, + toolOperation?.span.id, + "genkit.tool: summarizeCity", + ), + flowOperation, + findGenkitSpan(events, flowOperation?.span.id, "genkit.flow: recipeFlow"), + ); + } + + return summary.map((event) => + summarizeWrapperContract(event!, [ + "genkit.action_name", + "genkit.action_type", + "genkit.run_name", + "model", + "operation", + "provider", + "scenario", + ]), + ) as Json; +} + +export function defineGenkitInstrumentationAssertions(options: { + name: string; + runScenario: RunGenkitScenario; + snapshotName: string; + supportsActionSpans: boolean; + testFileUrl: string; + timeoutMs: number; +}): void { + const spanSnapshotPath = resolveFileSnapshotPath( + options.testFileUrl, + `${options.snapshotName}.span-events.json`, + ); + const testConfig = { + tags: [E2E_TAGS.hermetic], + timeout: options.timeoutMs, + }; + + describe(options.name, () => { + let events: CapturedLogEvent[] = []; + + beforeAll(async () => { + await withScenarioHarness(async (harness) => { + await options.runScenario(harness); + events = harness.events(); + }); + }, options.timeoutMs); + + test("captures the scenario root span", testConfig, () => { + const root = findLatestSpan(events, ROOT_NAME); + expect(root).toBeDefined(); + expect(root?.row.metadata).toMatchObject({ + scenario: SCENARIO_NAME, + }); + }); + + test("captures generate, stream, and embed spans", testConfig, () => { + const generateOperation = findLatestSpan( + events, + "genkit-generate-operation", + ); + const generateSpan = findGenkitSpan( + events, + generateOperation?.span.id, + "genkit.generate", + ); + const streamOperation = findLatestSpan(events, "genkit-stream-operation"); + const streamSpan = findGenkitSpan( + events, + streamOperation?.span.id, + "genkit.generateStream", + ); + const embedOperation = findLatestSpan(events, "genkit-embed-operation"); + const embedSpan = findGenkitSpan( + events, + embedOperation?.span.id, + "genkit.embed", + ); + + expect(generateSpan?.row.metadata).toMatchObject({ + provider: "genkit", + }); + expect(generateSpan?.row.metadata?.model).toEqual( + expect.stringContaining("gemini-2.5-flash-lite"), + ); + expect(generateSpan?.output).toBeDefined(); + expect(generateSpan?.metrics).toMatchObject({ + prompt_tokens: expect.any(Number), + completion_tokens: expect.any(Number), + tokens: expect.any(Number), + }); + + expect(streamSpan?.row.metadata).toMatchObject({ + provider: "genkit", + }); + expect(streamSpan?.output).toBeDefined(); + expect(streamSpan?.metrics?.time_to_first_token).toEqual( + expect.any(Number), + ); + + expect(embedSpan?.row.metadata).toMatchObject({ + provider: "genkit", + }); + expect(embedSpan?.row.metadata?.model).toEqual( + expect.stringContaining("gemini-embedding-001"), + ); + expect(embedSpan?.output).toMatchObject({ + embedding_count: 1, + }); + }); + + test.runIf(options.supportsActionSpans)( + "captures tool and flow action spans", + testConfig, + () => { + const toolOperation = findLatestSpan(events, "genkit-tool-operation"); + const toolSpan = findGenkitSpan( + events, + toolOperation?.span.id, + "genkit.tool: summarizeCity", + ); + const flowOperation = findLatestSpan(events, "genkit-flow-operation"); + const flowSpan = findGenkitSpan( + events, + flowOperation?.span.id, + "genkit.flow: recipeFlow", + ); + + expect(toolSpan?.row.metadata).toMatchObject({ + "genkit.action_name": "summarizeCity", + "genkit.action_type": "tool", + provider: "genkit", + }); + expect(toolSpan?.output).toMatchObject({ + summary: expect.any(String), + }); + + expect(flowSpan?.row.metadata).toMatchObject({ + "genkit.action_name": "recipeFlow", + "genkit.action_type": "flow", + provider: "genkit", + }); + expect(flowSpan?.output).toMatchObject({ + recipe: expect.any(String), + }); + }, + ); + + test("matches span snapshot", testConfig, async () => { + await expect( + formatJsonFileSnapshot( + buildSpanSummary(events, options.supportsActionSpans), + ), + ).toMatchFileSnapshot(spanSnapshotPath); + }); + }); +} diff --git a/e2e/scenarios/genkit-instrumentation/constants.mjs b/e2e/scenarios/genkit-instrumentation/constants.mjs new file mode 100644 index 000000000..8685f6f2b --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/constants.mjs @@ -0,0 +1,2 @@ +export const ROOT_NAME = "genkit-instrumentation-root"; +export const SCENARIO_NAME = "genkit-instrumentation"; diff --git a/e2e/scenarios/genkit-instrumentation/package.json b/e2e/scenarios/genkit-instrumentation/package.json new file mode 100644 index 000000000..2594b5506 --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/package.json @@ -0,0 +1,16 @@ +{ + "name": "@braintrust/e2e-genkit-instrumentation", + "private": true, + "braintrustScenario": { + "canary": { + "dependencies": { + "@genkit-ai/google-genai": "latest", + "genkit": "latest" + } + } + }, + "dependencies": { + "@genkit-ai/google-genai": "1.33.0", + "genkit": "1.33.0" + } +} diff --git a/e2e/scenarios/genkit-instrumentation/pnpm-lock.yaml b/e2e/scenarios/genkit-instrumentation/pnpm-lock.yaml new file mode 100644 index 000000000..aa789bd0d --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/pnpm-lock.yaml @@ -0,0 +1,4317 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@genkit-ai/google-genai': + specifier: 1.33.0 + version: 1.33.0(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)) + genkit: + specifier: 1.33.0 + version: 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0) + +packages: + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@dabh/diagnostics@2.0.8': + resolution: {integrity: sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==} + + '@fastify/busboy@3.2.0': + resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} + + '@firebase/app-check-interop-types@0.3.3': + resolution: {integrity: sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==} + + '@firebase/app-types@0.9.4': + resolution: {integrity: sha512-crX9TA5SVYZwLPG7/R16IsH8FLlgkPXjJUVhsVpHVDSqJiq3D/NuFTM5ctxGTExXAOeIn//69tQw47CPerM8MQ==} + + '@firebase/auth-interop-types@0.2.4': + resolution: {integrity: sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==} + + '@firebase/component@0.7.2': + resolution: {integrity: sha512-iyVDGc6Vjx7Rm0cAdccLH/NG6fADsgJak/XW9IA2lPf8AjIlsemOpFGKczYyPHxm4rnKdR8z6sK4+KEC7NwmEg==} + engines: {node: '>=20.0.0'} + + '@firebase/database-compat@2.1.3': + resolution: {integrity: sha512-GMyfWjD8mehjg/QpNkY/tl9G/MoeugPeg91n9D0atggxbWuKF/2KhVPHZDH+XmoP0EKYqMWYTtKxBsaBaNKLYQ==} + engines: {node: '>=20.0.0'} + + '@firebase/database-types@1.0.19': + resolution: {integrity: sha512-FqewjUZmV9LqFfuEnmgdcUpiOUz7qwLXxnm/H8BcMFEzQXtd1yyUDm8ex5VRad2nuTE+ahOuCjUAM/cyDncO+g==} + + '@firebase/database@1.1.2': + resolution: {integrity: sha512-lP96CMjMPy/+d1d9qaaHjHHdzdwvEOuyyLq9ehX89e2XMKwS1jHNzYBO+42bdSumuj5ukPbmnFtViZu8YOMT+w==} + engines: {node: '>=20.0.0'} + + '@firebase/logger@0.5.0': + resolution: {integrity: sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==} + engines: {node: '>=20.0.0'} + + '@firebase/util@1.15.0': + resolution: {integrity: sha512-AmWf3cHAOMbrCPG4xdPKQaj5iHnyYfyLKZxwz+Xf55bqKbpAmcYifB4jQinT2W9XhDRHISOoPyBOariJpCG6FA==} + engines: {node: '>=20.0.0'} + + '@genkit-ai/ai@1.33.0': + resolution: {integrity: sha512-d58ByMSIHy8cwKoq6CXdpIk7BMq3VIFi+5lfP4TlZiDxC+HQX1P+jTNjgGdCCjqIwhiF5qjqqX0/PbdX/YP1rg==} + + '@genkit-ai/core@1.33.0': + resolution: {integrity: sha512-0adFPBl/nsxuV+B94nyzwRkRHKkW5eCxQbv/80f0OdkcNpQS6CwamAK+kttjplHdUvq9Yu70PzRQz7Sx9tj5NQ==} + + '@genkit-ai/firebase@1.33.0': + resolution: {integrity: sha512-bRI6GdyEeZ8koCZ30BxYhB9RKa77/fVnhtc5aetMI1AE63be+SCwpSYanp/9YoUgcjToaRrF7KRnGAiDehcZ9w==} + peerDependencies: + '@google-cloud/firestore': ^7.11.0 + firebase: '>=11.5.0' + firebase-admin: '>=12.2' + genkit: ^1.33.0 + peerDependenciesMeta: + firebase: + optional: true + + '@genkit-ai/google-cloud@1.33.0': + resolution: {integrity: sha512-dj62UjoY7JpS1lm1GcjxV4/h/BnyL/zEswvvHWqVOY2rRuoCws3aNvJGPoxz67cOH9kDkkLN1BaGz9NbBGhTZg==} + peerDependencies: + genkit: ^1.33.0 + + '@genkit-ai/google-genai@1.33.0': + resolution: {integrity: sha512-OcwMAMrK1gdKzt8QKlup1GOc8nMgUZ8oiOFcLaIFG4fKhFs7zqLTgOxyUqCVeGH78vPahcLO4mA7aqScxte6OQ==} + peerDependencies: + genkit: ^1.33.0 + + '@google-cloud/common@5.0.2': + resolution: {integrity: sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA==} + engines: {node: '>=14.0.0'} + + '@google-cloud/firestore@7.11.6': + resolution: {integrity: sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==} + engines: {node: '>=14.0.0'} + + '@google-cloud/logging-winston@6.0.1': + resolution: {integrity: sha512-tgA/qe/aGZITMrJ/5Tuykv234pLb/Qo6iDZ8SDkjbsiIy69mLQmbphrUd/IqnE17BSDfrwDUckvWdghiy8b+Qg==} + engines: {node: '>=14.0.0'} + peerDependencies: + winston: '>=3.2.1' + + '@google-cloud/logging@11.2.1': + resolution: {integrity: sha512-2h9HBJG3OAsvzXmb81qXmaTPfXYU7KJTQUxunoOKFGnY293YQ/eCkW1Y5mHLocwpEqeqQYT/Qvl6Tk+Q7PfStw==} + engines: {node: '>=14.0.0'} + + '@google-cloud/modelarmor@0.4.1': + resolution: {integrity: sha512-CT9TpQF443aatjhRRvazrYNOvUot26HnFP3hhgmV89QYygNPB6owWvGFFOTsKK4zSvTDfkeeb+E6diVXxn9t4g==} + engines: {node: '>=14.0.0'} + + '@google-cloud/opentelemetry-cloud-monitoring-exporter@0.19.0': + resolution: {integrity: sha512-5SOPXwC6RET4ZvXxw5D97dp8fWpqWEunHrzrUUGXhG4UAeedQe1KvYV8CK+fnaAbN2l2ha6QDYspT6z40TVY0g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + '@opentelemetry/core': ^1.0.0 + '@opentelemetry/resources': ^1.0.0 + '@opentelemetry/sdk-metrics': ^1.0.0 + + '@google-cloud/opentelemetry-cloud-trace-exporter@2.4.1': + resolution: {integrity: sha512-Dq2IyAyA9PCjbjLOn86i2byjkYPC59b5ic8k/L4q5bBWH0Jro8lzMs8C0G5pJfqh2druj8HF+oAIAlSdWQ+Z9Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + '@opentelemetry/core': ^1.0.0 + '@opentelemetry/resources': ^1.0.0 + '@opentelemetry/sdk-trace-base': ^1.0.0 + + '@google-cloud/opentelemetry-resource-util@2.4.0': + resolution: {integrity: sha512-/7ujlMoKtDtrbQlJihCjQnm31n2s2RTlvJqcSbt2jV3OkCzPAdo3u31Q13HNugqtIRUSk7bUoLx6AzhURkhW4w==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/resources': ^1.0.0 + + '@google-cloud/paginator@5.0.2': + resolution: {integrity: sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==} + engines: {node: '>=14.0.0'} + + '@google-cloud/precise-date@4.0.0': + resolution: {integrity: sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==} + engines: {node: '>=14.0.0'} + + '@google-cloud/projectify@4.0.0': + resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==} + engines: {node: '>=14.0.0'} + + '@google-cloud/promisify@4.0.0': + resolution: {integrity: sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==} + engines: {node: '>=14'} + + '@google-cloud/storage@7.19.0': + resolution: {integrity: sha512-n2FjE7NAOYyshogdc7KQOl/VZb4sneqPjWouSyia9CMDdMhRX5+RIbqalNmC7LOLzuLAN89VlF2HvG8na9G+zQ==} + engines: {node: '>=14'} + + '@grpc/grpc-js@1.14.3': + resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.15': + resolution: {integrity: sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==} + engines: {node: '>=6'} + hasBin: true + + '@grpc/proto-loader@0.8.0': + resolution: {integrity: sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==} + engines: {node: '>=6'} + hasBin: true + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + + '@jsep-plugin/assignment@1.3.0': + resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + + '@jsep-plugin/regex@1.0.4': + resolution: {integrity: sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + + '@nodable/entities@2.1.0': + resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==} + + '@opentelemetry/api-logs@0.52.1': + resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.9.1': + resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/auto-instrumentations-node@0.49.2': + resolution: {integrity: sha512-xtETEPmAby/3MMmedv8Z/873sdLTWg+Vq98rtm4wbwvAiXBB/ao8qRyzRlvR2MR6puEr+vIB/CXeyJnzNA3cyw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.4.1 + + '@opentelemetry/context-async-hooks@1.25.1': + resolution: {integrity: sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.25.1': + resolution: {integrity: sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.30.1': + resolution: {integrity: sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-trace-otlp-grpc@0.52.1': + resolution: {integrity: sha512-pVkSH20crBwMTqB3nIN4jpQKUEoB0Z94drIHpYyEqs7UBr+I0cpYyOR3bqjA/UasQUMROb3GX8ZX4/9cVRqGBQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-http@0.52.1': + resolution: {integrity: sha512-05HcNizx0BxcFKKnS5rwOV+2GevLTVIRA0tRgWYyw4yCgR53Ic/xk83toYKts7kbzcI+dswInUg/4s8oyA+tqg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-proto@0.52.1': + resolution: {integrity: sha512-pt6uX0noTQReHXNeEslQv7x311/F1gJzMnp1HD2qgypLRPbXDeMzzeTngRTUaUbP6hqWNtPxuLr4DEoZG+TcEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-zipkin@1.25.1': + resolution: {integrity: sha512-RmOwSvkimg7ETwJbUOPTMhJm9A9bG1U8s7Zo3ajDh4zM7eYcycQ0dM7FbLD6NXWbI2yj7UY4q8BKinKYBQksyw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation-amqplib@0.41.0': + resolution: {integrity: sha512-00Oi6N20BxJVcqETjgNzCmVKN+I5bJH/61IlHiIWd00snj1FdgiIKlpE4hYVacTB2sjIBB3nTbHskttdZEE2eg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-aws-lambda@0.43.0': + resolution: {integrity: sha512-pSxcWlsE/pCWQRIw92sV2C+LmKXelYkjkA7C5s39iPUi4pZ2lA1nIiw+1R/y2pDEhUHcaKkNyljQr3cx9ZpVlQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-aws-sdk@0.43.1': + resolution: {integrity: sha512-qLT2cCniJ5W+6PFzKbksnoIQuq9pS83nmgaExfUwXVvlwi0ILc50dea0tWBHZMkdIDa/zZdcuFrJ7+fUcSnRow==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-bunyan@0.40.0': + resolution: {integrity: sha512-aZ4cXaGWwj79ZXSYrgFVsrDlE4mmf2wfvP9bViwRc0j75A6eN6GaHYHqufFGMTCqASQn5pIjjP+Bx+PWTGiofw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-cassandra-driver@0.40.0': + resolution: {integrity: sha512-JxbM39JU7HxE9MTKKwi6y5Z3mokjZB2BjwfqYi4B3Y29YO3I42Z7eopG6qq06yWZc+nQli386UDQe0d9xKmw0A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-connect@0.38.0': + resolution: {integrity: sha512-2/nRnx3pjYEmdPIaBwtgtSviTKHWnDZN3R+TkRUnhIVrvBKVcq+I5B2rtd6mr6Fe9cHlZ9Ojcuh7pkNh/xdWWg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-cucumber@0.8.0': + resolution: {integrity: sha512-ieTm4RBIlZt2brPwtX5aEZYtYnkyqhAVXJI9RIohiBVMe5DxiwCwt+2Exep/nDVqGPX8zRBZUl4AEw423OxJig==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation-dataloader@0.11.0': + resolution: {integrity: sha512-27urJmwkH4KDaMJtEv1uy2S7Apk4XbN4AgWMdfMJbi7DnOduJmeuA+DpJCwXB72tEWXo89z5T3hUVJIDiSNmNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-dns@0.38.0': + resolution: {integrity: sha512-Um07I0TQXDWa+ZbEAKDFUxFH40dLtejtExDOMLNJ1CL8VmOmA71qx93Qi/QG4tGkiI1XWqr7gF/oiMCJ4m8buQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-express@0.41.1': + resolution: {integrity: sha512-uRx0V3LPGzjn2bxAnV8eUsDT82vT7NTwI0ezEuPMBOTOsnPpGhWdhcdNdhH80sM4TrWrOfXm9HGEdfWE3TRIww==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-fastify@0.38.0': + resolution: {integrity: sha512-HBVLpTSYpkQZ87/Df3N0gAw7VzYZV3n28THIBrJWfuqw3Or7UqdhnjeuMIPQ04BKk3aZc0cWn2naSQObbh5vXw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-fs@0.14.0': + resolution: {integrity: sha512-pVc8P5AgliC1DphyyBUgsxXlm2XaPH4BpYvt7rAZDMIqUpRk8gs19SioABtKqqxvFzg5jPtgJfJsdxq0Y+maLw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-generic-pool@0.38.1': + resolution: {integrity: sha512-WvssuKCuavu/hlq661u82UWkc248cyI/sT+c2dEIj6yCk0BUkErY1D+9XOO+PmHdJNE+76i2NdcvQX5rJrOe/w==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-graphql@0.42.0': + resolution: {integrity: sha512-N8SOwoKL9KQSX7z3gOaw5UaTeVQcfDO1c21csVHnmnmGUoqsXbArK2B8VuwPWcv6/BC/i3io+xTo7QGRZ/z28Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-grpc@0.52.1': + resolution: {integrity: sha512-EdSDiDSAO+XRXk/ZN128qQpBo1I51+Uay/LUPcPQhSRGf7fBPIEUBeOLQiItguGsug5MGOYjql2w/1wCQF3fdQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-hapi@0.40.0': + resolution: {integrity: sha512-8U/w7Ifumtd2bSN1OLaSwAAFhb9FyqWUki3lMMB0ds+1+HdSxYBe9aspEJEgvxAqOkrQnVniAPTEGf1pGM7SOw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-http@0.52.1': + resolution: {integrity: sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-ioredis@0.42.0': + resolution: {integrity: sha512-P11H168EKvBB9TUSasNDOGJCSkpT44XgoM6d3gRIWAa9ghLpYhl0uRkS8//MqPzcJVHr3h3RmfXIpiYLjyIZTw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-kafkajs@0.2.0': + resolution: {integrity: sha512-uKKmhEFd0zR280tJovuiBG7cfnNZT4kvVTvqtHPxQP7nOmRbJstCYHFH13YzjVcKjkmoArmxiSulmZmF7SLIlg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-knex@0.39.0': + resolution: {integrity: sha512-lRwTqIKQecPWDkH1KEcAUcFhCaNssbKSpxf4sxRTAROCwrCEnYkjOuqJHV+q1/CApjMTaKu0Er4LBv/6bDpoxA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-koa@0.42.0': + resolution: {integrity: sha512-H1BEmnMhho8o8HuNRq5zEI4+SIHDIglNB7BPKohZyWG4fWNuR7yM4GTlR01Syq21vODAS7z5omblScJD/eZdKw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-lru-memoizer@0.39.0': + resolution: {integrity: sha512-eU1Wx1RRTR/2wYXFzH9gcpB8EPmhYlNDIUHzUXjyUE0CAXEJhBLkYNlzdaVCoQDw2neDqS+Woshiia6+emWK9A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-memcached@0.38.0': + resolution: {integrity: sha512-tPmyqQEZNyrvg6G+iItdlguQEcGzfE+bJkpQifmBXmWBnoS5oU3UxqtyYuXGL2zI9qQM5yMBHH4nRXWALzy7WA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mongodb@0.46.0': + resolution: {integrity: sha512-VF/MicZ5UOBiXrqBslzwxhN7TVqzu1/LN/QDpkskqM0Zm0aZ4CVRbUygL8d7lrjLn15x5kGIe8VsSphMfPJzlA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mongoose@0.41.0': + resolution: {integrity: sha512-ivJg4QnnabFxxoI7K8D+in7hfikjte38sYzJB9v1641xJk9Esa7jM3hmbPB7lxwcgWJLVEDvfPwobt1if0tXxA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mysql2@0.40.0': + resolution: {integrity: sha512-0xfS1xcqUmY7WE1uWjlmI67Xg3QsSUlNT+AcXHeA4BDUPwZtWqF4ezIwLgpVZfHOnkAEheqGfNSWd1PIu3Wnfg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mysql@0.40.0': + resolution: {integrity: sha512-d7ja8yizsOCNMYIJt5PH/fKZXjb/mS48zLROO4BzZTtDfhNCl2UM/9VIomP2qkGIFVouSJrGr/T00EzY7bPtKA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-nestjs-core@0.39.0': + resolution: {integrity: sha512-mewVhEXdikyvIZoMIUry8eb8l3HUjuQjSjVbmLVTt4NQi35tkpnHQrG9bTRBrl3403LoWZ2njMPJyg4l6HfKvA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-net@0.38.0': + resolution: {integrity: sha512-stjow1PijcmUquSmRD/fSihm/H61DbjPlJuJhWUe7P22LFPjFhsrSeiB5vGj3vn+QGceNAs+kioUTzMGPbNxtg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pg@0.43.0': + resolution: {integrity: sha512-og23KLyoxdnAeFs1UWqzSonuCkePUzCX30keSYigIzJe/6WSYA8rnEI5lobcxPEzg+GcU06J7jzokuEHbjVJNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pino@0.41.0': + resolution: {integrity: sha512-Kpv0fJRk/8iMzMk5Ue5BsUJfHkBJ2wQoIi/qduU1a1Wjx9GLj6J2G17PHjPK5mnZjPNzkFOXFADZMfgDioliQw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-redis-4@0.41.1': + resolution: {integrity: sha512-UqJAbxraBk7s7pQTlFi5ND4sAUs4r/Ai7gsAVZTQDbHl2kSsOp7gpHcpIuN5dpcI2xnuhM2tkH4SmEhbrv2S6Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-redis@0.41.0': + resolution: {integrity: sha512-RJ1pwI3btykp67ts+5qZbaFSAAzacucwBet5/5EsKYtWBpHbWwV/qbGN/kIBzXg5WEZBhXLrR/RUq0EpEUpL3A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-restify@0.40.0': + resolution: {integrity: sha512-sm/rH/GysY/KOEvZqYBZSLYFeXlBkHCgqPDgWc07tz+bHCN6mPs9P3otGOSTe7o3KAIM8Nc6ncCO59vL+jb2cA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-router@0.39.0': + resolution: {integrity: sha512-LaXnVmD69WPC4hNeLzKexCCS19hRLrUw3xicneAMkzJSzNJvPyk7G6I7lz7VjQh1cooObPBt9gNyd3hhTCUrag==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-socket.io@0.41.0': + resolution: {integrity: sha512-7fzDe9/FpO6NFizC/wnzXXX7bF9oRchsD//wFqy5g5hVEgXZCQ70IhxjrKdBvgjyIejR9T9zTvfQ6PfVKfkCAw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-tedious@0.13.0': + resolution: {integrity: sha512-Pob0+0R62AqXH50pjazTeGBy/1+SK4CYpFUBV5t7xpbpeuQezkkgVGvLca84QqjBqQizcXedjpUJLgHQDixPQg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-undici@0.5.0': + resolution: {integrity: sha512-aNTeSrFAVcM9qco5DfZ9DNXu6hpMRe8Kt8nCDHfMWDB3pwgGVUE76jTdohc+H/7eLRqh4L7jqs5NSQoHw7S6ww==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.7.0 + + '@opentelemetry/instrumentation-winston@0.39.0': + resolution: {integrity: sha512-v/1xziLJ9CyB3YDjBSBzbB70Qd0JwWTo36EqWK5m3AR0CzsyMQQmf3ZIZM6sgx7hXMcRQ0pnEYhg6nhrUQPm9A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.52.1': + resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.52.1': + resolution: {integrity: sha512-z175NXOtX5ihdlshtYBe5RpGeBoTXVCKPPLiQlD6FHvpM4Ch+p2B0yWKYSrBfLH24H9zjJiBdTrtD+hLlfnXEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-grpc-exporter-base@0.52.1': + resolution: {integrity: sha512-zo/YrSDmKMjG+vPeA9aBBrsQM9Q/f2zo6N04WMB3yNldJRsgpRBeLLwvAt/Ba7dpehDLOEFBd1i2JCoaFtpCoQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-transformer@0.52.1': + resolution: {integrity: sha512-I88uCZSZZtVa0XniRqQWKbjAUm73I8tpEy/uJYPPYw5d7BRdVk0RfTBQw8kSUl01oVWEuqxLDa802222MYyWHg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/propagation-utils@0.30.16': + resolution: {integrity: sha512-ZVQ3Z/PQ+2GQlrBfbMMMT0U7MzvYZLCPP800+ooyaBqm4hMvuQHfP028gB9/db0mwkmyEAMad9houukUVxhwcw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/propagator-aws-xray@1.26.2': + resolution: {integrity: sha512-k43wxTjKYvwfce9L4eT8fFYy/ATmCfPHZPZsyT/6ABimf2KE1HafoOsIcxLOtmNSZt6dCvBIYCrXaOWta20xJg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-b3@1.25.1': + resolution: {integrity: sha512-p6HFscpjrv7//kE+7L+3Vn00VEDUJB0n6ZrjkTYHrJ58QZ8B3ajSJhRbCcY6guQ3PDjTbxWklyvIN2ojVbIb1A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-jaeger@1.25.1': + resolution: {integrity: sha512-nBprRf0+jlgxks78G/xq72PipVK+4or9Ypntw0gVZYNTCSK8rg5SeaGV19tV920CMqBD/9UIOiFr23Li/Q8tiA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/redis-common@0.36.2': + resolution: {integrity: sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==} + engines: {node: '>=14'} + + '@opentelemetry/resource-detector-alibaba-cloud@0.29.7': + resolution: {integrity: sha512-PExUl/R+reSQI6Y/eNtgAsk6RHk1ElYSzOa8/FHfdc/nLmx9sqMasBEpLMkETkzDP7t27ORuXe4F9vwkV2uwwg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-aws@1.12.0': + resolution: {integrity: sha512-Cvi7ckOqiiuWlHBdA1IjS0ufr3sltex2Uws2RK6loVp4gzIJyOijsddAI6IZ5kiO8h/LgCWe8gxPmwkTKImd+Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-azure@0.2.12': + resolution: {integrity: sha512-iIarQu6MiCjEEp8dOzmBvCSlRITPFTinFB2oNKAjU6xhx8d7eUcjNOKhBGQTvuCriZrxrEvDaEEY9NfrPQ6uYQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-container@0.4.4': + resolution: {integrity: sha512-ZEN2mq7lIjQWJ8NTt1umtr6oT/Kb89856BOmESLSvgSHbIwOFYs7cSfSRH5bfiVw6dXTQAVbZA/wLgCHKrebJA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-gcp@0.29.13': + resolution: {integrity: sha512-vdotx+l3Q+89PeyXMgKEGnZ/CwzwMtuMi/ddgD9/5tKZ08DfDGB2Npz9m2oXPHRCjc4Ro6ifMqFlRyzIvgOjhg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resources@1.25.1': + resolution: {integrity: sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.52.1': + resolution: {integrity: sha512-MBYh+WcPPsN8YpRHRmK1Hsca9pVlyyKd4BxOC4SsgHACnl/bPp4Cri9hWhVm5+2tiQ9Zf4qSc1Jshw9tOLGWQA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.25.1': + resolution: {integrity: sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-node@0.52.1': + resolution: {integrity: sha512-uEG+gtEr6eKd8CVWeKMhH2olcCHM9dEK68pe0qE0be32BcCRsvYURhHaD1Srngh1SQcnQzZ4TP324euxqtBOJA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@1.25.1': + resolution: {integrity: sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@1.25.1': + resolution: {integrity: sha512-nMcjFIKxnFqoez4gUmihdBrbpsEnAX/Xj16sGvZm+guceYE0NE00vLhpDVK6f3q8Q4VFI5xG8JjlXKMB/SkTTQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.25.1': + resolution: {integrity: sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==} + engines: {node: '>=14'} + + '@opentelemetry/semantic-conventions@1.28.0': + resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} + engines: {node: '>=14'} + + '@opentelemetry/semantic-conventions@1.40.0': + resolution: {integrity: sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==} + engines: {node: '>=14'} + + '@opentelemetry/sql-common@0.40.1': + resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.1.0 + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + + '@so-ric/colorspace@1.1.6': + resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==} + + '@tootallnate/once@2.0.1': + resolution: {integrity: sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==} + engines: {node: '>= 10'} + + '@types/aws-lambda@8.10.122': + resolution: {integrity: sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==} + + '@types/bunyan@1.8.9': + resolution: {integrity: sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==} + + '@types/caseless@0.12.5': + resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} + + '@types/connect@3.4.36': + resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/jsonwebtoken@9.0.10': + resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} + + '@types/long@4.0.2': + resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} + + '@types/memcached@2.2.10': + resolution: {integrity: sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/mysql@2.15.22': + resolution: {integrity: sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==} + + '@types/node@20.19.39': + resolution: {integrity: sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==} + + '@types/node@25.6.0': + resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + + '@types/pg-pool@2.0.4': + resolution: {integrity: sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==} + + '@types/pg@8.6.1': + resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} + + '@types/request@2.48.13': + resolution: {integrity: sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==} + + '@types/shimmer@1.2.0': + resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} + + '@types/tedious@4.0.14': + resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + arrify@2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + + async-mutex@0.5.0: + resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} + + async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + body-parser@1.20.5: + resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + brace-expansion@2.1.0: + resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-convert@3.1.3: + resolution: {integrity: sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==} + engines: {node: '>=14.6'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-name@2.1.0: + resolution: {integrity: sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==} + engines: {node: '>=12.20'} + + color-string@2.1.4: + resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} + engines: {node: '>=18'} + + color@5.0.3: + resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} + engines: {node: '>=18'} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cors@2.8.6: + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} + + dotprompt@1.1.2: + resolution: {integrity: sha512-24EU+eORQbPywBicIP44BiqykzEXFwZq1ZQKO5TEr9KrrENyDA7I1NzqhtmmEdQVfAXka0DEbSLPN5nerCqJ8A==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventid@2.0.1: + resolution: {integrity: sha512-sPNTqiMokAvV048P2c9+foqVJzk49o6d4e0D/sq5jog3pw+4kBgyR0gaM1FM7Mx6Kzd9dztesh9oYz1LWWOpzw==} + engines: {node: '>=10'} + + express@4.22.1: + resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} + engines: {node: '>= 0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + farmhash-modern@1.1.0: + resolution: {integrity: sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==} + engines: {node: '>=18.0.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.1: + resolution: {integrity: sha512-h2r7rcm6Ee/J8o0LD5djLuFVcfbZxhvho4vvsbeV0aMvXjUgqv4YpxpkEx0d68l6+IleVfLAdVEfhR7QNMkGHQ==} + + fast-xml-builder@1.1.7: + resolution: {integrity: sha512-Yh7/7rQuMXICNr0oMYDR2yHP6oUvmQsTToFeOWj/kIDhAwQ+c4Ol/lbcwOmEM5OHYQmh6S6EQSQ1sljCKP36bQ==} + + fast-xml-parser@5.7.2: + resolution: {integrity: sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w==} + hasBin: true + + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + + firebase-admin@13.8.0: + resolution: {integrity: sha512-iawoQkmZbsA+2DY5UEuB8f6jSlskzzySoye0D2F6e3zlDZX9DUcXf0HhZqLUn/P6WhLGvTf6ZtCmshZvhAgTYg==} + engines: {node: '>=18'} + + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@2.5.5: + resolution: {integrity: sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==} + engines: {node: '>= 0.12'} + + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + functional-red-black-tree@1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gaxios@7.1.4: + resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} + engines: {node: '>=18'} + + gcp-metadata@6.1.1: + resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==} + engines: {node: '>=14'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + + genkit@1.33.0: + resolution: {integrity: sha512-46cS8uUE+Et/glO0zt4JxR/2RjJ2b9OCOYfIgmJKaOk9vdjLBVBIBcJPNQZ7ToGnr6TJE3ZfM6jyCRfxd7NFQA==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-port@5.1.1: + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + google-auth-library@10.6.2: + resolution: {integrity: sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==} + engines: {node: '>=18'} + + google-auth-library@9.15.1: + resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==} + engines: {node: '>=14'} + + google-gax@4.6.1: + resolution: {integrity: sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==} + engines: {node: '>=14'} + + google-gax@5.0.6: + resolution: {integrity: sha512-1kGbqVQBZPAAu4+/R1XxPQKP0ydbNYoLAr4l0ZO2bMV0kLyLW4I1gAk++qBLWt7DPORTzmWRMsCZe86gDjShJA==} + engines: {node: '>=18'} + + google-logging-utils@0.0.2: + resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==} + engines: {node: '>=14'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + + googleapis-common@7.2.0: + resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==} + engines: {node: '>=14.0.0'} + + googleapis@137.1.0: + resolution: {integrity: sha512-2L7SzN0FLHyQtFmyIxrcXhgust77067pkkduqkbIpDuj9JzVnByxsRrcRfUMFQam3rQkWW2B0f1i40IwKDWIVQ==} + engines: {node: '>=14.0.0'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + + handlebars@4.7.9: + resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.3: + resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + engines: {node: '>= 0.4'} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + import-in-the-middle@1.15.0: + resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jose@4.15.9: + resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + + jsep@1.4.0: + resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} + engines: {node: '>= 10.16.0'} + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonpath-plus@10.4.0: + resolution: {integrity: sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==} + engines: {node: '>=18.0.0'} + hasBin: true + + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} + engines: {node: '>=12', npm: '>=6'} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jwks-rsa@3.2.2: + resolution: {integrity: sha512-BqTyEDV+lS8F2trk3A+qJnxV5Q9EqKCBJOPti3W97r7qTympCZjb7h2X6f2kc+0K3rsSTY1/6YG2eaXKoj497w==} + engines: {node: '>=14'} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + + limiter@1.1.5: + resolution: {integrity: sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.mapvalues@4.6.0: + resolution: {integrity: sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + logform@2.7.0: + resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} + engines: {node: '>= 12.0.0'} + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-memoizer@2.3.0: + resolution: {integrity: sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + module-details-from-path@1.0.4: + resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + node-forge@1.4.0: + resolution: {integrity: sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==} + engines: {node: '>= 6.13.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + + path-expression-matcher@1.5.0: + resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} + engines: {node: '>=14.0.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.13: + resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-protocol@1.13.0: + resolution: {integrity: sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.1: + resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + proto3-json-serializer@2.0.2: + resolution: {integrity: sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==} + engines: {node: '>=14.0.0'} + + proto3-json-serializer@3.0.4: + resolution: {integrity: sha512-E1sbAYg3aEbXrq0n1ojJkRHQJGE1kaE/O6GLA94y8rnJBfgvOPTOd1b9hOceQK1FFZI9qMh1vBERCyO2ifubcw==} + engines: {node: '>=18'} + + protobufjs@7.5.6: + resolution: {integrity: sha512-M71sTMB146U3u0di3yup8iM+zv8yPRNQVr1KK4tyBitl3qFvEGucq/rGDRShD2rsJhtN02RJaJ7j5X5hmy8SJg==} + engines: {node: '>=12.0.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + pumpify@2.0.1: + resolution: {integrity: sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==} + + qs@6.14.2: + resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} + engines: {node: '>=0.6'} + + qs@6.15.1: + resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==} + engines: {node: '>=0.6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-in-the-middle@7.5.2: + resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} + engines: {node: '>=8.6.0'} + + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + + retry-request@7.0.2: + resolution: {integrity: sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==} + engines: {node: '>=14'} + + retry-request@8.0.2: + resolution: {integrity: sha512-JzFPAfklk1kjR1w76f0QOIhoDkNkSqW8wYKT08n9yysTmZfB+RQ2QoXoTAeOi1HD9ZipTyTAZg3c4pM/jeqgSw==} + engines: {node: '>=18'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stream-events@1.0.5: + resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==} + + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strnum@2.2.3: + resolution: {integrity: sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==} + + stubs@3.0.0: + resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + teeny-request@10.1.2: + resolution: {integrity: sha512-Xj0ZAQ0CeuQn6UxCDPLbFRlgcSTUEyO3+wiepr2grjIjyL/lMMs1Z4OwXn8kLvn/V1OuaEP0UY7Na6UDNNsYrQ==} + engines: {node: '>=18'} + + teeny-request@9.0.0: + resolution: {integrity: sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==} + engines: {node: '>=14'} + + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@7.19.2: + resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uri-templates@0.2.0: + resolution: {integrity: sha512-EWkjYEN0L6KOfEoOH6Wj4ghQqU7eBZMJqRHQnxQAq+dSEzRPClkWjf8557HkWQXF6BrAUoLSAyy9i3RVTliaNg==} + + url-template@2.0.8: + resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + uuid@11.1.1: + resolution: {integrity: sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==} + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + winston-transport@4.9.0: + resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} + engines: {node: '>= 12.0.0'} + + winston@3.19.0: + resolution: {integrity: sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==} + engines: {node: '>= 12.0.0'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.8.4: + resolution: {integrity: sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@cfworker/json-schema@4.1.1': + optional: true + + '@colors/colors@1.6.0': + optional: true + + '@dabh/diagnostics@2.0.8': + dependencies: + '@so-ric/colorspace': 1.1.6 + enabled: 2.0.0 + kuler: 2.0.0 + optional: true + + '@fastify/busboy@3.2.0': + optional: true + + '@firebase/app-check-interop-types@0.3.3': + optional: true + + '@firebase/app-types@0.9.4': + dependencies: + '@firebase/logger': 0.5.0 + optional: true + + '@firebase/auth-interop-types@0.2.4': + optional: true + + '@firebase/component@0.7.2': + dependencies: + '@firebase/util': 1.15.0 + tslib: 2.8.1 + optional: true + + '@firebase/database-compat@2.1.3': + dependencies: + '@firebase/component': 0.7.2 + '@firebase/database': 1.1.2 + '@firebase/database-types': 1.0.19 + '@firebase/logger': 0.5.0 + '@firebase/util': 1.15.0 + tslib: 2.8.1 + optional: true + + '@firebase/database-types@1.0.19': + dependencies: + '@firebase/app-types': 0.9.4 + '@firebase/util': 1.15.0 + optional: true + + '@firebase/database@1.1.2': + dependencies: + '@firebase/app-check-interop-types': 0.3.3 + '@firebase/auth-interop-types': 0.2.4 + '@firebase/component': 0.7.2 + '@firebase/logger': 0.5.0 + '@firebase/util': 1.15.0 + faye-websocket: 0.11.4 + tslib: 2.8.1 + optional: true + + '@firebase/logger@0.5.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@firebase/util@1.15.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@genkit-ai/ai@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0))': + dependencies: + '@genkit-ai/core': 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)) + '@opentelemetry/api': 1.9.1 + '@types/node': 20.19.39 + colorette: 2.0.20 + dotprompt: 1.1.2 + handlebars: 4.7.9 + json5: 2.2.3 + node-fetch: 3.3.2 + partial-json: 0.1.7 + uri-templates: 0.2.0 + uuid: 10.0.0 + transitivePeerDependencies: + - '@google-cloud/firestore' + - bufferutil + - encoding + - firebase + - firebase-admin + - genkit + - supports-color + - utf-8-validate + + '@genkit-ai/core@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0))': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + '@types/json-schema': 7.0.15 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + async-mutex: 0.5.0 + cors: 2.8.6 + dotprompt: 1.1.2 + express: 4.22.1 + get-port: 5.1.1 + json-schema: 0.4.0 + ws: 8.20.0 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + optionalDependencies: + '@cfworker/json-schema': 4.1.1 + '@genkit-ai/firebase': 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)) + transitivePeerDependencies: + - '@google-cloud/firestore' + - bufferutil + - encoding + - firebase + - firebase-admin + - genkit + - supports-color + - utf-8-validate + + '@genkit-ai/firebase@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0))': + dependencies: + '@genkit-ai/google-cloud': 1.33.0(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)) + '@google-cloud/firestore': 7.11.6 + firebase-admin: 13.8.0 + genkit: 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0) + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@genkit-ai/google-cloud@1.33.0(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0))': + dependencies: + '@google-cloud/logging-winston': 6.0.1(winston@3.19.0) + '@google-cloud/modelarmor': 0.4.1 + '@google-cloud/opentelemetry-cloud-monitoring-exporter': 0.19.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.1)) + '@google-cloud/opentelemetry-cloud-trace-exporter': 2.4.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.1)) + '@google-cloud/opentelemetry-resource-util': 2.4.0(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1)) + '@opentelemetry/api': 1.9.1 + '@opentelemetry/auto-instrumentations-node': 0.49.2(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pino': 0.41.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-winston': 0.39.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + genkit: 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0) + google-auth-library: 9.15.1 + node-fetch: 3.3.2 + winston: 3.19.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@genkit-ai/google-genai@1.33.0(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0))': + dependencies: + genkit: 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0) + google-auth-library: 9.15.1 + jsonpath-plus: 10.4.0 + transitivePeerDependencies: + - encoding + - supports-color + + '@google-cloud/common@5.0.2': + dependencies: + '@google-cloud/projectify': 4.0.0 + '@google-cloud/promisify': 4.0.0 + arrify: 2.0.1 + duplexify: 4.1.3 + extend: 3.0.2 + google-auth-library: 9.15.1 + html-entities: 2.6.0 + retry-request: 7.0.2 + teeny-request: 9.0.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/firestore@7.11.6': + dependencies: + '@opentelemetry/api': 1.9.1 + fast-deep-equal: 3.1.3 + functional-red-black-tree: 1.0.1 + google-gax: 4.6.1 + protobufjs: 7.5.6 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/logging-winston@6.0.1(winston@3.19.0)': + dependencies: + '@google-cloud/logging': 11.2.1 + google-auth-library: 9.15.1 + lodash.mapvalues: 4.6.0 + winston: 3.19.0 + winston-transport: 4.9.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/logging@11.2.1': + dependencies: + '@google-cloud/common': 5.0.2 + '@google-cloud/paginator': 5.0.2 + '@google-cloud/projectify': 4.0.0 + '@google-cloud/promisify': 4.0.0 + '@opentelemetry/api': 1.9.1 + arrify: 2.0.1 + dot-prop: 6.0.1 + eventid: 2.0.1 + extend: 3.0.2 + gcp-metadata: 6.1.1 + google-auth-library: 9.15.1 + google-gax: 4.6.1 + on-finished: 2.4.1 + pumpify: 2.0.1 + stream-events: 1.0.5 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/modelarmor@0.4.1': + dependencies: + google-gax: 5.0.6 + transitivePeerDependencies: + - supports-color + optional: true + + '@google-cloud/opentelemetry-cloud-monitoring-exporter@0.19.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.1))': + dependencies: + '@google-cloud/opentelemetry-resource-util': 2.4.0(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1)) + '@google-cloud/precise-date': 4.0.0 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.1) + google-auth-library: 9.15.1 + googleapis: 137.1.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/opentelemetry-cloud-trace-exporter@2.4.1(@opentelemetry/api@1.9.1)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.1))': + dependencies: + '@google-cloud/opentelemetry-resource-util': 2.4.0(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1)) + '@grpc/grpc-js': 1.14.3 + '@grpc/proto-loader': 0.7.15 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + google-auth-library: 9.15.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/opentelemetry-resource-util@2.4.0(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1))': + dependencies: + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + gcp-metadata: 6.1.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@google-cloud/paginator@5.0.2': + dependencies: + arrify: 2.0.1 + extend: 3.0.2 + optional: true + + '@google-cloud/precise-date@4.0.0': + optional: true + + '@google-cloud/projectify@4.0.0': + optional: true + + '@google-cloud/promisify@4.0.0': + optional: true + + '@google-cloud/storage@7.19.0': + dependencies: + '@google-cloud/paginator': 5.0.2 + '@google-cloud/projectify': 4.0.0 + '@google-cloud/promisify': 4.0.0 + abort-controller: 3.0.0 + async-retry: 1.3.3 + duplexify: 4.1.3 + fast-xml-parser: 5.7.2 + gaxios: 6.7.1 + google-auth-library: 9.15.1 + html-entities: 2.6.0 + mime: 3.0.0 + p-limit: 3.1.0 + retry-request: 7.0.2 + teeny-request: 9.0.0 + uuid: 8.3.2 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@grpc/grpc-js@1.14.3': + dependencies: + '@grpc/proto-loader': 0.8.0 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.15': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.6 + yargs: 17.7.2 + optional: true + + '@grpc/proto-loader@0.8.0': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.3.2 + protobufjs: 7.5.6 + yargs: 17.7.2 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + optional: true + + '@js-sdsl/ordered-map@4.4.2': {} + + '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)': + dependencies: + jsep: 1.4.0 + + '@jsep-plugin/regex@1.0.4(jsep@1.4.0)': + dependencies: + jsep: 1.4.0 + + '@nodable/entities@2.1.0': + optional: true + + '@opentelemetry/api-logs@0.52.1': + dependencies: + '@opentelemetry/api': 1.9.1 + + '@opentelemetry/api@1.9.1': {} + + '@opentelemetry/auto-instrumentations-node@0.49.2(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-amqplib': 0.41.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-aws-lambda': 0.43.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-aws-sdk': 0.43.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-bunyan': 0.40.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-cassandra-driver': 0.40.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-connect': 0.38.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-cucumber': 0.8.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-dataloader': 0.11.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-dns': 0.38.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-express': 0.41.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-fastify': 0.38.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-fs': 0.14.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-generic-pool': 0.38.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-graphql': 0.42.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-grpc': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-hapi': 0.40.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-http': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-ioredis': 0.42.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-kafkajs': 0.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-knex': 0.39.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-koa': 0.42.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-lru-memoizer': 0.39.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-memcached': 0.38.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mongodb': 0.46.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mongoose': 0.41.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mysql': 0.40.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mysql2': 0.40.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-nestjs-core': 0.39.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-net': 0.38.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pg': 0.43.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pino': 0.41.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-redis': 0.41.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-redis-4': 0.41.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-restify': 0.40.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-router': 0.39.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-socket.io': 0.41.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-tedious': 0.13.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-undici': 0.5.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-winston': 0.39.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-alibaba-cloud': 0.29.7(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-aws': 1.12.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-azure': 0.2.12(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-container': 0.4.4(@opentelemetry/api@1.9.1) + '@opentelemetry/resource-detector-gcp': 0.29.13(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@opentelemetry/context-async-hooks@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + + '@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.28.0 + optional: true + + '@opentelemetry/exporter-trace-otlp-grpc@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@grpc/grpc-js': 1.14.3 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-grpc-exporter-base': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-trace-otlp-http@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-trace-otlp-proto@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/exporter-zipkin@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/instrumentation-amqplib@0.41.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-aws-lambda@0.43.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-aws-xray': 1.26.2(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@types/aws-lambda': 8.10.122 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-aws-sdk@0.43.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/propagation-utils': 0.30.16(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-bunyan@0.40.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@types/bunyan': 1.8.9 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-cassandra-driver@0.40.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-connect@0.38.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@types/connect': 3.4.36 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-cucumber@0.8.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-dataloader@0.11.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-dns@0.38.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-express@0.41.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-fastify@0.38.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-fs@0.14.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-generic-pool@0.38.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-graphql@0.42.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-grpc@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.25.1 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-hapi@0.40.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-http@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.25.1 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-ioredis@0.42.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-kafkajs@0.2.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-knex@0.39.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-koa@0.42.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-lru-memoizer@0.39.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-memcached@0.38.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@types/memcached': 2.2.10 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-mongodb@0.46.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-mongoose@0.41.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-mysql2@0.40.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-mysql@0.40.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@types/mysql': 2.15.22 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-nestjs-core@0.39.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-net@0.38.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-pg@0.43.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.1) + '@types/pg': 8.6.1 + '@types/pg-pool': 2.0.4 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-pino@0.41.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-redis-4@0.41.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-redis@0.41.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-restify@0.40.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-router@0.39.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-socket.io@0.41.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-tedious@0.13.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@types/tedious': 4.0.14 + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-undici@0.5.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation-winston@0.39.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + optional: true + + '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.15.0 + require-in-the-middle: 7.5.2 + semver: 7.7.4 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/otlp-grpc-exporter-base@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@grpc/grpc-js': 1.14.3 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.52.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/otlp-transformer@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + protobufjs: 7.5.6 + + '@opentelemetry/propagation-utils@0.30.16(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + optional: true + + '@opentelemetry/propagator-aws-xray@1.26.2(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + optional: true + + '@opentelemetry/propagator-b3@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/propagator-jaeger@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/redis-common@0.36.2': + optional: true + + '@opentelemetry/resource-detector-alibaba-cloud@0.29.7(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + optional: true + + '@opentelemetry/resource-detector-aws@1.12.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + optional: true + + '@opentelemetry/resource-detector-azure@0.2.12(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + optional: true + + '@opentelemetry/resource-detector-container@0.4.4(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + optional: true + + '@opentelemetry/resource-detector-gcp@0.29.13(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + gcp-metadata: 6.1.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + '@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/sdk-logs@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + + '@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + lodash.merge: 4.6.2 + + '@opentelemetry/sdk-node@0.52.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.52.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-grpc': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-http': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-trace-otlp-proto': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/exporter-zipkin': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.52.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-node': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.25.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/sdk-trace-node@1.25.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-b3': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/propagator-jaeger': 1.25.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.1) + semver: 7.7.4 + + '@opentelemetry/semantic-conventions@1.25.1': {} + + '@opentelemetry/semantic-conventions@1.28.0': + optional: true + + '@opentelemetry/semantic-conventions@1.40.0': + optional: true + + '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.1) + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.1 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.1': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.1': {} + + '@so-ric/colorspace@1.1.6': + dependencies: + color: 5.0.3 + text-hex: 1.0.0 + optional: true + + '@tootallnate/once@2.0.1': + optional: true + + '@types/aws-lambda@8.10.122': + optional: true + + '@types/bunyan@1.8.9': + dependencies: + '@types/node': 25.6.0 + optional: true + + '@types/caseless@0.12.5': + optional: true + + '@types/connect@3.4.36': + dependencies: + '@types/node': 25.6.0 + optional: true + + '@types/json-schema@7.0.15': {} + + '@types/jsonwebtoken@9.0.10': + dependencies: + '@types/ms': 2.1.0 + '@types/node': 25.6.0 + optional: true + + '@types/long@4.0.2': + optional: true + + '@types/memcached@2.2.10': + dependencies: + '@types/node': 25.6.0 + optional: true + + '@types/ms@2.1.0': + optional: true + + '@types/mysql@2.15.22': + dependencies: + '@types/node': 25.6.0 + optional: true + + '@types/node@20.19.39': + dependencies: + undici-types: 6.21.0 + + '@types/node@25.6.0': + dependencies: + undici-types: 7.19.2 + + '@types/pg-pool@2.0.4': + dependencies: + '@types/pg': 8.6.1 + optional: true + + '@types/pg@8.6.1': + dependencies: + '@types/node': 25.6.0 + pg-protocol: 1.13.0 + pg-types: 2.2.0 + optional: true + + '@types/request@2.48.13': + dependencies: + '@types/caseless': 0.12.5 + '@types/node': 25.6.0 + '@types/tough-cookie': 4.0.5 + form-data: 2.5.5 + optional: true + + '@types/shimmer@1.2.0': {} + + '@types/tedious@4.0.14': + dependencies: + '@types/node': 25.6.0 + optional: true + + '@types/tough-cookie@4.0.5': + optional: true + + '@types/triple-beam@1.3.5': + optional: true + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + optional: true + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-import-attributes@1.9.5(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + agent-base@7.1.4: {} + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.1 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: + optional: true + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: + optional: true + + array-flatten@1.1.1: {} + + arrify@2.0.1: + optional: true + + async-mutex@0.5.0: + dependencies: + tslib: 2.8.1 + + async-retry@1.3.3: + dependencies: + retry: 0.13.1 + optional: true + + async@3.2.6: + optional: true + + asynckit@0.4.0: + optional: true + + balanced-match@1.0.2: + optional: true + + base64-js@1.5.1: {} + + bignumber.js@9.3.1: {} + + body-parser@1.20.5: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.15.1 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@2.1.0: + dependencies: + balanced-match: 1.0.2 + optional: true + + buffer-equal-constant-time@1.0.1: {} + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + cjs-module-lexer@1.4.3: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-convert@3.1.3: + dependencies: + color-name: 2.1.0 + optional: true + + color-name@1.1.4: {} + + color-name@2.1.0: + optional: true + + color-string@2.1.4: + dependencies: + color-name: 2.1.0 + optional: true + + color@5.0.3: + dependencies: + color-convert: 3.1.3 + color-string: 2.1.4 + optional: true + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + optional: true + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.7: {} + + cookie@0.7.2: {} + + cors@2.8.6: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + optional: true + + data-uri-to-buffer@4.0.1: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + delayed-stream@1.0.0: + optional: true + + depd@2.0.0: {} + + destroy@1.2.0: {} + + dot-prop@6.0.1: + dependencies: + is-obj: 2.0.0 + optional: true + + dotprompt@1.1.2: + dependencies: + handlebars: 4.7.9 + yaml: 2.8.4 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexify@4.1.3: + dependencies: + end-of-stream: 1.4.5 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + optional: true + + eastasianwidth@0.2.0: + optional: true + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: + optional: true + + enabled@2.0.0: + optional: true + + encodeurl@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + optional: true + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.3 + optional: true + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: + optional: true + + eventid@2.0.1: + dependencies: + uuid: 8.3.2 + optional: true + + express@4.22.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.5 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.14.2 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + farmhash-modern@1.1.0: + optional: true + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.1: {} + + fast-xml-builder@1.1.7: + dependencies: + path-expression-matcher: 1.5.0 + optional: true + + fast-xml-parser@5.7.2: + dependencies: + '@nodable/entities': 2.1.0 + fast-xml-builder: 1.1.7 + path-expression-matcher: 1.5.0 + strnum: 2.2.3 + optional: true + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + optional: true + + fecha@4.2.3: + optional: true + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + firebase-admin@13.8.0: + dependencies: + '@fastify/busboy': 3.2.0 + '@firebase/database-compat': 2.1.3 + '@firebase/database-types': 1.0.19 + farmhash-modern: 1.1.0 + fast-deep-equal: 3.1.3 + google-auth-library: 10.6.2 + jsonwebtoken: 9.0.3 + jwks-rsa: 3.2.2 + node-forge: 1.4.0 + uuid: 11.1.1 + optionalDependencies: + '@google-cloud/firestore': 7.11.6 + '@google-cloud/storage': 7.19.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + fn.name@1.1.0: + optional: true + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + optional: true + + form-data@2.5.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.3 + mime-types: 2.1.35 + safe-buffer: 5.2.1 + optional: true + + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + function-bind@1.1.2: {} + + functional-red-black-tree@1.0.1: + optional: true + + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gaxios@7.1.4: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + optional: true + + gcp-metadata@6.1.1: + dependencies: + gaxios: 6.7.1 + google-logging-utils: 0.0.2 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.1.4 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + optional: true + + genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0): + dependencies: + '@genkit-ai/ai': 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)) + '@genkit-ai/core': 1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)(genkit@1.33.0(@google-cloud/firestore@7.11.6)(firebase-admin@13.8.0)) + uuid: 10.0.0 + transitivePeerDependencies: + - '@google-cloud/firestore' + - bufferutil + - encoding + - firebase + - firebase-admin + - supports-color + - utf-8-validate + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.3 + math-intrinsics: 1.1.0 + + get-port@5.1.1: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + optional: true + + google-auth-library@10.6.2: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.4 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + optional: true + + google-auth-library@9.15.1: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.1 + gtoken: 7.1.0 + jws: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + google-gax@4.6.1: + dependencies: + '@grpc/grpc-js': 1.14.3 + '@grpc/proto-loader': 0.7.15 + '@types/long': 4.0.2 + abort-controller: 3.0.0 + duplexify: 4.1.3 + google-auth-library: 9.15.1 + node-fetch: 2.7.0 + object-hash: 3.0.0 + proto3-json-serializer: 2.0.2 + protobufjs: 7.5.6 + retry-request: 7.0.2 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + google-gax@5.0.6: + dependencies: + '@grpc/grpc-js': 1.14.3 + '@grpc/proto-loader': 0.8.0 + duplexify: 4.1.3 + google-auth-library: 10.6.2 + google-logging-utils: 1.1.3 + node-fetch: 3.3.2 + object-hash: 3.0.0 + proto3-json-serializer: 3.0.4 + protobufjs: 7.5.6 + retry-request: 8.0.2 + rimraf: 5.0.10 + transitivePeerDependencies: + - supports-color + optional: true + + google-logging-utils@0.0.2: {} + + google-logging-utils@1.1.3: + optional: true + + googleapis-common@7.2.0: + dependencies: + extend: 3.0.2 + gaxios: 6.7.1 + google-auth-library: 9.15.1 + qs: 6.15.1 + url-template: 2.0.8 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + googleapis@137.1.0: + dependencies: + google-auth-library: 9.15.1 + googleapis-common: 7.2.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + gopd@1.2.0: {} + + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + handlebars@4.7.9: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + optional: true + + hasown@2.0.3: + dependencies: + function-bind: 1.1.2 + + html-entities@2.6.0: + optional: true + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: + optional: true + + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.1 + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + import-in-the-middle@1.15.0: + dependencies: + acorn: 8.16.0 + acorn-import-attributes: 1.9.5(acorn@8.16.0) + cjs-module-lexer: 1.4.3 + module-details-from-path: 1.0.4 + + inherits@2.0.4: {} + + ipaddr.js@1.9.1: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.3 + + is-fullwidth-code-point@3.0.0: {} + + is-obj@2.0.0: + optional: true + + is-stream@2.0.1: {} + + isexe@2.0.0: + optional: true + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + optional: true + + jose@4.15.9: + optional: true + + jsep@1.4.0: {} + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + + json-schema-traverse@1.0.0: {} + + json-schema@0.4.0: {} + + json5@2.2.3: {} + + jsonpath-plus@10.4.0: + dependencies: + '@jsep-plugin/assignment': 1.3.0(jsep@1.4.0) + '@jsep-plugin/regex': 1.0.4(jsep@1.4.0) + jsep: 1.4.0 + + jsonwebtoken@9.0.3: + dependencies: + jws: 4.0.1 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.7.4 + optional: true + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jwks-rsa@3.2.2: + dependencies: + '@types/jsonwebtoken': 9.0.10 + debug: 4.4.3 + jose: 4.15.9 + limiter: 1.1.5 + lru-memoizer: 2.3.0 + transitivePeerDependencies: + - supports-color + optional: true + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + kuler@2.0.0: + optional: true + + limiter@1.1.5: + optional: true + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: + optional: true + + lodash.includes@4.3.0: + optional: true + + lodash.isboolean@3.0.3: + optional: true + + lodash.isinteger@4.0.4: + optional: true + + lodash.isnumber@3.0.3: + optional: true + + lodash.isplainobject@4.0.6: + optional: true + + lodash.isstring@4.0.1: + optional: true + + lodash.mapvalues@4.6.0: + optional: true + + lodash.merge@4.6.2: {} + + lodash.once@4.1.1: + optional: true + + logform@2.7.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + optional: true + + long@5.3.2: {} + + lru-cache@10.4.3: + optional: true + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + optional: true + + lru-memoizer@2.3.0: + dependencies: + lodash.clonedeep: 4.5.0 + lru-cache: 6.0.0 + optional: true + + math-intrinsics@1.1.0: {} + + media-typer@0.3.0: {} + + merge-descriptors@1.0.3: {} + + methods@1.1.2: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mime@3.0.0: + optional: true + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.0 + optional: true + + minimist@1.2.8: {} + + minipass@7.1.3: + optional: true + + module-details-from-path@1.0.4: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + negotiator@0.6.3: {} + + neo-async@2.6.2: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + + node-forge@1.4.0: + optional: true + + object-assign@4.1.1: {} + + object-hash@3.0.0: + optional: true + + object-inspect@1.13.4: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + optional: true + + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + optional: true + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + optional: true + + package-json-from-dist@1.0.1: + optional: true + + parseurl@1.3.3: {} + + partial-json@0.1.7: {} + + path-expression-matcher@1.5.0: + optional: true + + path-key@3.1.1: + optional: true + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + optional: true + + path-to-regexp@0.1.13: {} + + pg-int8@1.0.1: + optional: true + + pg-protocol@1.13.0: + optional: true + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.1 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + optional: true + + postgres-array@2.0.0: + optional: true + + postgres-bytea@1.0.1: + optional: true + + postgres-date@1.0.7: + optional: true + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + optional: true + + proto3-json-serializer@2.0.2: + dependencies: + protobufjs: 7.5.6 + optional: true + + proto3-json-serializer@3.0.4: + dependencies: + protobufjs: 7.5.6 + optional: true + + protobufjs@7.5.6: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.1 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 25.6.0 + long: 5.3.2 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + optional: true + + pumpify@2.0.1: + dependencies: + duplexify: 4.1.3 + inherits: 2.0.4 + pump: 3.0.4 + optional: true + + qs@6.14.2: + dependencies: + side-channel: 1.1.0 + + qs@6.15.1: + dependencies: + side-channel: 1.1.0 + + range-parser@1.2.1: {} + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + optional: true + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-in-the-middle@7.5.2: + dependencies: + debug: 4.4.3 + module-details-from-path: 1.0.4 + resolve: 1.22.12 + transitivePeerDependencies: + - supports-color + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry-request@7.0.2: + dependencies: + '@types/request': 2.48.13 + extend: 3.0.2 + teeny-request: 9.0.0 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + retry-request@8.0.2: + dependencies: + extend: 3.0.2 + teeny-request: 10.1.2 + transitivePeerDependencies: + - supports-color + optional: true + + retry@0.13.1: + optional: true + + rimraf@5.0.10: + dependencies: + glob: 10.5.0 + optional: true + + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.5.0: + optional: true + + safer-buffer@2.1.2: {} + + semver@7.7.4: {} + + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + optional: true + + shebang-regex@3.0.0: + optional: true + + shimmer@1.2.1: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@4.1.0: + optional: true + + source-map@0.6.1: {} + + stack-trace@0.0.10: + optional: true + + statuses@2.0.2: {} + + stream-events@1.0.5: + dependencies: + stubs: 3.0.0 + optional: true + + stream-shift@1.0.3: + optional: true + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + optional: true + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + optional: true + + strnum@2.2.3: + optional: true + + stubs@3.0.0: + optional: true + + supports-preserve-symlinks-flag@1.0.0: {} + + teeny-request@10.1.2: + dependencies: + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + stream-events: 1.0.5 + transitivePeerDependencies: + - supports-color + optional: true + + teeny-request@9.0.0: + dependencies: + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + stream-events: 1.0.5 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + optional: true + + text-hex@1.0.0: + optional: true + + toidentifier@1.0.1: {} + + tr46@0.0.3: {} + + triple-beam@1.4.1: + optional: true + + tslib@2.8.1: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + uglify-js@3.19.3: + optional: true + + undici-types@6.21.0: {} + + undici-types@7.19.2: {} + + unpipe@1.0.0: {} + + uri-templates@0.2.0: {} + + url-template@2.0.8: + optional: true + + util-deprecate@1.0.2: + optional: true + + utils-merge@1.0.1: {} + + uuid@10.0.0: {} + + uuid@11.1.1: + optional: true + + uuid@8.3.2: + optional: true + + uuid@9.0.1: {} + + vary@1.1.2: {} + + web-streams-polyfill@3.3.3: {} + + webidl-conversions@3.0.1: {} + + websocket-driver@0.7.4: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + optional: true + + websocket-extensions@0.1.4: + optional: true + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + optional: true + + winston-transport@4.9.0: + dependencies: + logform: 2.7.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + optional: true + + winston@3.19.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.8 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.7.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.9.0 + optional: true + + wordwrap@1.0.0: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + optional: true + + wrappy@1.0.2: + optional: true + + ws@8.20.0: {} + + xtend@4.0.2: + optional: true + + y18n@5.0.8: {} + + yallist@4.0.0: + optional: true + + yaml@2.8.4: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: + optional: true + + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} diff --git a/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs b/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs new file mode 100644 index 000000000..f457d2b2c --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs @@ -0,0 +1,231 @@ +import { wrapGenkit } from "braintrust"; +import { + collectAsync, + runOperation, + runTracedScenario, +} from "../../helpers/provider-runtime.mjs"; +import { ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; + +export const GENKIT_SCENARIO_TIMEOUT_MS = 90_000; + +const GOOGLE_MODEL_NAME = "gemini-2.5-flash-lite"; +const GOOGLE_EMBEDDING_MODEL_NAME = "gemini-embedding-001"; +const GOOGLE_GENAI_RETRY_OPTIONS = { + attempts: 4, + delayMs: 1_000, + maxDelayMs: 8_000, + shouldRetry: isRetriableGoogleGenAIError, +}; + +function isObject(value) { + return value !== null && typeof value === "object" && !Array.isArray(value); +} + +function getRetryStatus(error) { + if (!isObject(error)) { + return undefined; + } + + const directStatus = error.status; + if (typeof directStatus === "number") { + return directStatus; + } + + const nestedError = error.error; + if ( + isObject(nestedError) && + typeof nestedError.code === "number" && + Number.isFinite(nestedError.code) + ) { + return nestedError.code; + } + + return undefined; +} + +function isRetriableGoogleGenAIError(error) { + const status = getRetryStatus(error); + if ( + status === 408 || + status === 429 || + status === 500 || + status === 502 || + status === 503 || + status === 504 + ) { + return true; + } + + const message = error instanceof Error ? error.message : String(error ?? ""); + const normalizedMessage = message.toLowerCase(); + return ( + normalizedMessage.includes("request timed out") || + normalizedMessage.includes("timed out") || + normalizedMessage.includes("unavailable") || + normalizedMessage.includes("high demand") + ); +} + +async function withRetry( + callback, + { + attempts = 3, + delayMs = 1_000, + maxDelayMs = Number.POSITIVE_INFINITY, + shouldRetry = () => true, + } = {}, +) { + let lastError; + for (let attempt = 1; attempt <= attempts; attempt++) { + try { + return await callback(); + } catch (error) { + lastError = error; + if (attempt === attempts || !shouldRetry(error)) { + throw error; + } + const retryDelayMs = Math.min(delayMs * attempt, maxDelayMs); + await new Promise((resolve) => setTimeout(resolve, retryDelayMs)); + } + } + + throw lastError; +} + +async function buildAI(options = {}) { + const { genkit, z } = await import("genkit"); + const { googleAI } = await import("@genkit-ai/google-genai"); + const baseAI = genkit({ + plugins: [googleAI()], + model: googleAI.model(GOOGLE_MODEL_NAME), + promptDir: null, + }); + const ai = options.wrap ? wrapGenkit(baseAI) : baseAI; + + return { + ai, + embedder: googleAI.embedder(GOOGLE_EMBEDDING_MODEL_NAME), + model: googleAI.model(GOOGLE_MODEL_NAME), + z, + }; +} + +export async function runGenkitInstrumentationScenario(options = {}) { + const { ai, embedder, model, z } = await buildAI(options); + + const summarizeTool = ai.defineTool( + { + name: "summarizeCity", + description: "Summarizes a city.", + inputSchema: z.object({ + city: z.string(), + }), + outputSchema: z.object({ + summary: z.string(), + }), + }, + async ({ city }) => ({ + summary: `${city} has precise instrumentation weather.`, + }), + ); + + const recipeFlow = ai.defineFlow( + { + name: "recipeFlow", + inputSchema: z.string(), + outputSchema: z.object({ + recipe: z.string(), + }), + }, + async (topic) => { + const normalized = await ai.run("normalize-topic", topic, async (input) => + String(input).trim().toLowerCase(), + ); + const response = await withRetry( + () => + ai.generate({ + model, + prompt: `Write a recipe about ${normalized}.`, + config: { + temperature: 0, + maxOutputTokens: 32, + }, + }), + GOOGLE_GENAI_RETRY_OPTIONS, + ); + return { + recipe: response.text, + }; + }, + ); + + await runTracedScenario({ + callback: async () => { + await runOperation("genkit-generate-operation", "generate", async () => { + await withRetry( + () => + ai.generate({ + model, + prompt: "Reply with exactly OK.", + config: { + temperature: 0, + maxOutputTokens: 24, + }, + }), + GOOGLE_GENAI_RETRY_OPTIONS, + ); + }); + + await runOperation("genkit-stream-operation", "stream", async () => { + await withRetry(async () => { + const { response, stream } = ai.generateStream({ + model, + prompt: "Stream a short phrase.", + config: { + temperature: 0, + maxOutputTokens: 32, + }, + }); + await collectAsync(stream); + await response; + }, GOOGLE_GENAI_RETRY_OPTIONS); + }); + + await runOperation("genkit-embed-operation", "embed", async () => { + await withRetry( + () => + ai.embed({ + embedder, + content: "embed this", + }), + GOOGLE_GENAI_RETRY_OPTIONS, + ); + }); + + await runOperation("genkit-tool-operation", "tool", async () => { + await summarizeTool.run({ + city: "Vienna", + }); + }); + + await runOperation("genkit-flow-operation", "flow", async () => { + await recipeFlow("Cake"); + }); + }, + flushCount: 2, + flushDelayMs: 20, + metadata: { + scenario: SCENARIO_NAME, + }, + projectNameBase: "e2e-genkit-instrumentation", + rootName: ROOT_NAME, + }); +} + +export async function runWrappedGenkitInstrumentation() { + await runGenkitInstrumentationScenario({ wrap: true }); +} + +export async function runAutoGenkitInstrumentation() { + await runGenkitInstrumentationScenario(); +} diff --git a/e2e/scenarios/genkit-instrumentation/scenario.mjs b/e2e/scenarios/genkit-instrumentation/scenario.mjs new file mode 100644 index 000000000..0b4fb92b8 --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/scenario.mjs @@ -0,0 +1,4 @@ +import { runMain } from "../../helpers/provider-runtime.mjs"; +import { runAutoGenkitInstrumentation } from "./scenario.impl.mjs"; + +runMain(async () => runAutoGenkitInstrumentation()); diff --git a/e2e/scenarios/genkit-instrumentation/scenario.test.ts b/e2e/scenarios/genkit-instrumentation/scenario.test.ts new file mode 100644 index 000000000..0541ade14 --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/scenario.test.ts @@ -0,0 +1,50 @@ +import { describe } from "vitest"; +import { + prepareScenarioDir, + readInstalledPackageVersion, + resolveScenarioDir, +} from "../../helpers/scenario-harness"; +import { defineGenkitInstrumentationAssertions } from "./assertions"; +import { GENKIT_SCENARIO_TIMEOUT_MS } from "./scenario.impl.mjs"; + +const scenarioDir = await prepareScenarioDir({ + scenarioDir: resolveScenarioDir(import.meta.url), +}); + +const genkitVersion = await readInstalledPackageVersion(scenarioDir, "genkit"); +const snapshotName = `genkit-v${genkitVersion.replace(/\./g, "-")}`; + +describe(`genkit ${genkitVersion}`, () => { + defineGenkitInstrumentationAssertions({ + name: "wrapped instrumentation", + runScenario: async ({ runScenarioDir }) => { + await runScenarioDir({ + entry: "scenario.ts", + runContext: { variantKey: snapshotName }, + scenarioDir, + timeoutMs: GENKIT_SCENARIO_TIMEOUT_MS, + }); + }, + snapshotName: `${snapshotName}-wrapped`, + supportsActionSpans: true, + testFileUrl: import.meta.url, + timeoutMs: GENKIT_SCENARIO_TIMEOUT_MS, + }); + + defineGenkitInstrumentationAssertions({ + name: "auto-hook instrumentation", + runScenario: async ({ runNodeScenarioDir }) => { + await runNodeScenarioDir({ + entry: "scenario.mjs", + nodeArgs: ["--import", "braintrust/hook.mjs"], + runContext: { variantKey: snapshotName }, + scenarioDir, + timeoutMs: GENKIT_SCENARIO_TIMEOUT_MS, + }); + }, + snapshotName: `${snapshotName}-auto`, + supportsActionSpans: false, + testFileUrl: import.meta.url, + timeoutMs: GENKIT_SCENARIO_TIMEOUT_MS, + }); +}); diff --git a/e2e/scenarios/genkit-instrumentation/scenario.ts b/e2e/scenarios/genkit-instrumentation/scenario.ts new file mode 100644 index 000000000..0f471311b --- /dev/null +++ b/e2e/scenarios/genkit-instrumentation/scenario.ts @@ -0,0 +1,4 @@ +import { runMain } from "../../helpers/provider-runtime.mjs"; +import { runWrappedGenkitInstrumentation } from "./scenario.impl.mjs"; + +runMain(async () => runWrappedGenkitInstrumentation()); diff --git a/js/src/auto-instrumentations/bundler/plugin.ts b/js/src/auto-instrumentations/bundler/plugin.ts index 2462c5faf..caeb2c7ef 100644 --- a/js/src/auto-instrumentations/bundler/plugin.ts +++ b/js/src/auto-instrumentations/bundler/plugin.ts @@ -32,6 +32,7 @@ import { openRouterConfigs } from "../configs/openrouter"; import { mistralConfigs } from "../configs/mistral"; import { cohereConfigs } from "../configs/cohere"; import { groqConfigs } from "../configs/groq"; +import { genkitConfigs } from "../configs/genkit"; export interface BundlerPluginOptions { /** @@ -85,6 +86,7 @@ export const unplugin = createUnplugin((options = {}) => { ...mistralConfigs, ...cohereConfigs, ...groqConfigs, + ...genkitConfigs, ...(options.instrumentations || []), ]; diff --git a/js/src/auto-instrumentations/bundler/webpack-loader.ts b/js/src/auto-instrumentations/bundler/webpack-loader.ts index 966c659aa..8d18d5b83 100644 --- a/js/src/auto-instrumentations/bundler/webpack-loader.ts +++ b/js/src/auto-instrumentations/bundler/webpack-loader.ts @@ -41,6 +41,7 @@ import { openRouterConfigs } from "../configs/openrouter"; import { mistralConfigs } from "../configs/mistral"; import { cohereConfigs } from "../configs/cohere"; import { groqConfigs } from "../configs/groq"; +import { genkitConfigs } from "../configs/genkit"; import { type BundlerPluginOptions } from "./plugin"; /** @@ -80,6 +81,7 @@ function getMatcher(options: BundlerPluginOptions): InstrumentationMatcher { ...mistralConfigs, ...cohereConfigs, ...groqConfigs, + ...genkitConfigs, ...(options.instrumentations ?? []), ]; const dcModule = options.browser ? "dc-browser" : undefined; diff --git a/js/src/auto-instrumentations/configs/genkit.ts b/js/src/auto-instrumentations/configs/genkit.ts new file mode 100644 index 000000000..7438f8379 --- /dev/null +++ b/js/src/auto-instrumentations/configs/genkit.ts @@ -0,0 +1,144 @@ +import type { InstrumentationConfig } from "@apm-js-collab/code-transformer"; +import { genkitChannels } from "../../instrumentation/plugins/genkit-channels"; + +const genkitVersionRange = ">=1.0.0 <2.0.0"; + +/** + * Instrumentation configurations for Genkit's JavaScript SDK. + * + * Genkit's public instance methods live on the GenkitAI base class in + * @genkit-ai/ai. The top-level `genkit` package subclasses that class, so + * targeting these methods instruments regular `genkit({ ... })` instances. + */ +export const genkitConfigs: InstrumentationConfig[] = [ + { + channelName: genkitChannels.generate.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.mjs", + }, + functionQuery: { + className: "GenkitAI", + methodName: "generate", + kind: "Async", + }, + }, + { + channelName: genkitChannels.generate.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.js", + }, + functionQuery: { + className: "GenkitAI", + methodName: "generate", + kind: "Async", + }, + }, + { + channelName: genkitChannels.generateStream.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.mjs", + }, + functionQuery: { + className: "GenkitAI", + methodName: "generateStream", + kind: "Sync", + }, + }, + { + channelName: genkitChannels.generateStream.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.js", + }, + functionQuery: { + className: "GenkitAI", + methodName: "generateStream", + kind: "Sync", + }, + }, + { + channelName: genkitChannels.embed.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.mjs", + }, + functionQuery: { + className: "GenkitAI", + methodName: "embed", + kind: "Async", + }, + }, + { + channelName: genkitChannels.embed.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.js", + }, + functionQuery: { + className: "GenkitAI", + methodName: "embed", + kind: "Async", + }, + }, + { + channelName: genkitChannels.embedMany.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.mjs", + }, + functionQuery: { + className: "GenkitAI", + methodName: "embedMany", + kind: "Async", + }, + }, + { + channelName: genkitChannels.embedMany.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.js", + }, + functionQuery: { + className: "GenkitAI", + methodName: "embedMany", + kind: "Async", + }, + }, + { + channelName: genkitChannels.actionRun.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.mjs", + }, + functionQuery: { + className: "GenkitAI", + methodName: "run", + kind: "Async", + }, + }, + { + channelName: genkitChannels.actionRun.channelName, + module: { + name: "@genkit-ai/ai", + versionRange: genkitVersionRange, + filePath: "lib/genkit-ai.js", + }, + functionQuery: { + className: "GenkitAI", + methodName: "run", + kind: "Async", + }, + }, +]; diff --git a/js/src/auto-instrumentations/hook.mts b/js/src/auto-instrumentations/hook.mts index 46fe0f0d2..a68622351 100644 --- a/js/src/auto-instrumentations/hook.mts +++ b/js/src/auto-instrumentations/hook.mts @@ -27,6 +27,7 @@ import { mistralConfigs } from "./configs/mistral.js"; import { googleADKConfigs } from "./configs/google-adk.js"; import { cohereConfigs } from "./configs/cohere.js"; import { groqConfigs } from "./configs/groq.js"; +import { genkitConfigs } from "./configs/genkit.js"; import { ModulePatch } from "./loader/cjs-patch.js"; import { patchTracingChannel } from "./patch-tracing-channel.js"; @@ -88,6 +89,9 @@ const allConfigs = [ : googleADKConfigs), ...(isDisabled(disabledIntegrations, "cohere") ? [] : cohereConfigs), ...(isDisabled(disabledIntegrations, "groq", "groq-sdk") ? [] : groqConfigs), + ...(isDisabled(disabledIntegrations, "genkit", "firebase-genkit") + ? [] + : genkitConfigs), ]; // 1. Register ESM loader for ESM modules diff --git a/js/src/auto-instrumentations/index.ts b/js/src/auto-instrumentations/index.ts index bdac954ab..df9579620 100644 --- a/js/src/auto-instrumentations/index.ts +++ b/js/src/auto-instrumentations/index.ts @@ -41,6 +41,7 @@ export { mistralConfigs } from "./configs/mistral"; export { googleADKConfigs } from "./configs/google-adk"; export { cohereConfigs } from "./configs/cohere"; export { groqConfigs } from "./configs/groq"; +export { genkitConfigs } from "./configs/genkit"; // Re-export orchestrion configuration types // Note: ModuleMetadata and FunctionQuery are properties of InstrumentationConfig, diff --git a/js/src/exports.ts b/js/src/exports.ts index 02dadbf66..b3dc057f5 100644 --- a/js/src/exports.ts +++ b/js/src/exports.ts @@ -180,6 +180,7 @@ export { wrapClaudeAgentSDK } from "./wrappers/claude-agent-sdk/claude-agent-sdk export { wrapCursorSDK } from "./wrappers/cursor-sdk"; export { wrapGoogleGenAI } from "./wrappers/google-genai"; export { wrapGoogleADK } from "./wrappers/google-adk"; +export { wrapGenkit } from "./wrappers/genkit"; export { wrapHuggingFace } from "./wrappers/huggingface"; export { wrapOpenRouterAgent } from "./wrappers/openrouter-agent"; export { wrapOpenRouter } from "./wrappers/openrouter"; diff --git a/js/src/instrumentation/braintrust-plugin.ts b/js/src/instrumentation/braintrust-plugin.ts index 5db01b441..b9a4ad158 100644 --- a/js/src/instrumentation/braintrust-plugin.ts +++ b/js/src/instrumentation/braintrust-plugin.ts @@ -12,6 +12,7 @@ import { MistralPlugin } from "./plugins/mistral-plugin"; import { GoogleADKPlugin } from "./plugins/google-adk-plugin"; import { CoherePlugin } from "./plugins/cohere-plugin"; import { GroqPlugin } from "./plugins/groq-plugin"; +import { GenkitPlugin } from "./plugins/genkit-plugin"; export interface BraintrustPluginConfig { integrations?: { @@ -31,6 +32,7 @@ export interface BraintrustPluginConfig { googleADK?: boolean; cohere?: boolean; groq?: boolean; + genkit?: boolean; }; } @@ -65,6 +67,7 @@ export class BraintrustPlugin extends BasePlugin { private googleADKPlugin: GoogleADKPlugin | null = null; private coherePlugin: CoherePlugin | null = null; private groqPlugin: GroqPlugin | null = null; + private genkitPlugin: GenkitPlugin | null = null; constructor(config: BraintrustPluginConfig = {}) { super(); @@ -146,6 +149,11 @@ export class BraintrustPlugin extends BasePlugin { this.groqPlugin = new GroqPlugin(); this.groqPlugin.enable(); } + + if (integrations.genkit !== false) { + this.genkitPlugin = new GenkitPlugin(); + this.genkitPlugin.enable(); + } } protected onDisable(): void { @@ -213,6 +221,11 @@ export class BraintrustPlugin extends BasePlugin { this.groqPlugin.disable(); this.groqPlugin = null; } + + if (this.genkitPlugin) { + this.genkitPlugin.disable(); + this.genkitPlugin = null; + } } } diff --git a/js/src/instrumentation/plugins/genkit-channels.ts b/js/src/instrumentation/plugins/genkit-channels.ts new file mode 100644 index 000000000..a3e863a88 --- /dev/null +++ b/js/src/instrumentation/plugins/genkit-channels.ts @@ -0,0 +1,53 @@ +import { channel, defineChannels } from "../core/channel-definitions"; +import type { + GenkitAction, + GenkitEmbedManyParams, + GenkitEmbedParams, + GenkitEmbedding, + GenkitGenerateInput, + GenkitGenerateResponse, + GenkitGenerateResponseChunk, + GenkitGenerateStreamResponse, +} from "../../vendor-sdk-types/genkit"; + +export const genkitChannels = defineChannels("@genkit-ai/ai", { + generate: channel<[GenkitGenerateInput], GenkitGenerateResponse>({ + channelName: "generate", + kind: "async", + }), + + generateStream: channel< + [GenkitGenerateInput], + GenkitGenerateStreamResponse, + Record, + GenkitGenerateResponseChunk + >({ + channelName: "generateStream", + kind: "sync-stream", + }), + + embed: channel<[GenkitEmbedParams], GenkitEmbedding[]>({ + channelName: "embed", + kind: "async", + }), + + embedMany: channel<[GenkitEmbedManyParams], unknown>({ + channelName: "embedMany", + kind: "async", + }), + + actionRun: channel<[unknown, unknown?], unknown>({ + channelName: "action.run", + kind: "async", + }), + + actionStream: channel< + [unknown, unknown?], + ReturnType>, + Record, + unknown + >({ + channelName: "action.stream", + kind: "sync-stream", + }), +}); diff --git a/js/src/instrumentation/plugins/genkit-plugin.ts b/js/src/instrumentation/plugins/genkit-plugin.ts new file mode 100644 index 000000000..d18d31a14 --- /dev/null +++ b/js/src/instrumentation/plugins/genkit-plugin.ts @@ -0,0 +1,516 @@ +import { BasePlugin } from "../core"; +import { + traceAsyncChannel, + traceSyncStreamChannel, + unsubscribeAll, +} from "../core/channel-tracing"; +import type { ChannelMessage } from "../core/channel-definitions"; +import type { IsoChannelHandlers, IsoTracingChannel } from "../../isomorph"; +import { startSpan } from "../../logger"; +import type { Span } from "../../logger"; +import { getCurrentUnixTimestamp, isObject } from "../../util"; +import { SpanTypeAttribute } from "../../../util/index"; +import { processInputAttachments } from "../../wrappers/attachment-utils"; +import { genkitChannels } from "./genkit-channels"; +import type { + GenkitAction, + GenkitActionMetadata, + GenkitEmbedManyParams, + GenkitEmbedParams, + GenkitGenerateInput, + GenkitGenerateResponse, + GenkitGenerateResponseChunk, + GenkitGenerateStreamResponse, + GenkitUsage, +} from "../../vendor-sdk-types/genkit"; + +type SpanState = { + span: Span; + startTime: number; +}; + +export class GenkitPlugin extends BasePlugin { + protected onEnable(): void { + this.subscribeToGenkitChannels(); + } + + protected onDisable(): void { + this.unsubscribers = unsubscribeAll(this.unsubscribers); + } + + private subscribeToGenkitChannels(): void { + this.unsubscribers.push( + traceAsyncChannel(genkitChannels.generate, { + name: "genkit.generate", + type: SpanTypeAttribute.FUNCTION, + extractInput: ([input]) => extractGenerateInput(input), + extractOutput: extractGenerateOutput, + extractMetadata: (result, event) => + extractGenerateResponseMetadata(result, event?.arguments?.[0]), + extractMetrics: (result) => parseGenkitUsageMetrics(result?.usage), + }), + ); + + this.unsubscribers.push( + traceSyncStreamChannel(genkitChannels.generateStream, { + name: "genkit.generateStream", + type: SpanTypeAttribute.FUNCTION, + extractInput: ([input]) => extractGenerateInput(input), + patchResult: ({ result, span, startTime }) => + patchGenerateStreamResult(result, span, startTime), + }), + ); + + this.unsubscribers.push( + traceAsyncChannel(genkitChannels.embed, { + name: "genkit.embed", + type: SpanTypeAttribute.FUNCTION, + extractInput: ([params]) => extractEmbedInput(params), + extractOutput: (result) => summarizeEmbeddingResult(result), + extractMetadata: (_result, event) => + extractEmbedMetadata(event?.arguments?.[0]), + extractMetrics: () => ({}), + }), + ); + + this.unsubscribers.push( + traceAsyncChannel(genkitChannels.embedMany, { + name: "genkit.embedMany", + type: SpanTypeAttribute.FUNCTION, + extractInput: ([params]) => extractEmbedManyInput(params), + extractOutput: summarizeEmbeddingResult, + extractMetadata: (_result, event) => + extractEmbedMetadata(event?.arguments?.[0]), + extractMetrics: () => ({}), + }), + ); + + this.subscribeToActionRun(); + this.subscribeToActionStream(); + } + + private subscribeToActionRun(): void { + const tracingChannel = + genkitChannels.actionRun.tracingChannel() as IsoTracingChannel< + ChannelMessage + >; + const states = new WeakMap(); + + const handlers: IsoChannelHandlers< + ChannelMessage + > = { + start: (event) => { + const metadata = extractActionMetadata(event.self); + const runStepName = + !metadata && typeof event.arguments[0] === "string" + ? event.arguments[0] + : undefined; + const span = startSpan({ + name: actionSpanName(metadata, runStepName), + spanAttributes: { + type: actionSpanType(metadata), + }, + }); + const startTime = getCurrentUnixTimestamp(); + + span.log({ + input: runStepName ? event.arguments[1] : event.arguments[0], + metadata: actionMetadataForLog(metadata, runStepName), + }); + states.set(event, { span, startTime }); + }, + asyncEnd: (event) => { + const state = states.get(event); + if (!state) { + return; + } + + try { + state.span.log({ + output: extractActionOutput(event.result), + metrics: durationMetrics(state.startTime), + }); + } finally { + state.span.end(); + states.delete(event); + } + }, + error: (event) => { + const state = states.get(event); + if (!state || !event.error) { + return; + } + state.span.log({ error: event.error.message }); + state.span.end(); + states.delete(event); + }, + }; + + tracingChannel.subscribe(handlers); + this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers)); + } + + private subscribeToActionStream(): void { + this.unsubscribers.push( + traceSyncStreamChannel(genkitChannels.actionStream, { + name: "genkit.action.stream", + type: SpanTypeAttribute.TASK, + extractInput: ([input], event) => ({ + input, + metadata: actionMetadataForLog(extractActionMetadata(event.self)), + }), + patchResult: ({ result, span, startTime }) => + patchActionStreamResult(result, span, startTime), + }), + ); + } +} + +function normalizeInput(input: GenkitGenerateInput): GenkitGenerateInput { + if (typeof input === "string" || Array.isArray(input)) { + return { prompt: input }; + } + return input; +} + +function extractGenerateInput(input: GenkitGenerateInput): { + input: unknown; + metadata: Record; +} { + const normalized = normalizeInput(input); + if (!isObject(normalized)) { + return { + input: undefined, + metadata: genkitProviderMetadata(), + }; + } + + const options = normalized as Record; + return { + input: processInputAttachments( + options.prompt ?? options.messages ?? options.system, + ), + metadata: { + ...genkitProviderMetadata(), + ...pickDefined({ + model: modelName(options.model), + temperature: configValue(options.config, "temperature"), + maxOutputTokens: configValue(options.config, "maxOutputTokens"), + max_output_tokens: configValue(options.config, "max_output_tokens"), + }), + }, + }; +} + +function extractGenerateOutput(result: GenkitGenerateResponse | undefined) { + if (!isObject(result)) { + return result; + } + + return pickDefined({ + text: safeGet(result, "text"), + output: safeGet(result, "output"), + message: safeGet(result, "message"), + finishReason: safeGet(result, "finishReason"), + finishMessage: safeGet(result, "finishMessage"), + }); +} + +function extractGenerateResponseMetadata( + result: GenkitGenerateResponse | undefined, + input: GenkitGenerateInput | undefined, +): Record { + const normalized = input ? normalizeInput(input) : undefined; + const request = isObject(result?.request) + ? (result?.request as Record) + : isObject(normalized) + ? (normalized as Record) + : undefined; + + return { + ...genkitProviderMetadata(), + ...pickDefined({ + model: modelName(result?.model ?? request?.model), + finishReason: result?.finishReason, + finishMessage: result?.finishMessage, + }), + }; +} + +function extractEmbedInput(params: GenkitEmbedParams | undefined): { + input: unknown; + metadata: Record; +} { + return { + input: processInputAttachments(params?.content), + metadata: extractEmbedMetadata(params), + }; +} + +function extractEmbedManyInput(params: GenkitEmbedManyParams | undefined): { + input: unknown; + metadata: Record; +} { + return { + input: processInputAttachments(params?.content), + metadata: extractEmbedMetadata(params), + }; +} + +function extractEmbedMetadata( + params: GenkitEmbedParams | GenkitEmbedManyParams | undefined, +): Record { + return { + ...genkitProviderMetadata(), + ...pickDefined({ + model: modelName(params?.embedder), + }), + }; +} + +function summarizeEmbeddingResult(result: unknown): unknown { + if (Array.isArray(result)) { + return { + embedding_count: result.length, + dimensions: + Array.isArray(result[0]) || Array.isArray(result[0]?.embedding) + ? (result[0] as number[]).length || result[0]?.embedding?.length + : undefined, + }; + } + + if (isObject(result) && Array.isArray(result.embeddings)) { + return { + embedding_count: result.embeddings.length, + dimensions: Array.isArray(result.embeddings[0]) + ? result.embeddings[0].length + : undefined, + }; + } + + return result; +} + +function patchGenerateStreamResult( + result: GenkitGenerateStreamResponse, + span: Span, + startTime: number, +): boolean { + if (!isObject(result) || !isAsyncIterableLike(result.stream)) { + return false; + } + + let firstChunkTime: number | undefined; + const chunks: GenkitGenerateResponseChunk[] = []; + + void (async () => { + try { + for await (const chunk of result.stream) { + if (firstChunkTime === undefined) { + firstChunkTime = getCurrentUnixTimestamp(); + } + chunks.push(chunk); + } + + const response = await result.response; + const metrics = parseGenkitUsageMetrics(response?.usage); + if (firstChunkTime !== undefined) { + metrics.time_to_first_token = firstChunkTime - startTime; + } + + span.log({ + output: { + ...extractGenerateOutput(response), + streamedText: chunks.map((chunk) => safeGet(chunk, "text")).join(""), + }, + metadata: extractGenerateResponseMetadata(response, undefined), + metrics, + }); + } catch (error) { + span.log({ error: errorMessage(error) }); + } finally { + span.end(); + } + })(); + + return true; +} + +function patchActionStreamResult( + result: ReturnType>, + span: Span, + startTime: number, +): boolean { + if (!isObject(result) || !isAsyncIterableLike(result.stream)) { + return false; + } + + void (async () => { + const chunks: unknown[] = []; + try { + for await (const chunk of result.stream) { + chunks.push(chunk); + } + span.log({ + output: { + chunks, + result: await result.output, + }, + metrics: durationMetrics(startTime), + }); + } catch (error) { + span.log({ error: errorMessage(error) }); + } finally { + span.end(); + } + })(); + + return true; +} + +function parseGenkitUsageMetrics( + usage: GenkitUsage | undefined, +): Record { + if (!isObject(usage)) { + return {}; + } + + return pickNumberMetrics({ + tokens: usage.totalTokens, + prompt_tokens: usage.inputTokens, + completion_tokens: usage.outputTokens, + cached_tokens: usage.cachedContentTokens, + reasoning_tokens: usage.thoughtsTokens, + }); +} + +function durationMetrics(startTime: number): Record { + const end = getCurrentUnixTimestamp(); + return { + start: startTime, + end, + duration: end - startTime, + }; +} + +function extractActionMetadata( + self: unknown, +): GenkitActionMetadata | undefined { + if (!isObject(self) || !isObject(self.__action)) { + return undefined; + } + return self.__action as GenkitActionMetadata; +} + +function actionSpanName( + metadata: GenkitActionMetadata | undefined, + runStepName?: string, +): string { + const actionType = metadata?.actionType; + const name = metadata?.name; + if (actionType && name) { + return `genkit.${actionType}: ${name}`; + } + if (name) { + return `genkit.action: ${name}`; + } + if (runStepName) { + return `genkit.run: ${runStepName}`; + } + return "genkit.action"; +} + +function actionSpanType(metadata: GenkitActionMetadata | undefined): string { + switch (metadata?.actionType) { + case "tool": + case "tool.v2": + return SpanTypeAttribute.TOOL; + case "model": + case "embedder": + return SpanTypeAttribute.LLM; + default: + return SpanTypeAttribute.TASK; + } +} + +function actionMetadataForLog( + metadata: GenkitActionMetadata | undefined, + runStepName?: string, +): Record { + return { + ...genkitProviderMetadata(), + ...pickDefined({ + "genkit.action_type": metadata?.actionType, + "genkit.action_name": metadata?.name, + "genkit.action_key": metadata?.key, + "genkit.run_name": runStepName, + }), + }; +} + +function extractActionOutput(result: unknown): unknown { + if (isObject(result) && "result" in result) { + return result.result; + } + return result; +} + +function genkitProviderMetadata(): Record { + return { provider: "genkit" }; +} + +function safeGet(value: unknown, key: string): unknown { + if (!isObject(value)) { + return undefined; + } + try { + return value[key]; + } catch { + return undefined; + } +} + +function configValue(config: unknown, key: string): unknown { + return isObject(config) ? config[key] : undefined; +} + +function modelName(model: unknown): string | undefined { + if (typeof model === "string") { + return model; + } + if (isObject(model)) { + const name = model.name ?? model.model; + return typeof name === "string" ? name : undefined; + } + return undefined; +} + +function pickDefined(values: Record): Record { + return Object.fromEntries( + Object.entries(values).filter(([, value]) => value !== undefined), + ); +} + +function pickNumberMetrics( + values: Record, +): Record { + return Object.fromEntries( + Object.entries(values).filter((entry): entry is [string, number] => { + const value = entry[1]; + return typeof value === "number" && Number.isFinite(value); + }), + ); +} + +function isAsyncIterableLike(value: unknown): value is AsyncIterable { + return ( + isObject(value) && + typeof (value as { [Symbol.asyncIterator]?: unknown })[ + Symbol.asyncIterator + ] === "function" + ); +} + +function errorMessage(error: unknown): string { + return error instanceof Error ? error.message : String(error); +} diff --git a/js/src/instrumentation/registry.ts b/js/src/instrumentation/registry.ts index 8e09f214a..11d863c43 100644 --- a/js/src/instrumentation/registry.ts +++ b/js/src/instrumentation/registry.ts @@ -19,6 +19,8 @@ export interface InstrumentationConfig { vercel?: boolean; aisdk?: boolean; google?: boolean; + googleGenAI?: boolean; + googleADK?: boolean; huggingface?: boolean; claudeAgentSDK?: boolean; cursor?: boolean; @@ -27,6 +29,8 @@ export interface InstrumentationConfig { openrouterAgent?: boolean; mistral?: boolean; cohere?: boolean; + groq?: boolean; + genkit?: boolean; }; } @@ -111,6 +115,8 @@ class PluginRegistry { vercel: true, aisdk: true, google: true, + googleGenAI: true, + googleADK: true, huggingface: true, claudeAgentSDK: true, cursor: true, @@ -119,6 +125,8 @@ class PluginRegistry { openrouterAgent: true, mistral: true, cohere: true, + groq: true, + genkit: true, }; } diff --git a/js/src/vendor-sdk-types/genkit.ts b/js/src/vendor-sdk-types/genkit.ts new file mode 100644 index 000000000..5bebdfe51 --- /dev/null +++ b/js/src/vendor-sdk-types/genkit.ts @@ -0,0 +1,150 @@ +/** + * Vendored Genkit types used internally by the wrapper and instrumentation. + * + * Should never be exposed to users of the SDK. + */ + +export type GenkitModelArgument = + | string + | { + name?: string; + version?: string; + [key: string]: unknown; + } + | { + model?: string; + [key: string]: unknown; + }; + +export type GenkitPart = { + text?: string; + media?: unknown; + data?: unknown; + [key: string]: unknown; +}; + +export type GenkitGenerateOptions = { + model?: GenkitModelArgument; + prompt?: string | GenkitPart[]; + system?: string | GenkitPart[]; + messages?: Array<{ + role?: string; + content?: GenkitPart[]; + [key: string]: unknown; + }>; + docs?: unknown; + tools?: unknown; + config?: Record; + output?: unknown; + metadata?: Record; + context?: Record; + [key: string]: unknown; +}; + +export type GenkitGenerateInput = + | string + | GenkitPart[] + | GenkitGenerateOptions + | PromiseLike; + +export type GenkitUsage = { + inputTokens?: number; + outputTokens?: number; + totalTokens?: number; + thoughtsTokens?: number; + cachedContentTokens?: number; + [key: string]: unknown; +}; + +export type GenkitGenerateResponse = { + text?: string; + output?: unknown; + message?: unknown; + finishReason?: string; + finishMessage?: string; + usage?: GenkitUsage; + request?: GenkitGenerateOptions; + model?: string; + toJSON?: () => unknown; + [key: string]: unknown; +}; + +export type GenkitGenerateResponseChunk = { + text?: string; + accumulatedText?: string; + content?: GenkitPart[]; + role?: string; + [key: string]: unknown; +}; + +export type GenkitGenerateStreamResponse = { + stream: AsyncIterable; + response: Promise; + [key: string]: unknown; +}; + +export type GenkitEmbedding = number[] | { embedding?: number[] }; + +export type GenkitEmbedParams = { + embedder?: GenkitModelArgument; + content?: unknown; + metadata?: Record; + options?: Record; + [key: string]: unknown; +}; + +export type GenkitEmbedManyParams = { + embedder?: GenkitModelArgument; + content?: unknown[]; + metadata?: Record; + options?: Record; + [key: string]: unknown; +}; + +export type GenkitActionMetadata = { + actionType?: string; + key?: string; + name?: string; + description?: string; + metadata?: Record; + [key: string]: unknown; +}; + +export type GenkitActionResult = { + result?: unknown; + telemetry?: { + traceId?: string; + spanId?: string; + }; + [key: string]: unknown; +}; + +export type GenkitAction = { + (input?: unknown, options?: unknown): Promise; + __action?: GenkitActionMetadata; + __registry?: unknown; + run?: (input?: unknown, options?: unknown) => Promise; + stream?: ( + input?: unknown, + options?: unknown, + ) => { + stream: AsyncIterable; + output: Promise; + }; + [key: string]: unknown; +}; + +export type GenkitInstance = { + generate?: (input: GenkitGenerateInput) => Promise; + generateStream?: (input: GenkitGenerateInput) => GenkitGenerateStreamResponse; + embed?: (params: GenkitEmbedParams) => Promise; + embedMany?: (params: GenkitEmbedManyParams) => Promise; + run?: ( + name: string, + inputOrFn: unknown, + maybeFn?: (input?: unknown) => Promise, + ) => Promise; + defineFlow?: (...args: unknown[]) => GenkitAction; + defineTool?: (...args: unknown[]) => GenkitAction; + [key: string]: unknown; +}; diff --git a/js/src/wrappers/genkit.ts b/js/src/wrappers/genkit.ts new file mode 100644 index 000000000..6b5fd1bb7 --- /dev/null +++ b/js/src/wrappers/genkit.ts @@ -0,0 +1,237 @@ +import { genkitChannels } from "../instrumentation/plugins/genkit-channels"; +import type { + GenkitAction, + GenkitEmbedManyParams, + GenkitEmbedParams, + GenkitEmbedding, + GenkitGenerateInput, + GenkitGenerateResponse, + GenkitGenerateStreamResponse, + GenkitInstance, +} from "../vendor-sdk-types/genkit"; + +const WRAPPED_GENKIT = Symbol.for("braintrust.genkit.wrapped"); + +/** + * Wrap a Genkit instance or module so Genkit calls emit diagnostics-channel + * events that Braintrust plugins can consume. + * + * This supports both: + * - `const ai = wrapGenkit(genkit({ ... }))` + * - wrapping the module namespace and then calling its `genkit` factory + */ +export function wrapGenkit(genkit: T): T { + if (isGenkitInstance(genkit)) { + return wrapGenkitInstance(genkit) as T; + } + + if (isGenkitModule(genkit)) { + return wrapGenkitModule(genkit) as T; + } + + // eslint-disable-next-line no-restricted-properties -- preserving intentional console usage. + console.warn("Unsupported Genkit object. Not wrapping."); + return genkit; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function hasFunction(value: unknown, methodName: string): boolean { + return ( + isRecord(value) && + methodName in value && + typeof value[methodName] === "function" + ); +} + +function isGenkitInstance(value: unknown): value is GenkitInstance { + return ( + isRecord(value) && + (hasFunction(value, "generate") || + hasFunction(value, "generateStream") || + hasFunction(value, "defineFlow") || + hasFunction(value, "defineTool")) + ); +} + +function isGenkitModule(value: unknown): value is Record & { + genkit: (...args: unknown[]) => unknown; +} { + return hasFunction(value, "genkit"); +} + +function wrapGenkitModule>(module: T): T { + return new Proxy(module, { + get(target, prop, receiver) { + const value = Reflect.get(target, prop, receiver); + if (prop === "genkit" && typeof value === "function") { + const factory = value as (...args: unknown[]) => unknown; + return (...args: unknown[]) => wrapGenkit(factory(...args)); + } + return value; + }, + }); +} + +function wrapGenkitInstance(instance: GenkitInstance): GenkitInstance { + if (hasWrappedFlag(instance)) { + return instance; + } + + const proxy = new Proxy(instance, { + get(target, prop, receiver) { + switch (prop) { + case WRAPPED_GENKIT: + return true; + case "generate": + return typeof target.generate === "function" + ? wrapGenerate(target.generate.bind(target)) + : target.generate; + case "generateStream": + return typeof target.generateStream === "function" + ? wrapGenerateStream(target.generateStream.bind(target)) + : target.generateStream; + case "embed": + return typeof target.embed === "function" + ? wrapEmbed(target.embed.bind(target)) + : target.embed; + case "embedMany": + return typeof target.embedMany === "function" + ? wrapEmbedMany(target.embedMany.bind(target)) + : target.embedMany; + case "run": + return typeof target.run === "function" + ? wrapRun(target.run.bind(target)) + : target.run; + case "defineFlow": + return typeof target.defineFlow === "function" + ? (...args: unknown[]) => + wrapGenkitAction(target.defineFlow!(...args)) + : target.defineFlow; + case "defineTool": + return typeof target.defineTool === "function" + ? (...args: unknown[]) => + wrapGenkitAction(target.defineTool!(...args)) + : target.defineTool; + default: + return Reflect.get(target, prop, receiver); + } + }, + }); + + return proxy; +} + +function wrapGenerate( + generate: (input: GenkitGenerateInput) => Promise, +): NonNullable { + return (input) => + genkitChannels.generate.tracePromise(() => generate(input), { + arguments: [input], + }); +} + +function wrapGenerateStream( + generateStream: (input: GenkitGenerateInput) => GenkitGenerateStreamResponse, +): NonNullable { + return (input) => + genkitChannels.generateStream.traceSync(() => generateStream(input), { + arguments: [input], + } as Parameters[1]); +} + +function wrapEmbed( + embed: (params: GenkitEmbedParams) => Promise, +): NonNullable { + return (params) => + genkitChannels.embed.tracePromise(() => embed(params), { + arguments: [params], + }) as Promise; +} + +function wrapEmbedMany( + embedMany: (params: GenkitEmbedManyParams) => Promise, +): NonNullable { + return (params) => + genkitChannels.embedMany.tracePromise(() => embedMany(params), { + arguments: [params], + }) as Promise; +} + +function wrapRun( + run: NonNullable, +): NonNullable { + return (name, inputOrFn, maybeFn) => + genkitChannels.actionRun.tracePromise(() => run(name, inputOrFn, maybeFn), { + arguments: [name, inputOrFn, maybeFn], + } as Parameters< + typeof genkitChannels.actionRun.tracePromise + >[1]) as Promise; +} + +function wrapGenkitAction(action: GenkitAction): GenkitAction { + if (!isGenkitAction(action) || hasWrappedFlag(action)) { + return action; + } + + return new Proxy(action, { + apply(target, thisArg, argArray) { + return traceActionRun(target, () => + Reflect.apply(target, thisArg, argArray), + )(argArray[0], argArray[1]); + }, + get(target, prop, receiver) { + switch (prop) { + case WRAPPED_GENKIT: + return true; + case "run": + return typeof target.run === "function" + ? traceActionRun(target, target.run.bind(target)) + : target.run; + case "stream": + return typeof target.stream === "function" + ? traceActionStream(target, target.stream.bind(target)) + : target.stream; + default: + return Reflect.get(target, prop, receiver); + } + }, + }); +} + +function isGenkitAction(value: unknown): value is GenkitAction { + return ( + typeof value === "function" && + "__action" in (value as unknown as Record) + ); +} + +function traceActionRun( + action: GenkitAction, + run: (input?: unknown, options?: unknown) => Promise, +): (input?: unknown, options?: unknown) => Promise { + return (input, options) => + genkitChannels.actionRun.tracePromise(() => run(input, options), { + arguments: [input, options], + self: action, + } as Parameters< + typeof genkitChannels.actionRun.tracePromise + >[1]) as Promise; +} + +function traceActionStream( + action: GenkitAction, + stream: NonNullable, +): NonNullable { + return (input, options) => + genkitChannels.actionStream.traceSync(() => stream(input, options), { + arguments: [input, options], + self: action, + } as Parameters[1]); +} + +function hasWrappedFlag(value: object): boolean { + return Boolean((value as Record)[WRAPPED_GENKIT]); +} From 9e47e19869d775d475cff4a0764b6bcaaef2e98b Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 May 2026 15:38:58 -0700 Subject: [PATCH 2/5] cs --- .changeset/fancy-symbols-double.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fancy-symbols-double.md diff --git a/.changeset/fancy-symbols-double.md b/.changeset/fancy-symbols-double.md new file mode 100644 index 000000000..7e0660a1f --- /dev/null +++ b/.changeset/fancy-symbols-double.md @@ -0,0 +1,5 @@ +--- +"braintrust": minor +--- + +feat: Add Firebase genkit instrumentation From d0089bab5ea5b5e165d461751dc86ce7ab21fb41 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 May 2026 15:44:13 -0700 Subject: [PATCH 3/5] fix hermetic --- e2e/scenarios/genkit-instrumentation/assertions.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/e2e/scenarios/genkit-instrumentation/assertions.ts b/e2e/scenarios/genkit-instrumentation/assertions.ts index 4b311a1cb..81bf98cf6 100644 --- a/e2e/scenarios/genkit-instrumentation/assertions.ts +++ b/e2e/scenarios/genkit-instrumentation/assertions.ts @@ -6,7 +6,6 @@ import { resolveFileSnapshotPath, } from "../../helpers/file-snapshot"; import { withScenarioHarness } from "../../helpers/scenario-harness"; -import { E2E_TAGS } from "../../helpers/tags"; import { findChildSpans, findLatestSpan } from "../../helpers/trace-selectors"; import { summarizeWrapperContract } from "../../helpers/wrapper-contract"; import { ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; @@ -95,7 +94,6 @@ export function defineGenkitInstrumentationAssertions(options: { `${options.snapshotName}.span-events.json`, ); const testConfig = { - tags: [E2E_TAGS.hermetic], timeout: options.timeoutMs, }; From e36c57a6241611936bddf9b00e9a10435b6c6f3b Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 May 2026 17:26:04 -0700 Subject: [PATCH 4/5] properly nest --- .../genkit-v1-33-0-auto.span-events.json | 74 +++++++++++-- .../genkit-v1-33-0-wrapped.span-events.json | 103 ++++++++++++------ .../genkit-instrumentation/assertions.ts | 83 ++++++++++++-- .../genkit-instrumentation/constants.mjs | 1 + .../genkit-instrumentation/scenario.impl.mjs | 91 +++++++++++----- 5 files changed, 273 insertions(+), 79 deletions(-) diff --git a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json index d3cf1fba3..a4595130a 100644 --- a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json +++ b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json @@ -16,10 +16,10 @@ "has_input": false, "has_output": false, "metadata": { - "operation": "generate" + "operation": "flow" }, "metric_keys": [], - "name": "genkit-generate-operation", + "name": "genkit-flow-operation", "root_span_id": "", "span_id": "", "span_parents": [ @@ -27,6 +27,21 @@ ], "type": null }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "generate" + }, + "metric_keys": [], + "name": "genkit-generate-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, { "has_input": true, "has_output": true, @@ -41,9 +56,9 @@ ], "name": "genkit.generate", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -56,9 +71,9 @@ "metric_keys": [], "name": "genkit-stream-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -77,9 +92,9 @@ ], "name": "genkit.generateStream", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -92,9 +107,9 @@ "metric_keys": [], "name": "genkit-embed-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -108,9 +123,44 @@ "metric_keys": [], "name": "genkit.embed", "root_span_id": "", - "span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "function" + }, + { + "has_input": false, + "has_output": true, + "metadata": { + "operation": "model-tool" + }, + "metric_keys": [], + "name": "genkit-model-tool-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "model": "googleai/gemini-2.5-flash-lite", + "provider": "genkit" + }, + "metric_keys": [ + "completion_tokens", + "prompt_tokens", + "tokens" + ], + "name": "genkit.generate", + "root_span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" } diff --git a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json index 0637aba1a..c2a6b095a 100644 --- a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json +++ b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json @@ -16,10 +16,10 @@ "has_input": false, "has_output": false, "metadata": { - "operation": "generate" + "operation": "flow" }, "metric_keys": [], - "name": "genkit-generate-operation", + "name": "genkit-flow-operation", "root_span_id": "", "span_id": "", "span_parents": [ @@ -27,6 +27,40 @@ ], "type": null }, + { + "has_input": true, + "has_output": true, + "metadata": { + "genkit.action_name": "instrumentationFlow", + "genkit.action_type": "flow", + "provider": "genkit" + }, + "metric_keys": [ + "duration" + ], + "name": "genkit.flow: instrumentationFlow", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "task" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "generate" + }, + "metric_keys": [], + "name": "genkit-generate-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, { "has_input": true, "has_output": true, @@ -41,9 +75,9 @@ ], "name": "genkit.generate", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -56,9 +90,9 @@ "metric_keys": [], "name": "genkit-stream-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -77,9 +111,9 @@ ], "name": "genkit.generateStream", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -92,9 +126,9 @@ "metric_keys": [], "name": "genkit-embed-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -108,24 +142,24 @@ "metric_keys": [], "name": "genkit.embed", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, { "has_input": false, - "has_output": false, + "has_output": true, "metadata": { - "operation": "tool" + "operation": "model-tool" }, "metric_keys": [], - "name": "genkit-tool-operation", + "name": "genkit-model-tool-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -133,33 +167,34 @@ "has_input": true, "has_output": true, "metadata": { - "genkit.action_name": "summarizeCity", - "genkit.action_type": "tool", + "model": "googleai/gemini-2.5-flash-lite", "provider": "genkit" }, "metric_keys": [ - "duration" + "completion_tokens", + "prompt_tokens", + "tokens" ], - "name": "genkit.tool: summarizeCity", + "name": "genkit.generate", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], - "type": "tool" + "type": "function" }, { "has_input": false, "has_output": false, "metadata": { - "operation": "flow" + "operation": "tool" }, "metric_keys": [], - "name": "genkit-flow-operation", + "name": "genkit-tool-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -167,19 +202,19 @@ "has_input": true, "has_output": true, "metadata": { - "genkit.action_name": "recipeFlow", - "genkit.action_type": "flow", + "genkit.action_name": "summarizeCity", + "genkit.action_type": "tool", "provider": "genkit" }, "metric_keys": [ "duration" ], - "name": "genkit.flow: recipeFlow", + "name": "genkit.tool: summarizeCity", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], - "type": "task" + "type": "tool" } ] diff --git a/e2e/scenarios/genkit-instrumentation/assertions.ts b/e2e/scenarios/genkit-instrumentation/assertions.ts index 81bf98cf6..3eea952fc 100644 --- a/e2e/scenarios/genkit-instrumentation/assertions.ts +++ b/e2e/scenarios/genkit-instrumentation/assertions.ts @@ -8,7 +8,7 @@ import { import { withScenarioHarness } from "../../helpers/scenario-harness"; import { findChildSpans, findLatestSpan } from "../../helpers/trace-selectors"; import { summarizeWrapperContract } from "../../helpers/wrapper-contract"; -import { ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; +import { MODEL_TOOL_MARKER, ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; type RunGenkitScenario = (harness: { runNodeScenarioDir: (options: { @@ -35,27 +35,49 @@ function findGenkitSpan( return spans.find((candidate) => candidate.output !== undefined) ?? spans[0]; } +function expectChildOf( + child: CapturedLogEvent | undefined, + parent: CapturedLogEvent | undefined, +) { + expect(child?.span.parentIds).toContain(parent?.span.id); +} + function buildSpanSummary( events: CapturedLogEvent[], supportsActionSpans: boolean, ): Json { + const flowOperation = findLatestSpan(events, "genkit-flow-operation"); + const flowSpan = supportsActionSpans + ? findGenkitSpan( + events, + flowOperation?.span.id, + "genkit.flow: instrumentationFlow", + ) + : undefined; const generateOperation = findLatestSpan(events, "genkit-generate-operation"); const streamOperation = findLatestSpan(events, "genkit-stream-operation"); const embedOperation = findLatestSpan(events, "genkit-embed-operation"); + const modelToolOperation = findLatestSpan( + events, + "genkit-model-tool-operation", + ); const summary = [ findLatestSpan(events, ROOT_NAME), + flowOperation, + ...(supportsActionSpans ? [flowSpan] : []), generateOperation, findGenkitSpan(events, generateOperation?.span.id, "genkit.generate"), streamOperation, findGenkitSpan(events, streamOperation?.span.id, "genkit.generateStream"), embedOperation, findGenkitSpan(events, embedOperation?.span.id, "genkit.embed"), + modelToolOperation, + findGenkitSpan(events, modelToolOperation?.span.id, "genkit.generate"), ]; if (supportsActionSpans) { const toolOperation = findLatestSpan(events, "genkit-tool-operation"); - const flowOperation = findLatestSpan(events, "genkit-flow-operation"); summary.push( toolOperation, findGenkitSpan( @@ -63,8 +85,6 @@ function buildSpanSummary( toolOperation?.span.id, "genkit.tool: summarizeCity", ), - flowOperation, - findGenkitSpan(events, flowOperation?.span.id, "genkit.flow: recipeFlow"), ); } @@ -115,6 +135,34 @@ export function defineGenkitInstrumentationAssertions(options: { }); }); + test( + "nests scenario operations under the flow operation", + testConfig, + () => { + const flowOperation = findLatestSpan(events, "genkit-flow-operation"); + expect(flowOperation).toBeDefined(); + + if (options.supportsActionSpans) { + const flowSpan = findGenkitSpan( + events, + flowOperation?.span.id, + "genkit.flow: instrumentationFlow", + ); + expectChildOf(flowSpan, flowOperation); + } + + for (const operationName of [ + "genkit-generate-operation", + "genkit-stream-operation", + "genkit-embed-operation", + "genkit-tool-operation", + "genkit-model-tool-operation", + ]) { + expectChildOf(findLatestSpan(events, operationName), flowOperation); + } + }, + ); + test("captures generate, stream, and embed spans", testConfig, () => { const generateOperation = findLatestSpan( events, @@ -170,6 +218,27 @@ export function defineGenkitInstrumentationAssertions(options: { }); }); + test("captures a model-triggered tool call", testConfig, () => { + const modelToolOperation = findLatestSpan( + events, + "genkit-model-tool-operation", + ); + const generateSpan = findGenkitSpan( + events, + modelToolOperation?.span.id, + "genkit.generate", + ); + + expect(generateSpan?.row.metadata).toMatchObject({ + provider: "genkit", + }); + expect(generateSpan?.output).toBeDefined(); + expect(modelToolOperation?.output).toMatchObject({ + marker: MODEL_TOOL_MARKER, + toolCalled: true, + }); + }); + test.runIf(options.supportsActionSpans)( "captures tool and flow action spans", testConfig, @@ -184,7 +253,7 @@ export function defineGenkitInstrumentationAssertions(options: { const flowSpan = findGenkitSpan( events, flowOperation?.span.id, - "genkit.flow: recipeFlow", + "genkit.flow: instrumentationFlow", ); expect(toolSpan?.row.metadata).toMatchObject({ @@ -197,12 +266,12 @@ export function defineGenkitInstrumentationAssertions(options: { }); expect(flowSpan?.row.metadata).toMatchObject({ - "genkit.action_name": "recipeFlow", + "genkit.action_name": "instrumentationFlow", "genkit.action_type": "flow", provider: "genkit", }); expect(flowSpan?.output).toMatchObject({ - recipe: expect.any(String), + completed: true, }); }, ); diff --git a/e2e/scenarios/genkit-instrumentation/constants.mjs b/e2e/scenarios/genkit-instrumentation/constants.mjs index 8685f6f2b..f8fcdc07f 100644 --- a/e2e/scenarios/genkit-instrumentation/constants.mjs +++ b/e2e/scenarios/genkit-instrumentation/constants.mjs @@ -1,2 +1,3 @@ export const ROOT_NAME = "genkit-instrumentation-root"; export const SCENARIO_NAME = "genkit-instrumentation"; +export const MODEL_TOOL_MARKER = "genkit-model-tool-called-vienna"; diff --git a/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs b/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs index f457d2b2c..2ea0b3866 100644 --- a/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs +++ b/e2e/scenarios/genkit-instrumentation/scenario.impl.mjs @@ -1,10 +1,10 @@ -import { wrapGenkit } from "braintrust"; +import { currentSpan, wrapGenkit } from "braintrust"; import { collectAsync, runOperation, runTracedScenario, } from "../../helpers/provider-runtime.mjs"; -import { ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; +import { MODEL_TOOL_MARKER, ROOT_NAME, SCENARIO_NAME } from "./constants.mjs"; export const GENKIT_SCENARIO_TIMEOUT_MS = 90_000; @@ -129,38 +129,36 @@ export async function runGenkitInstrumentationScenario(options = {}) { }), ); - const recipeFlow = ai.defineFlow( + let modelToolCallCount = 0; + const modelTool = ai.defineTool( { - name: "recipeFlow", - inputSchema: z.string(), + name: "cityMarkerTool", + description: + "Returns the canonical marker for a city. Always use this tool when asked for a city marker.", + inputSchema: z.object({ + city: z.string(), + }), outputSchema: z.object({ - recipe: z.string(), + marker: z.string(), }), }, - async (topic) => { - const normalized = await ai.run("normalize-topic", topic, async (input) => - String(input).trim().toLowerCase(), - ); - const response = await withRetry( - () => - ai.generate({ - model, - prompt: `Write a recipe about ${normalized}.`, - config: { - temperature: 0, - maxOutputTokens: 32, - }, - }), - GOOGLE_GENAI_RETRY_OPTIONS, - ); + async ({ city }) => { + modelToolCallCount += 1; return { - recipe: response.text, + marker: city === "Vienna" ? MODEL_TOOL_MARKER : `marker-${city}`, }; }, ); - await runTracedScenario({ - callback: async () => { + const instrumentationFlow = ai.defineFlow( + { + name: "instrumentationFlow", + inputSchema: z.string(), + outputSchema: z.object({ + completed: z.boolean(), + }), + }, + async () => { await runOperation("genkit-generate-operation", "generate", async () => { await withRetry( () => @@ -208,8 +206,49 @@ export async function runGenkitInstrumentationScenario(options = {}) { }); }); + await runOperation( + "genkit-model-tool-operation", + "model-tool", + async () => { + const previousToolCallCount = modelToolCallCount; + await withRetry( + () => + ai.generate({ + model, + prompt: + "Use the cityMarkerTool tool with city Vienna before answering.", + tools: [modelTool], + maxTurns: 3, + config: { + temperature: 0, + maxOutputTokens: 64, + }, + }), + GOOGLE_GENAI_RETRY_OPTIONS, + ); + + if (modelToolCallCount === previousToolCallCount) { + throw new Error("Expected model generation to call cityMarkerTool"); + } + currentSpan().log({ + output: { + marker: MODEL_TOOL_MARKER, + toolCalled: true, + }, + }); + }, + ); + + return { + completed: true, + }; + }, + ); + + await runTracedScenario({ + callback: async () => { await runOperation("genkit-flow-operation", "flow", async () => { - await recipeFlow("Cake"); + await instrumentationFlow("run"); }); }, flushCount: 2, From 5b3dd42dd4c06b74e7f171fb362c3280ad086163 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 5 May 2026 10:22:39 -0700 Subject: [PATCH 5/5] proper nesting --- .../genkit-v1-33-0-auto.span-events.json | 85 +++++- .../genkit-v1-33-0-wrapped.span-events.json | 10 +- .../genkit-instrumentation/assertions.ts | 44 ++- .../genkit-instrumentation/scenario.test.ts | 2 +- .../auto-instrumentations/configs/genkit.ts | 29 +- .../plugins/genkit-channels.ts | 7 + .../instrumentation/plugins/genkit-plugin.ts | 274 ++++++++++++++++-- 7 files changed, 381 insertions(+), 70 deletions(-) diff --git a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json index a4595130a..ea1e93dfa 100644 --- a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json +++ b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-auto.span-events.json @@ -27,6 +27,25 @@ ], "type": null }, + { + "has_input": true, + "has_output": true, + "metadata": { + "genkit.action_name": "instrumentationFlow", + "genkit.action_type": "flow", + "provider": "genkit" + }, + "metric_keys": [ + "duration" + ], + "name": "genkit.flow: instrumentationFlow", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "task" + }, { "has_input": false, "has_output": false, @@ -36,9 +55,9 @@ "metric_keys": [], "name": "genkit-generate-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -56,9 +75,9 @@ ], "name": "genkit.generate", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -71,9 +90,9 @@ "metric_keys": [], "name": "genkit-stream-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -92,9 +111,9 @@ ], "name": "genkit.generateStream", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -107,9 +126,9 @@ "metric_keys": [], "name": "genkit-embed-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -123,9 +142,9 @@ "metric_keys": [], "name": "genkit.embed", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" }, @@ -138,9 +157,9 @@ "metric_keys": [], "name": "genkit-model-tool-operation", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -158,10 +177,44 @@ ], "name": "genkit.generate", "root_span_id": "", - "span_id": "", + "span_id": "", "span_parents": [ - "" + "" ], "type": "function" + }, + { + "has_input": false, + "has_output": false, + "metadata": { + "operation": "tool" + }, + "metric_keys": [], + "name": "genkit-tool-operation", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": null + }, + { + "has_input": true, + "has_output": true, + "metadata": { + "genkit.action_name": "summarizeCity", + "genkit.action_type": "tool", + "provider": "genkit" + }, + "metric_keys": [ + "duration" + ], + "name": "genkit.tool: summarizeCity", + "root_span_id": "", + "span_id": "", + "span_parents": [ + "" + ], + "type": "tool" } ] diff --git a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json index c2a6b095a..ea1e93dfa 100644 --- a/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json +++ b/e2e/scenarios/genkit-instrumentation/__snapshots__/genkit-v1-33-0-wrapped.span-events.json @@ -57,7 +57,7 @@ "root_span_id": "", "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -92,7 +92,7 @@ "root_span_id": "", "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -128,7 +128,7 @@ "root_span_id": "", "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -159,7 +159,7 @@ "root_span_id": "", "span_id": "", "span_parents": [ - "" + "" ], "type": null }, @@ -194,7 +194,7 @@ "root_span_id": "", "span_id": "", "span_parents": [ - "" + "" ], "type": null }, diff --git a/e2e/scenarios/genkit-instrumentation/assertions.ts b/e2e/scenarios/genkit-instrumentation/assertions.ts index 3eea952fc..4844cdf78 100644 --- a/e2e/scenarios/genkit-instrumentation/assertions.ts +++ b/e2e/scenarios/genkit-instrumentation/assertions.ts @@ -135,33 +135,27 @@ export function defineGenkitInstrumentationAssertions(options: { }); }); - test( - "nests scenario operations under the flow operation", - testConfig, - () => { - const flowOperation = findLatestSpan(events, "genkit-flow-operation"); - expect(flowOperation).toBeDefined(); + test("nests scenario operations under the flow span", testConfig, () => { + const flowOperation = findLatestSpan(events, "genkit-flow-operation"); + expect(flowOperation).toBeDefined(); - if (options.supportsActionSpans) { - const flowSpan = findGenkitSpan( - events, - flowOperation?.span.id, - "genkit.flow: instrumentationFlow", - ); - expectChildOf(flowSpan, flowOperation); - } + const flowSpan = findGenkitSpan( + events, + flowOperation?.span.id, + "genkit.flow: instrumentationFlow", + ); + expectChildOf(flowSpan, flowOperation); - for (const operationName of [ - "genkit-generate-operation", - "genkit-stream-operation", - "genkit-embed-operation", - "genkit-tool-operation", - "genkit-model-tool-operation", - ]) { - expectChildOf(findLatestSpan(events, operationName), flowOperation); - } - }, - ); + for (const operationName of [ + "genkit-generate-operation", + "genkit-stream-operation", + "genkit-embed-operation", + "genkit-tool-operation", + "genkit-model-tool-operation", + ]) { + expectChildOf(findLatestSpan(events, operationName), flowSpan); + } + }); test("captures generate, stream, and embed spans", testConfig, () => { const generateOperation = findLatestSpan( diff --git a/e2e/scenarios/genkit-instrumentation/scenario.test.ts b/e2e/scenarios/genkit-instrumentation/scenario.test.ts index 0541ade14..0f327d2b8 100644 --- a/e2e/scenarios/genkit-instrumentation/scenario.test.ts +++ b/e2e/scenarios/genkit-instrumentation/scenario.test.ts @@ -43,7 +43,7 @@ describe(`genkit ${genkitVersion}`, () => { }); }, snapshotName: `${snapshotName}-auto`, - supportsActionSpans: false, + supportsActionSpans: true, testFileUrl: import.meta.url, timeoutMs: GENKIT_SCENARIO_TIMEOUT_MS, }); diff --git a/js/src/auto-instrumentations/configs/genkit.ts b/js/src/auto-instrumentations/configs/genkit.ts index 7438f8379..2ba2a111f 100644 --- a/js/src/auto-instrumentations/configs/genkit.ts +++ b/js/src/auto-instrumentations/configs/genkit.ts @@ -1,5 +1,8 @@ import type { InstrumentationConfig } from "@apm-js-collab/code-transformer"; -import { genkitChannels } from "../../instrumentation/plugins/genkit-channels"; +import { + genkitChannels, + genkitCoreChannels, +} from "../../instrumentation/plugins/genkit-channels"; const genkitVersionRange = ">=1.0.0 <2.0.0"; @@ -141,4 +144,28 @@ export const genkitConfigs: InstrumentationConfig[] = [ kind: "Async", }, }, + { + channelName: genkitCoreChannels.actionSpan.channelName, + module: { + name: "@genkit-ai/core", + versionRange: genkitVersionRange, + filePath: "lib/tracing/instrumentation.mjs", + }, + functionQuery: { + functionName: "runInNewSpan", + kind: "Async", + }, + }, + { + channelName: genkitCoreChannels.actionSpan.channelName, + module: { + name: "@genkit-ai/core", + versionRange: genkitVersionRange, + filePath: "lib/tracing/instrumentation.js", + }, + functionQuery: { + functionName: "runInNewSpan", + kind: "Async", + }, + }, ]; diff --git a/js/src/instrumentation/plugins/genkit-channels.ts b/js/src/instrumentation/plugins/genkit-channels.ts index a3e863a88..b85ce26c0 100644 --- a/js/src/instrumentation/plugins/genkit-channels.ts +++ b/js/src/instrumentation/plugins/genkit-channels.ts @@ -51,3 +51,10 @@ export const genkitChannels = defineChannels("@genkit-ai/ai", { kind: "sync-stream", }), }); + +export const genkitCoreChannels = defineChannels("@genkit-ai/core", { + actionSpan: channel<[unknown, unknown, unknown?], unknown>({ + channelName: "action.span", + kind: "async", + }), +}); diff --git a/js/src/instrumentation/plugins/genkit-plugin.ts b/js/src/instrumentation/plugins/genkit-plugin.ts index d18d31a14..3c1cb83ce 100644 --- a/js/src/instrumentation/plugins/genkit-plugin.ts +++ b/js/src/instrumentation/plugins/genkit-plugin.ts @@ -6,12 +6,16 @@ import { } from "../core/channel-tracing"; import type { ChannelMessage } from "../core/channel-definitions"; import type { IsoChannelHandlers, IsoTracingChannel } from "../../isomorph"; -import { startSpan } from "../../logger"; -import type { Span } from "../../logger"; +import { + _internalGetGlobalState, + BRAINTRUST_CURRENT_SPAN_STORE, + startSpan, +} from "../../logger"; +import type { CurrentSpanStore, Span } from "../../logger"; import { getCurrentUnixTimestamp, isObject } from "../../util"; import { SpanTypeAttribute } from "../../../util/index"; import { processInputAttachments } from "../../wrappers/attachment-utils"; -import { genkitChannels } from "./genkit-channels"; +import { genkitChannels, genkitCoreChannels } from "./genkit-channels"; import type { GenkitAction, GenkitActionMetadata, @@ -86,6 +90,7 @@ export class GenkitPlugin extends BasePlugin { ); this.subscribeToActionRun(); + this.subscribeToActionSpan(); this.subscribeToActionStream(); } @@ -95,29 +100,19 @@ export class GenkitPlugin extends BasePlugin { ChannelMessage >; const states = new WeakMap(); + const unbindCurrentSpanStore = bindActionCurrentSpanStoreToStart( + tracingChannel, + states, + (event) => startActionRunSpan(event), + ); const handlers: IsoChannelHandlers< ChannelMessage > = { start: (event) => { - const metadata = extractActionMetadata(event.self); - const runStepName = - !metadata && typeof event.arguments[0] === "string" - ? event.arguments[0] - : undefined; - const span = startSpan({ - name: actionSpanName(metadata, runStepName), - spanAttributes: { - type: actionSpanType(metadata), - }, - }); - const startTime = getCurrentUnixTimestamp(); - - span.log({ - input: runStepName ? event.arguments[1] : event.arguments[0], - metadata: actionMetadataForLog(metadata, runStepName), - }); - states.set(event, { span, startTime }); + ensureActionSpanState(states, event as object, () => + startActionRunSpan(event), + ); }, asyncEnd: (event) => { const state = states.get(event); @@ -147,7 +142,65 @@ export class GenkitPlugin extends BasePlugin { }; tracingChannel.subscribe(handlers); - this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers)); + this.unsubscribers.push(() => { + unbindCurrentSpanStore?.(); + tracingChannel.unsubscribe(handlers); + }); + } + + private subscribeToActionSpan(): void { + const tracingChannel = + genkitCoreChannels.actionSpan.tracingChannel() as IsoTracingChannel< + ChannelMessage + >; + const states = new WeakMap(); + const unbindCurrentSpanStore = bindActionCurrentSpanStoreToStart( + tracingChannel, + states, + (event) => startActionSpan(event), + ); + + const handlers: IsoChannelHandlers< + ChannelMessage + > = { + start: (event) => { + ensureActionSpanState(states, event as object, () => + startActionSpan(event), + ); + }, + asyncEnd: (event) => { + const state = states.get(event as object); + if (!state) { + return; + } + + try { + state.span.log({ + input: extractActionSpanInput(event.arguments), + output: extractActionOutput(event.result), + metrics: durationMetrics(state.startTime), + }); + } finally { + state.span.end(); + states.delete(event as object); + } + }, + error: (event) => { + const state = states.get(event as object); + if (!state || !event.error) { + return; + } + state.span.log({ error: event.error.message }); + state.span.end(); + states.delete(event as object); + }, + }; + + tracingChannel.subscribe(handlers); + this.unsubscribers.push(() => { + unbindCurrentSpanStore?.(); + tracingChannel.unsubscribe(handlers); + }); } private subscribeToActionStream(): void { @@ -166,6 +219,122 @@ export class GenkitPlugin extends BasePlugin { } } +function startActionRunSpan( + event: ChannelMessage, +): SpanState | undefined { + const metadata = extractActionMetadata(event.self); + const runStepName = + !metadata && typeof event.arguments[0] === "string" + ? event.arguments[0] + : undefined; + return startActionSpanState({ + input: runStepName ? event.arguments[1] : event.arguments[0], + metadata, + runStepName, + }); +} + +function startActionSpan( + event: ChannelMessage, +): SpanState | undefined { + const metadata = extractActionSpanMetadata(event.arguments); + if (!metadata) { + return undefined; + } + + return startActionSpanState({ + input: extractActionSpanInput(event.arguments), + metadata, + }); +} + +function startActionSpanState(args: { + input?: unknown; + metadata?: GenkitActionMetadata; + runStepName?: string; +}): SpanState | undefined { + if (!shouldTraceAction(args.metadata, args.runStepName)) { + return undefined; + } + + const span = startSpan({ + name: actionSpanName(args.metadata, args.runStepName), + spanAttributes: { + type: actionSpanType(args.metadata), + }, + }); + const startTime = getCurrentUnixTimestamp(); + + span.log({ + input: args.input, + metadata: actionMetadataForLog(args.metadata, args.runStepName), + }); + return { span, startTime }; +} + +function ensureActionSpanState( + states: WeakMap, + event: object, + create: () => SpanState | undefined, +): SpanState | undefined { + const existing = states.get(event); + if (existing) { + return existing; + } + + const created = create(); + if (created) { + states.set(event, created); + } + return created; +} + +function bindActionCurrentSpanStoreToStart< + TChannel extends + | typeof genkitChannels.actionRun + | typeof genkitCoreChannels.actionSpan, +>( + tracingChannel: IsoTracingChannel>, + states: WeakMap, + create: (event: ChannelMessage) => SpanState | undefined, +): (() => void) | undefined { + const state = _internalGetGlobalState(); + const contextManager = state?.contextManager; + const startChannel = tracingChannel.start as + | ({ + bindStore?: ( + store: CurrentSpanStore, + callback: (event: ChannelMessage) => unknown, + ) => void; + unbindStore?: (store: CurrentSpanStore) => void; + } & object) + | undefined; + const currentSpanStore = contextManager + ? ( + contextManager as { + [BRAINTRUST_CURRENT_SPAN_STORE]?: CurrentSpanStore; + } + )[BRAINTRUST_CURRENT_SPAN_STORE] + : undefined; + + if (!startChannel?.bindStore || !currentSpanStore) { + return undefined; + } + + startChannel.bindStore(currentSpanStore, (event) => { + const state = ensureActionSpanState(states, event as object, () => + create(event), + ); + return state + ? contextManager!.wrapSpanForStore(state.span) + : currentSpanStore.getStore(); + }); + + return () => { + startChannel.unbindStore?.(currentSpanStore); + }; +} + function normalizeInput(input: GenkitGenerateInput): GenkitGenerateInput { if (typeof input === "string" || Array.isArray(input)) { return { prompt: input }; @@ -402,6 +571,63 @@ function extractActionMetadata( return self.__action as GenkitActionMetadata; } +function extractActionSpanMetadata( + args: unknown[], +): GenkitActionMetadata | undefined { + const options = extractRunInNewSpanOptions(args); + const labels = isObject(options?.labels) + ? (options.labels as Record) + : undefined; + const metadata = isObject(options?.metadata) + ? (options.metadata as Record) + : undefined; + const actionType = stringValue(labels?.["genkit:metadata:subtype"]); + const name = stringValue(metadata?.name); + + if (!actionType || !name) { + return undefined; + } + + return { + actionType, + key: stringValue(labels?.["genkit:key"]), + name, + }; +} + +function extractActionSpanInput(args: unknown[]): unknown { + const options = extractRunInNewSpanOptions(args); + if (!isObject(options?.metadata)) { + return undefined; + } + return options.metadata.input; +} + +function extractRunInNewSpanOptions( + args: unknown[], +): Record | undefined { + const options = args.length === 3 ? args[1] : args[0]; + return isObject(options) ? (options as Record) : undefined; +} + +function shouldTraceAction( + metadata: GenkitActionMetadata | undefined, + runStepName?: string, +): boolean { + if (runStepName) { + return true; + } + + switch (metadata?.actionType) { + case "model": + case "background-model": + case "embedder": + return false; + default: + return Boolean(metadata); + } +} + function actionSpanName( metadata: GenkitActionMetadata | undefined, runStepName?: string, @@ -514,3 +740,7 @@ function isAsyncIterableLike(value: unknown): value is AsyncIterable { function errorMessage(error: unknown): string { return error instanceof Error ? error.message : String(error); } + +function stringValue(value: unknown): string | undefined { + return typeof value === "string" ? value : undefined; +}