mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
* fix(llms): limit Langfuse telemetry to Cline provider Refs ENG-2505 * fix(llms): include ClinePass in Langfuse telemetry Refs ENG-2505 * feat(llms): sampled cline-provider AI SDK tracing via the host OTLP exporter Enables the collector-relay tracing path: when the host telemetry service has registered an OTLP tracer provider, cline-provider streams can emit AI SDK spans without Langfuse credentials in the process. - CLINE_TRACE_SAMPLE_PERCENT (default 0 = off) gates emission; sampling is a deterministic FNV-1a hash of the task/session id, so whole tasks sample together and retries decide identically. - Metadata-only by default (recordInputs/recordOutputs false): models, tokens, timings, errors — no prompt or completion content. Content requires CLINE_TRACE_RECORD_CONTENT=true explicitly. - The direct Langfuse path (env credentials, hub/internal) is unchanged: full content, every request, provider-gated as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(telemetry): client OTLP trace pipeline for cline-provider AI SDK spans Extension side of the Langfuse collector relay: - OpenTelemetryClientProvider gains a TracerProvider: when tracesExporter is configured, spans batch-export over OTLP (grpc / http/json / http/protobuf) to the same collector endpoint as logs/metrics. register() also installs the async context manager span parenting needs. - tracesExporter plumbed through all three config sources: build constants (OTEL_TRACES_EXPORTER), runtime env (CLINE_OTEL_TRACES_EXPORTER), and remote config (openTelemetryTracesExporter) — the last is the no-release kill switch. - SDK: a host that registers a traces exporter now defaults to 100% task sampling; CLINE_TRACE_SAMPLE_PERCENT reduces it (0 disables). Env reads are literal so build-time inlining works. Metadata-only stays the default; content still requires CLINE_TRACE_RECORD_CONTENT=true. - CLI build inlines the new envs alongside the existing OTEL set. No publish workflow sets OTEL_TRACES_EXPORTER yet, so shipped builds keep tracing dark — activation is a separate one-line-per-workflow PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(llms): honor the global telemetry opt-out on the trace relay path AI SDK spans bypass the ITelemetryService wrapper that enforces the user's opt-out for events and metrics, so an opted-out user's prompts would still have traced once a host registered an OTLP exporter. resolveAiSdkTelemetry now re-checks the shared global settings file (telemetryOptOut) per stream — covering startup state and mid-session opt-outs across extension and CLI. The credentialed direct Langfuse path is unchanged: it only activates on explicit operator config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: biome format Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(llms): one trace export path per host — direct Langfuse declines when an OTLP tracer is registered Enablement is a per-stream boolean but export fan-out is processor-level: attaching the direct LangfuseSpanProcessor to a host-registered tracer provider ships every span twice (direct + collector relay). The direct path now declines instead of cooperating when a recording provider already owns the global slot; it only exports when it registers its own provider. A host therefore configures exactly one of LANGFUSE_* credentials or an OTLP traces exporter, and misconfiguring both is safe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat(hub): daemon-distinct trace identity for Langfuse hub coverage (#14034) The detached hub daemon already has everything needed to emit AI SDK traces: it ships in the same compiled binary as the CLI (so the publish build's OTEL_TRACES_EXPORTER / CLINE_TRACE_RECORD_CONTENT inlining reaches it), its telemetry handle flows into the hub server and the scheduled-run handlers, core's OpenTelemetryProvider registers a global tracer when the exporter is configured, and shutdown already flushes with a hard deadline. What was missing is identity: spans carry only the OTel resource, not per-event metadata, so daemon-emitted traces were indistinguishable from CLI-local ones (both service.name=cline). The daemon now declares serviceName=cline-hub-daemon (+ serviceVersion), via new optional serviceName/serviceVersion fields on the shared OpenTelemetryClientConfig. Opt-out holds for the daemon unchanged: it is a same-machine, same-user process, so the shared global settings file the per-stream gate reads is the requesting user's own (shared/cloud topologies tracked in ENG-2525). Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * fix(llms): fail closed when the telemetry opt-out cannot be verified The relay's opt-out guard treated every settings read failure as 'no opt-out recorded', so a corrupted or unreadable settings file (including a torn read of the non-atomic writer) silently re-enabled tracing for a user who had opted out. Only a genuinely absent file (ENOENT, first run) now reads as opted in; malformed JSON and every other read failure disable the relay — consent that cannot be verified is not consent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(llms): identify the OTLP relay explicitly instead of inferring it from any recording tracer 'Some recording tracer exists' misclassified console-only tracing as the collector relay (enabling the relay decision) and — for mutable providers — newly suppressed the direct Langfuse attach that worked before the one-path guard. The hosts that build tracer providers now stamp a relay marker only when a real OTLP span processor was created (console-only providers stay unmarked), and the trace decisions key off that marker: - relay path enables only behind a marked provider; - the one-path decline fires only for marked providers — unmarked mutable providers keep the original cooperative attach behavior; - a relay decline is no longer cached, so direct Langfuse gets to retry once a relay is disposed. The marker lives on the provider instance (reached through the OTel API global), which survives bundled module duplication where a module-level registry would not. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * style: organize imports Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(telemetry): own and dispose remote trace clients across config updates * fix(llms): wire per-call Langfuse telemetry and isolate direct export * refactor(telemetry): reject unsupported providers before initialization * test(desktop): raise sidecar vitest timeout above the module-graph import cost The first test in each sidecar file pays the @cline/core → @cline/llms import cost, which lands within ~100ms of the 5s default on CI runners (commands-account failed at 5009ms; context.test.ts passed at 4923ms). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: abeatrix <beatrix@cline.bot>