Merge branch 'worktree/deps-20261007-telemetry' into worktree/deps-20261007-actions-final

This commit is contained in:
Tianyi Cui committed 2026-10-07 23:27:17 +08:00
commit 5d41a61cfd
18 files changed
+84 -49

No files matched your search

+6 -4
View File
@@ -2830,8 +2830,8 @@ export interface Config {
## `@deepseek-ai/dsh-session-telemetry-otel`
- `inject`: `sessions` · `otel`
- `refs`: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`)
- `source`: [`packages/session/session-telemetry-otel/src/index.ts:87`](../packages/session/session-telemetry-otel/src/index.ts)
- `refs`: [`LogExporterOptions`](../packages/telemetry/otel/src/index.ts) · [`SessionLogProcessorOptions`](../packages/telemetry/otel/src/index.ts)
- `source`: [`packages/session/session-telemetry-otel/src/index.ts:85`](../packages/session/session-telemetry-otel/src/index.ts)
```ts config-catalog
/**
@@ -2845,16 +2845,18 @@ export interface Config {
/**
* Explicit SDK HTTP transport settings, including optional routing headers.
* Ambient credentials are not inherited. URL is required while uploading.
* Exporter self-observability metering is not supported.
*/
exporter?: OTLPExporterNodeConfigBase & {
exporter?: Omit<LogExporterOptions, 'url'> & {
/** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */
url?: string
}
/**
* Count, queue, cadence, and per-request watchdog settings for the byte-bounded
* processor. A watchdog warning never releases an unsettled transport slot.
* SDK processor self-observability metering is not supported.
*/
processor?: Omit<BatchLogRecordProcessorOptions, 'exporter'>
processor?: SessionLogProcessorOptions
/** Maximum time spent awaiting the SDK provider's complete shutdown path. */
shutdownTimeoutMillis?: number
/** Uncompressed OTLP request byte limit, at most 4,000,000. */
+6 -4
View File
@@ -2832,8 +2832,8 @@ export interface Config {
## `@deepseek-ai/dsh-session-telemetry-otel`
- `inject`: `sessions` · `otel`
- `refs`: `BatchLogRecordProcessorOptions` (`@opentelemetry/sdk-logs`) · `OTLPExporterNodeConfigBase` (`@opentelemetry/otlp-exporter-base`)
- `source`: [`packages/session/session-telemetry-otel/src/index.ts:87`](../packages/session/session-telemetry-otel/src/index.ts)
- `refs`: [`LogExporterOptions`](../packages/telemetry/otel/src/index.ts) · [`SessionLogProcessorOptions`](../packages/telemetry/otel/src/index.ts)
- `source`: [`packages/session/session-telemetry-otel/src/index.ts:85`](../packages/session/session-telemetry-otel/src/index.ts)
```ts config-catalog
/**
@@ -2847,16 +2847,18 @@ export interface Config {
/**
* Explicit SDK HTTP transport settings, including optional routing headers.
* Ambient credentials are not inherited. URL is required while uploading.
* Exporter self-observability metering is not supported.
*/
exporter?: OTLPExporterNodeConfigBase & {
exporter?: Omit<LogExporterOptions, 'url'> & {
/** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */
url?: string
}
/**
* Count, queue, cadence, and per-request watchdog settings for the byte-bounded
* processor. A watchdog warning never releases an unsettled transport slot.
* SDK processor self-observability metering is not supported.
*/
processor?: Omit<BatchLogRecordProcessorOptions, 'exporter'>
processor?: SessionLogProcessorOptions
/** Maximum time spent awaiting the SDK provider's complete shutdown path. */
shutdownTimeoutMillis?: number
/** Uncompressed OTLP request byte limit, at most 4,000,000. */
@@ -5334,7 +5334,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'EventLogOptions',
declaration: 'export interface EventLogOptions {\n exporter: SessionLogOptions[\'exporter\'];\n resourceAttributes: Attributes;\n scope: {\n name: string;\n version?: string;\n };\n processor: Omit<BatchLogRecordProcessorOptions, \'exporter\'>;\n onFailure: SessionLogOptions[\'onFailure\'];\n}',
declaration: 'export interface EventLogOptions {\n exporter: LogExporterOptions;\n resourceAttributes: Attributes;\n scope: {\n name: string;\n version?: string;\n };\n processor: Omit<BatchLogRecordProcessorOptions, \'exporter\'>;\n onFailure: SessionLogOptions[\'onFailure\'];\n}',
},
{
name: 'EventLogReporter',
@@ -5844,6 +5844,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [
name: 'LocalizedText',
declaration: 'export type LocalizedText = string | {\n readonly en: string;\n readonly [locale: string]: string;\n};',
},
{
name: 'LogExporterOptions',
declaration: 'export type LogExporterOptions = Omit<OTLPExporterNodeConfigBase, \'selfObsMeterProvider\'> & {\n url: string;\n};',
},
{
name: 'LspHover',
declaration: 'export interface LspHover {\n readonly contents: string;\n readonly range?: LspRange;\n}',
@@ -6950,7 +6954,11 @@ export const TYPE_API: readonly TypeApiEntry[] = [
},
{
name: 'SessionLogOptions',
declaration: 'export interface SessionLogOptions {\n exporter: OTLPExporterNodeConfigBase & {\n url: string;\n };\n processor?: Omit<BatchLogRecordProcessorOptions, \'exporter\'>;\n maxRequestBytes?: number;\n scope: {\n name: string;\n version?: string;\n };\n resourceAttributes: Attributes;\n onFailure: (message: string, error?: Error) => void;\n}',
declaration: 'export interface SessionLogOptions {\n exporter: LogExporterOptions;\n processor?: SessionLogProcessorOptions;\n maxRequestBytes?: number;\n scope: {\n name: string;\n version?: string;\n };\n resourceAttributes: Attributes;\n onFailure: (message: string, error?: Error) => void;\n}',
},
{
name: 'SessionLogProcessorOptions',
declaration: 'export type SessionLogProcessorOptions = Omit<BatchLogRecordProcessorOptions, \'exporter\' | \'selfObsMeterProvider\'>;',
},
{
name: 'SessionLogRecord',
@@ -54,8 +54,8 @@
en: 7593cf5d0d2cedd6
zh: f57cc48a1b5cbfa9
/deepseek-ai-dsh-session-telemetry-otel/known-limitations-and-deferred-work:
en: e43087aea7af4c9e
zh: f8b529e2012b4c63
en: 5d0b88f8256bd782
zh: 36b8d64645ed6c2e
/deepseek-ai-dsh-session-telemetry-otel/known-limitations-and-deferred-work/dev-note:
en: e67f633dc6fe7773
zh: 3bb0c20c93f16f98
@@ -137,7 +137,7 @@ None; the package neither assembles nor sends a provider request.
These limits define where SDK behavior governs and where export guarantees end. They are current package constraints.
- **Upstream experimental tree** — `@opentelemetry/sdk-logs` is published from the upstream experimental tree; SDK API churn lands here and only here, while the seam contract does not move.
- **Upstream experimental tree** — `@opentelemetry/sdk-logs` is published from the upstream experimental tree; SDK API churn lands in the [shared OTel plugin](../../telemetry/otel/README.md), while the seam contract does not move.
- **Live-collector behavior belongs to the SDK exporter** — authentication, TLS, throttling, and other real OTLP deployment behavior follow the upstream SDK rather than a package-owned compatibility layer.
- **Best-effort handoff** — new cold snapshots and a new feedback submission after restart can repeat prefixes; receivers deduplicate by Session id, format version, and event seq. There is no durable outbox, delivery watermark, automatic retry promise, or collector-acceptance guarantee. OTel and the opt-in DeepSeek API path can overlap. Withdrawal exports a deletion event, not remote erasure.
@@ -137,7 +137,7 @@ kind: "package-reference"
这些限制说明 SDK 行为在何处起主导作用、导出保证止于何处。它们是当前包约束。
- **上游实验性源码树**——`@opentelemetry/sdk-logs` 从上游实验性源码树发布;SDK API 的变动只会落在本包,也仅落在本包,而 seam 约定不动。
- **上游实验性源码树**——`@opentelemetry/sdk-logs` 从上游实验性源码树发布;SDK API 的变动落在[共享 OTel 插件](../../telemetry/otel/README.zh.md),而 seam 约定不动。
- **真实 collector 行为属于 SDK 导出器**——身份验证、TLS、限流及其他真实 OTLP 部署行为遵循上游 SDK,不由本包自有兼容层处理。
- **尽力交接**——新冷快照以及重启后的新反馈提交可能重复前缀;接收方按 Session id、格式版本和事件 seq 去重。没有持久化 outbox、投递水位、自动重试承诺或采集端接受保证。OTel 与需显式启用的 DeepSeek API 路径可能重叠。撤回导出删除事件,不是远端擦除。
@@ -28,8 +28,6 @@
"license": "MIT",
"dependencies": {
"@opentelemetry/api-logs": "^0.222.0",
"@opentelemetry/otlp-exporter-base": "^0.222.0",
"@opentelemetry/sdk-logs": "^0.222.0",
"@deepseek-ai/schemastery": "workspace:~"
},
"peerDependencies": {
@@ -24,9 +24,7 @@ import {
} from '@deepseek-ai/dsh-session-telemetry'
import { APP_IDENTITY } from '@deepseek-ai/dsh-llm'
import { getOrCreateAnonymousUserId } from '@deepseek-ai/dsh-anonymous-user-id'
import type { SessionLogReporter } from '@deepseek-ai/dsh-otel'
import type { BatchLogRecordProcessorOptions } from '@opentelemetry/sdk-logs'
import type { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'
import type { LogExporterOptions, SessionLogProcessorOptions, SessionLogReporter } from '@deepseek-ai/dsh-otel'
import { SeverityNumber } from '@opentelemetry/api-logs'
/** Session-sharing policy selected by {@link Config.mode}. */
@@ -90,16 +88,18 @@ export interface Config {
/**
* Explicit SDK HTTP transport settings, including optional routing headers.
* Ambient credentials are not inherited. URL is required while uploading.
* Exporter self-observability metering is not supported.
*/
exporter?: OTLPExporterNodeConfigBase & {
exporter?: Omit<LogExporterOptions, 'url'> & {
/** Full logs endpoint (e.g. `https://collector.example.com/v1/logs`). Required outside `DISABLED`; validated at load. */
url?: string
}
/**
* Count, queue, cadence, and per-request watchdog settings for the byte-bounded
* processor. A watchdog warning never releases an unsettled transport slot.
* SDK processor self-observability metering is not supported.
*/
processor?: Omit<BatchLogRecordProcessorOptions, 'exporter'>
processor?: SessionLogProcessorOptions
/** Maximum time spent awaiting the SDK provider's complete shutdown path. */
shutdownTimeoutMillis?: number
/** Uncompressed OTLP request byte limit, at most 4,000,000. */
@@ -110,7 +110,8 @@ export interface Config {
* Schemastery validator for {@link Config}; cordis runs it before the plugin
* starts. The constructor validates endpoint and shutdown requirements; the
* reporter validates Session byte and queue limits. SDK transport and
* processor settings retain their upstream types.
* processor settings use the reporter's accepted option types, which exclude
* self-observability metering.
*/
export const Config: z<Config> = z.object({
mode: z.union(Object.values(SessionTelemetryMode)).default(DEFAULT_TELEMETRY_MODE),
+2 -2
View File
@@ -18,8 +18,8 @@
en: f141a9d909c555d8
zh: e4f5b690ccb1337c
/deepseek-ai-dsh-otel/understand-the-implementation:
en: d1b6f8f2b25ea252
zh: 73d6147bae811ce0
en: db3709ac9594b0de
zh: 8e5c84967d1eafbb
/deepseek-ai-dsh-otel/further-exploration:
en: ee17b991de098cc0
zh: f90257e411921f2b
+1 -1
View File
@@ -34,7 +34,7 @@ Headers are explicit. The service does not add a channel header or inherit ambie
<a id="understand-the-implementation"></a>
## Understand the implementation
`src/index.ts` registers the service; `event-log.ts` owns ordinary SDK batching; `session-log.ts` owns byte/count scheduling; `transport.ts` supplies the Session SDK JSON HTTP delegate; `event-transport.ts` uses Got for cancellable ordinary-event HTTP requests and retry waits with SDK serialization and export accounting. No global OTel provider is installed. The Session processor measures each record once, groups conservative sizes, and waits for the SDK concurrency queue to clear after every callback before sending another request.
`src/index.ts` registers the service; `event-log.ts` owns ordinary SDK batching; `session-log.ts` owns byte/count scheduling; `transport.ts` supplies the Session SDK JSON HTTP delegate and owns the shared exporter metrics recorder, which receives no meter provider and records nothing; `event-transport.ts` uses Got for cancellable ordinary-event HTTP requests and retry waits with SDK serialization and export accounting. No global OTel provider is installed; the accepted exporter options exclude the upstream `selfObsMeterProvider`, and the Session processor accepts only the batching fields it implements, so exporter and Session-processor self-observability metrics stay unrecorded. The Session processor measures each record once, groups conservative sizes, and waits for the SDK concurrency queue to clear after every callback before sending another request.
Composition tests exercise independent channels and service removal; adapter tests cover dependent-fiber cleanup and feedback authorization.
+1 -1
View File
@@ -34,7 +34,7 @@ Header 显式提供。服务不会附加 channel header,也不继承环境中
<a id="understand-the-implementation"></a>
## 理解实现
`src/index.ts` 注册服务;`event-log.ts` 负责普通事件的 SDK 聚合;`session-log.ts` 负责字节和条数调度;`transport.ts` 提供 Session 的 SDK JSON HTTP delegate;`event-transport.ts` 使用 Got 实现可取消的普通事件 HTTP 请求和重试等待,序列化与导出计数仍由 SDK 负责。不安装全局 OTel provider。Session processor 对每条记录只计量一次,按保守大小组包,并在每次回调后等待 SDK 并发队列清理完成才发送下一请求。
`src/index.ts` 注册服务;`event-log.ts` 负责普通事件的 SDK 聚合;`session-log.ts` 负责字节和条数调度;`transport.ts` 提供 Session 的 SDK JSON HTTP delegate,并持有共享的 exporter 指标记录器(不接收 meter provider,不记录任何指标);`event-transport.ts` 使用 Got 实现可取消的普通事件 HTTP 请求和重试等待,序列化与导出计数仍由 SDK 负责。不安装全局 OTel provider;接受的 exporter 选项排除上游的 `selfObsMeterProvider`,Session processor 也只接受它实现的聚合字段,因此 exporter 和 Session processor 的自观测指标都不会被记录。Session processor 对每条记录只计量一次,按保守大小组包,并在每次回调后等待 SDK 并发队列清理完成才发送下一请求。
组合测试覆盖独立通道和服务移除;适配器测试覆盖依赖 fiber 清理与反馈授权。
+2 -1
View File
@@ -8,6 +8,7 @@ import { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs
import type { BatchLogRecordProcessorOptions, LogRecordExporter } from '@opentelemetry/sdk-logs'
import type { SessionLogOptions } from './session-log.ts'
import { createEventLogExporter } from './event-transport.ts'
import type { LogExporterOptions } from './transport.ts'
/** Scalar values accepted by the collector's Arrow attributes map. */
export type OTelEventScalar = string | number | boolean
@@ -28,7 +29,7 @@ export interface OTelEventRecord {
/** Ordinary-event transport, resource, scope, and count-batching options. */
export interface EventLogOptions {
exporter: SessionLogOptions['exporter']
exporter: LogExporterOptions
resourceAttributes: Attributes
scope: { name: string; version?: string }
processor: Omit<BatchLogRecordProcessorOptions, 'exporter'>
@@ -2,10 +2,10 @@
import type { Agent as HttpsAgent } from 'node:https'
import { gzipSync } from 'node:zlib'
import got from 'got'
import { createOtlpNetworkExportDelegate, OTLPExporterBase, type OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'
import { createOtlpNetworkExportDelegate, OTLPExporterBase } from '@opentelemetry/otlp-exporter-base'
import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer'
import type { LogRecordExporter } from '@opentelemetry/sdk-logs'
import { createLogExporterMetrics, logTransportOptions } from './transport.ts'
import { createLogExporterMetrics, type LogExporterOptions, logTransportOptions } from './transport.ts'
/**
* Create a channel-owned exporter whose cancellation releases requests and retry timers.
@@ -13,7 +13,7 @@ import { createLogExporterMetrics, logTransportOptions } from './transport.ts'
* @param signal - channel cancellation, shared by current and future batch exports.
* @returns the SDK exporter; shutdown also destroys its owned HTTP agent.
*/
export function createEventLogExporter(options: OTLPExporterNodeConfigBase & { url: string }, signal: AbortSignal): LogRecordExporter {
export function createEventLogExporter(options: LogExporterOptions, signal: AbortSignal): LogRecordExporter {
const config = logTransportOptions(options)
let agent: ReturnType<typeof config.agentFactory> | undefined
const exporter = new OTLPExporterBase(createOtlpNetworkExportDelegate(config, JsonLogsSerializer, createLogExporterMetrics(config.url), {
+2 -1
View File
@@ -31,4 +31,5 @@ export default class OTel extends Service {
}
export type { EventLogOptions, OTelEventRecord, OTelEventScalar, EventLogReporter } from './event-log.ts'
export type { SessionLogRecord, SessionLogOptions, SessionLogReporter } from './session-log.ts'
export type { SessionLogProcessorOptions, SessionLogRecord, SessionLogOptions, SessionLogReporter } from './session-log.ts'
export type { LogExporterOptions } from './transport.ts'
+13 -9
View File
@@ -3,11 +3,10 @@ import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
import type { Attributes } from '@opentelemetry/api'
import { SeverityNumber } from '@opentelemetry/api-logs'
import { ExportResultCode } from '@opentelemetry/core'
import type { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'
import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer'
import { resourceFromAttributes } from '@opentelemetry/resources'
import { LoggerProvider, type BatchLogRecordProcessorOptions, type LogRecordExporter, type ReadableLogRecord, type LogRecordProcessor } from '@opentelemetry/sdk-logs'
import { createLogExporter } from './transport.ts'
import { createLogExporter, type LogExporterOptions } from './transport.ts'
/** Collector request ceiling in uncompressed UTF-8 bytes, including the OTLP envelope. */
export const SESSION_LOG_MAX_REQUEST_BYTES = 4_000_000
@@ -23,15 +22,20 @@ export interface SessionLogRecord {
severityNumber?: SeverityNumber
}
/**
* Byte and count batching fields implemented by {@link SessionLogProcessor}.
*
* `exporter` belongs to the owning channel, and `selfObsMeterProvider` is
* excluded because this processor implements no self-observability metering.
*/
export type SessionLogProcessorOptions = Omit<BatchLogRecordProcessorOptions, 'exporter' | 'selfObsMeterProvider'>
/** Session-log transport and byte/count queue settings. */
export interface SessionLogOptions {
/** Explicit destination and SDK transport options. */
exporter: OTLPExporterNodeConfigBase & {
/** Full HTTP(S) logs destination. */
url: string
}
/** Explicit destination and SDK transport settings; exporter self-observability metering is not supported. */
exporter: LogExporterOptions
/** Session-only queue settings, independent of product-event aggregation. */
processor?: Omit<BatchLogRecordProcessorOptions, 'exporter'>
processor?: SessionLogProcessorOptions
/** May lower, but never exceed, the collector's 4,000,000-byte limit. */
maxRequestBytes?: number
/** Instrumentation scope supplied by the business owner. */
@@ -76,7 +80,7 @@ class SessionLogProcessor implements LogRecordProcessor {
constructor(
private readonly exporter: LogRecordExporter,
private readonly limit: number,
private readonly config: Required<Pick<BatchLogRecordProcessorOptions, 'maxQueueSize' | 'maxExportBatchSize' | 'scheduledDelayMillis' | 'exportTimeoutMillis'>>,
private readonly config: Required<Pick<SessionLogProcessorOptions, 'maxQueueSize' | 'maxExportBatchSize' | 'scheduledDelayMillis' | 'exportTimeoutMillis'>>,
private readonly warn: SessionLogOptions['onFailure'],
) {}
+13 -2
View File
@@ -7,12 +7,23 @@ import type { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-lo
/** `otel.component.type` reported by OTLP HTTP log exporter self-observability metrics. */
const OTLP_HTTP_LOG_EXPORTER_COMPONENT_TYPE = 'otlp_http_log_exporter'
/**
* Collector and SDK HTTP settings accepted by this package's log exporters.
*
* `OTLPExporterConfigBase.selfObsMeterProvider` is excluded: every channel here
* passes no meter provider to the exporter metrics recorder, which stays noop.
*/
export type LogExporterOptions = Omit<OTLPExporterNodeConfigBase, 'selfObsMeterProvider'> & {
/** Full HTTP(S) logs destination. */
url: string
}
/**
* Create an SDK JSON exporter without inheriting another collector's headers or TLS identity.
* @param options - explicit endpoint, headers, agent, and SDK transport settings.
* @returns the exporter owned by one independent log pipeline.
*/
export function createLogExporter(options: OTLPExporterNodeConfigBase & { url: string }): LogRecordExporter {
export function createLogExporter(options: LogExporterOptions): LogRecordExporter {
return new OTLPExporterBase(createOtlpHttpExportDelegate(
logTransportOptions(options), JsonLogsSerializer, OTLP_HTTP_LOG_EXPORTER_COMPONENT_TYPE, LogsExporterMetricsHelper, undefined))
}
@@ -32,7 +43,7 @@ export function createLogExporterMetrics(url: string): ExporterMetrics<ReadableL
* @returns resolved transport settings without ambient credentials.
*/
export function logTransportOptions(
options: OTLPExporterNodeConfigBase & { url: string },
options: LogExporterOptions,
): Parameters<typeof createOtlpHttpExportDelegate>[0] {
const shared = mergeOtlpSharedConfigurationWithDefaults(options, getSharedConfigurationFromEnvironment('LOGS'), getSharedConfigurationDefaults())
return {
@@ -5,10 +5,23 @@ import { Agent, createServer, type IncomingHttpHeaders } from 'node:http'
import { once } from 'node:events'
import { gunzipSync } from 'node:zlib'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import type { MeterProvider } from '@opentelemetry/api'
import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base'
import { JsonLogsSerializer } from '@opentelemetry/otlp-transformer'
import { SessionId, SessionSeq } from '@deepseek-ai/dsh-session'
import { SESSION_LOG_MAX_REQUEST_BYTES, type SessionLogRecord, type SessionLogOptions } from '../src/session-log.ts'
import { SESSION_LOG_MAX_REQUEST_BYTES, type SessionLogProcessorOptions, type SessionLogRecord, type SessionLogOptions } from '../src/session-log.ts'
import type { LogExporterOptions } from '../src/transport.ts'
/** Type-only probe: accepted channel options exclude SDK self-observability metering. */
function meteringOptionsAreExcluded(url: string, meterProvider: MeterProvider): void {
// @ts-expect-error -- exporter self-observability metering is not accepted.
const exporter: LogExporterOptions = { url, selfObsMeterProvider: meterProvider }
// @ts-expect-error -- this processor implements no self-observability metering.
const processor: SessionLogProcessorOptions = { selfObsMeterProvider: meterProvider }
void exporter
void processor
}
void meteringOptionsAreExcluded
interface Capture {
bytes: number
-6
View File
@@ -12137,12 +12137,6 @@ importers:
'@opentelemetry/api-logs':
specifier: ^0.222.0
version: 0.222.0
'@opentelemetry/otlp-exporter-base':
specifier: ^0.222.0
version: 0.222.0(@opentelemetry/[email protected])
'@opentelemetry/sdk-logs':
specifier: ^0.222.0
version: 0.222.0(@opentelemetry/[email protected])
devDependencies:
'@deepseek-ai/cordis':
specifier: workspace:~