{"version":3,"file":"telemetry-agent-runner.mjs","names":[],"sources":["../../../src/lib/runtime/telemetry-agent-runner.ts"],"sourcesContent":["/**\n * TelemetryAgentRunner - A wrapper around AgentRunner that adds telemetry\n * for agent execution streams.\n *\n * This captures the following telemetry events:\n * - oss.runtime.agent_execution_stream_started - when an agent execution starts\n * - oss.runtime.agent_execution_stream_ended - when an agent execution completes\n * - oss.runtime.agent_execution_stream_errored - when an agent execution fails\n */\n\nimport { type AgentRunner, InMemoryAgentRunner } from \"../../v2/runtime\";\nimport { createHash } from \"node:crypto\";\nimport { tap, catchError, finalize } from \"rxjs\";\nimport telemetry from \"../telemetry-client\";\nimport type { AgentExecutionResponseInfo } from \"@copilotkit/shared/src/telemetry/events\";\n\n/**\n * Configuration options for TelemetryAgentRunner\n */\nexport interface TelemetryAgentRunnerConfig {\n  /**\n   * The underlying runner to delegate to\n   * If not provided, defaults to InMemoryAgentRunner\n   */\n  runner?: AgentRunner;\n\n  /**\n   * Optional LangSmith API key (will be hashed for telemetry)\n   */\n  langsmithApiKey?: string;\n}\n\n/**\n * An AgentRunner wrapper that adds telemetry tracking for agent executions.\n *\n * Usage:\n * ```ts\n * const runtime = new CopilotRuntime({\n *   runner: new TelemetryAgentRunner(),\n *   // or with custom runner:\n *   runner: new TelemetryAgentRunner({ runner: customRunner }),\n * });\n * ```\n */\nexport class TelemetryAgentRunner implements AgentRunner {\n  private readonly _runner: AgentRunner;\n  private readonly hashedLgcKey: string | undefined;\n\n  constructor(config?: TelemetryAgentRunnerConfig) {\n    this._runner = config?.runner ?? new InMemoryAgentRunner();\n    this.hashedLgcKey = config?.langsmithApiKey\n      ? createHash(\"sha256\").update(config.langsmithApiKey).digest(\"hex\")\n      : undefined;\n  }\n\n  /**\n   * Runs an agent with telemetry tracking.\n   * Wraps the underlying runner's Observable stream with telemetry events.\n   */\n  run(...args: Parameters<AgentRunner[\"run\"]>): ReturnType<AgentRunner[\"run\"]> {\n    const streamInfo: AgentExecutionResponseInfo = {\n      hashedLgcKey: this.hashedLgcKey,\n    };\n    let streamErrored = false;\n\n    // Capture stream started event\n    telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {\n      hashedLgcKey: this.hashedLgcKey,\n    });\n\n    // Delegate to the underlying runner and wrap with telemetry\n    return this._runner.run(...args).pipe(\n      // Extract metadata from events if available\n      tap((event) => {\n        // Try to extract provider/model info from raw events\n        const rawEvent = (\n          event as {\n            rawEvent?: {\n              metadata?: Record<string, unknown>;\n              data?: Record<string, unknown>;\n            };\n          }\n        ).rawEvent;\n        if (rawEvent?.data) {\n          const data = rawEvent.data as { output?: { model?: string } };\n          if (data?.output?.model) {\n            streamInfo.model = data.output.model;\n            streamInfo.provider = data.output.model;\n          }\n        }\n        if (rawEvent?.metadata) {\n          const metadata = rawEvent.metadata as {\n            langgraph_host?: string;\n            langgraph_version?: string;\n          };\n          if (metadata?.langgraph_host) {\n            streamInfo.langGraphHost = metadata.langgraph_host;\n          }\n          if (metadata?.langgraph_version) {\n            streamInfo.langGraphVersion = metadata.langgraph_version;\n          }\n        }\n      }),\n      catchError((error) => {\n        // Capture stream error event\n        streamErrored = true;\n        telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n          ...streamInfo,\n          error: error instanceof Error ? error.message : String(error),\n        });\n        throw error;\n      }),\n      finalize(() => {\n        // Capture stream ended event (only if not errored)\n        if (!streamErrored) {\n          telemetry.capture(\n            \"oss.runtime.agent_execution_stream_ended\",\n            streamInfo,\n          );\n        }\n      }),\n    );\n  }\n\n  /**\n   * Delegates to the underlying runner's connect method\n   */\n  connect(\n    ...args: Parameters<AgentRunner[\"connect\"]>\n  ): ReturnType<AgentRunner[\"connect\"]> {\n    return this._runner.connect(...args);\n  }\n\n  /**\n   * Delegates to the underlying runner's isRunning method\n   */\n  isRunning(\n    ...args: Parameters<AgentRunner[\"isRunning\"]>\n  ): ReturnType<AgentRunner[\"isRunning\"]> {\n    return this._runner.isRunning(...args);\n  }\n\n  /**\n   * Delegates to the underlying runner's stop method\n   */\n  stop(\n    ...args: Parameters<AgentRunner[\"stop\"]>\n  ): ReturnType<AgentRunner[\"stop\"]> {\n    return this._runner.stop(...args);\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,IAAa,uBAAb,MAAyD;CAIvD,YAAY,QAAqC;AAC/C,OAAK,UAAU,QAAQ,UAAU,IAAI,qBAAqB;AAC1D,OAAK,eAAe,QAAQ,kBACxB,WAAW,SAAS,CAAC,OAAO,OAAO,gBAAgB,CAAC,OAAO,MAAM,GACjE;;;;;;CAON,IAAI,GAAG,MAAsE;EAC3E,MAAM,aAAyC,EAC7C,cAAc,KAAK,cACpB;EACD,IAAI,gBAAgB;AAGpB,kBAAU,QAAQ,8CAA8C,EAC9D,cAAc,KAAK,cACpB,CAAC;AAGF,SAAO,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC,KAE/B,KAAK,UAAU;GAEb,MAAM,WACJ,MAMA;AACF,OAAI,UAAU,MAAM;IAClB,MAAM,OAAO,SAAS;AACtB,QAAI,MAAM,QAAQ,OAAO;AACvB,gBAAW,QAAQ,KAAK,OAAO;AAC/B,gBAAW,WAAW,KAAK,OAAO;;;AAGtC,OAAI,UAAU,UAAU;IACtB,MAAM,WAAW,SAAS;AAI1B,QAAI,UAAU,eACZ,YAAW,gBAAgB,SAAS;AAEtC,QAAI,UAAU,kBACZ,YAAW,mBAAmB,SAAS;;IAG3C,EACF,YAAY,UAAU;AAEpB,mBAAgB;AAChB,mBAAU,QAAQ,8CAA8C;IAC9D,GAAG;IACH,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D,CAAC;AACF,SAAM;IACN,EACF,eAAe;AAEb,OAAI,CAAC,cACH,iBAAU,QACR,4CACA,WACD;IAEH,CACH;;;;;CAMH,QACE,GAAG,MACiC;AACpC,SAAO,KAAK,QAAQ,QAAQ,GAAG,KAAK;;;;;CAMtC,UACE,GAAG,MACmC;AACtC,SAAO,KAAK,QAAQ,UAAU,GAAG,KAAK;;;;;CAMxC,KACE,GAAG,MAC8B;AACjC,SAAO,KAAK,QAAQ,KAAK,GAAG,KAAK"}