Skip to content

feat(agent-tracing): add @eggjs/agent-tracing package for AI agent tracing#5822

Open
jerryliang64 wants to merge 10 commits intonextfrom
feat/agent-tracing
Open

feat(agent-tracing): add @eggjs/agent-tracing package for AI agent tracing#5822
jerryliang64 wants to merge 10 commits intonextfrom
feat/agent-tracing

Conversation

@jerryliang64
Copy link
Contributor

@jerryliang64 jerryliang64 commented Mar 5, 2026

Summary

  • Add new @eggjs/agent-tracing package for AI agent LLM call tracing
  • Support tracing LangChain-based AI agent invocations with structured span/trace data
  • Replace direct ali-oss dependency with IOssClient IoC injection for better testability
  • Replace logService config with ILogServiceClient IoC injection following DI best practices
  • Rename test files to PascalCase for consistency

Changes

  • packages/agent-tracing/ — New package implementing AI agent tracing
    • LangChain callback handler for capturing LLM traces
    • OSS client interface injection (IOssClient) for uploading trace data
    • Log service client interface injection (ILogServiceClient) for structured logging
    • Vitest-based test suite with PascalCase test file naming

Test plan

  • Unit tests pass with pnpm --filter=@eggjs/agent-tracing run test
  • TypeScript type checking passes
  • Dependencies deduplicated in lockfile

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • New agent-tracing package with Claude and LangGraph tracers, centralized tracing service, OSS/log client interfaces, and public types/configuration surfaces
  • Tests
    • Comprehensive unit tests and test utilities covering tracer behaviors and tracing service
  • Chores
    • Project TypeScript/test configs added and dependency version bumps for langchain/core

jerryliang64 and others added 5 commits March 2, 2026 00:17
…acing

Add tracing support for AI agents built with LangGraph and Claude Agent SDK.

- LangGraphTracer: extends LangChain BaseTracer, hooks into graph lifecycle
- ClaudeAgentTracer: converts Claude SDK messages to LangChain Run format
- TraceSession: streaming support for real-time message processing
- TracingService: shared log formatting, OSS upload, and log service sync
- applyTracerConfig: shared configure() logic for both tracers
- Comprehensive tests for configure, LangGraph integration, and Claude integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… code

- Rename test files to match PascalCase convention
- Remove unused module.yml
- Clean up TracingService and ClaudeAgentTracer code
- Remove unnecessary dependencies from package.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Bump @langchain/core from ^1.1.1 to ^1.1.29 in langchain-decorator,
  langchain plugin, and agent-tracing to fix `this._addVersion is not a
  function` error caused by @langchain/openai@1.2.11 requiring the new
  _addVersion method introduced in @langchain/core@1.1.29
- Run pnpm dedupe to resolve ERR_PNPM_DEDUPE_CHECK_ISSUES in CI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lient injection

Remove hard dependency on ali-oss. TracingService now receives an optional
IOssClient via @InjectOptional(), allowing users to provide any OSS
implementation through the Tegg IoC container.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ient IoC injection

Remove hardcoded HTTP POST logic in syncLocalToLogService and replace with
an abstract ILogServiceClient that users implement and register via Tegg IoC,
consistent with the existing IOssClient injection pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a dedicated tracing package for AI agents, enabling detailed monitoring and debugging of agent interactions. It standardizes how agent execution flows, LLM calls, and tool usage are logged, providing structured data for analysis. The architectural improvements, such as dependency injection for external services, ensure the tracing solution is robust, extensible, and easily testable within the Egg.js ecosystem.

Highlights

  • New AI Agent Tracing Package: Introduced a new package, @eggjs/agent-tracing, to provide comprehensive tracing capabilities for AI agents, specifically supporting LangChain-based invocations and Claude Agent SDK messages.
  • Structured Tracing Data: Implemented mechanisms to capture and log structured span/trace data for agent executions, including root runs, LLM calls, and tool uses, with detailed information on inputs, outputs, and costs.
  • Dependency Injection for Services: Replaced direct dependencies on ali-oss and a generic logService with abstract interfaces (IOssClient and ILogServiceClient) for IoC injection, enhancing testability and adherence to DI best practices.
  • Flexible Tracing Modes: Provided support for both batch processing of agent messages and real-time streaming trace sessions, allowing immediate logging of messages as they arrive.
  • Dependency Updates: Updated various LangChain-related dependencies (@langchain/core, @langchain/langgraph, @langchain/openai, langchain) and other core packages to their latest versions.
Changelog
  • pnpm-lock.yaml
    • Removed axios dependency from vitepress.
    • Added new package tegg/core/agent-tracing with its dependencies and devDependencies.
    • Updated @modelcontextprotocol/sdk to version 1.27.1 across multiple importers.
    • Updated @langchain/core to 1.1.29 and @langchain/langgraph to 1.2.0 for various importers.
    • Updated @langchain/openai to 1.2.11 and langchain to 1.2.28 for various importers.
    • Updated langsmith to 0.5.7.
    • Added new package entries for @anthropic-ai/claude-agent-sdk, @anthropic-ai/sdk, @babel/runtime, and various @img/sharp native modules.
    • Added new package entries for address@1.2.2, agentkeepalive@3.5.3, ali-oss@6.23.0, ansi-styles@5.2.0, bowser@1.9.4, builtin-status-codes@3.0.0, dateformat@2.2.0, end-or-error@1.0.1, get-ready@1.0.0, isarray@1.0.0, js-base64@2.6.4, json-schema-to-ts@3.1.1, jstoxml@2.2.9, p-retry@4.6.2, process-nextick-args@2.0.1, readable-stream@2.3.8, retry@0.13.1, safe-buffer@5.1.2, sdk-base@2.0.1, stream-http@2.8.2, stream-wormhole@1.1.0, string_decoder@1.1.1, to-arraybuffer@1.0.1, ts-algebra@2.0.0, urllib@2.44.0, uuid@11.1.0, uuid@9.0.1, xml2js@0.6.2, xmlbuilder@11.0.1, xtend@4.0.2.
    • Removed axios@1.13.5, follow-redirects@1.15.11, proxy-from-env@1.1.0.
    • Downgraded form-data from 4.0.5 to 4.0.4.
    • Updated hono from 4.11.10 to 4.12.3.
    • Updated is-network-error from 1.3.0 to 1.3.1.
    • Updated openai from 6.22.0 to 6.25.0.
    • Removed ws@8.19.0 as a direct dependency from openai snapshots.
  • tegg/core/agent-tracing/package.json
    • Added new package manifest for @eggjs/agent-tracing.
    • Defined package metadata, dependencies, devDependencies, and peerDependencies for AI agent tracing.
  • tegg/core/agent-tracing/src/ClaudeAgentTracer.ts
    • Added ClaudeAgentTracer class for processing Claude SDK messages into LangChain Run format.
    • Implemented TraceSession for managing streaming agent execution and logging messages.
    • Provided internal methods for creating and completing root, LLM, and tool runs, and extracting token usage.
  • tegg/core/agent-tracing/src/ILogServiceClient.ts
    • Added abstract ILogServiceClient class for dependency injection of log service implementations.
  • tegg/core/agent-tracing/src/IOssClient.ts
    • Added abstract IOssClient class for dependency injection of OSS client implementations.
  • tegg/core/agent-tracing/src/LangGraphTracer.ts
    • Added LangGraphTracer class extending BaseTracer to log LangChain Run events.
  • tegg/core/agent-tracing/src/TracingService.ts
    • Added TracingService class to centralize common tracing operations.
    • Implemented methods for environment detection, log prefix generation, OSS uploads, and syncing local logs to a log service.
    • Handled uploading large fields of Run objects to OSS and logging metadata.
  • tegg/core/agent-tracing/src/claude.ts
    • Exported ClaudeAgentTracer and TraceSession from ClaudeAgentTracer.ts.
  • tegg/core/agent-tracing/src/index.ts
    • Exported core tracing types and services (TracingService, IOssClient, ILogServiceClient).
  • tegg/core/agent-tracing/src/langgraph.ts
    • Exported LangGraphTracer from LangGraphTracer.ts.
  • tegg/core/agent-tracing/src/types.ts
    • Defined Claude SDK message types, content blocks, token usage, and shared tracing interfaces (IResource, IRunCost, ILogRun, RunStatus).
    • Introduced TracerConfig and applyTracerConfig for configuring tracers.
  • tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts
    • Added unit tests for ClaudeAgentTracer covering streaming and batch message processing, tool execution, text-only responses, and error handling.
  • tegg/core/agent-tracing/test/Configure.test.ts
    • Added unit tests for configure methods of TracingService, LangGraphTracer, and ClaudeAgentTracer.
  • tegg/core/agent-tracing/test/LangGraphTracer.test.ts
    • Added unit tests for LangGraphTracer covering chain lifecycle hooks, parent-child run relationships, LLM tracing, error handling, and data completeness.
  • tegg/core/agent-tracing/test/TestUtils.ts
    • Added utility functions for creating mock loggers, background task helpers, OSS clients, log service clients, and tracing services for testing.
  • tegg/core/agent-tracing/tsconfig.json
    • Added TypeScript configuration for the new agent-tracing package, extending the root tsconfig.json.
  • tegg/core/agent-tracing/vitest.config.ts
    • Added Vitest configuration for the new agent-tracing package.
  • tegg/core/langchain-decorator/package.json
    • Updated @langchain/core dependency to ^1.1.29.
  • tegg/plugin/langchain/package.json
    • Updated @langchain/core dependency to ^1.1.29.
  • tsconfig.json
    • Added a project reference to ./tegg/core/agent-tracing.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

Introduces a new @eggjs/agent-tracing package that converts Claude SDK messages and LangGraph tracer events into LangChain-style Run hierarchies, supports streaming and batch modes, uploads large fields to OSS, syncs local logs to a log service, and provides types, interfaces, and tests.

Changes

Cohort / File(s) Summary
Package & config
tegg/core/agent-tracing/package.json, tsconfig.json, tegg/core/agent-tracing/tsconfig.json, tegg/core/agent-tracing/vitest.config.ts
New package metadata, ESM exports, Node engine requirement, TypeScript project reference, and Vitest config for the agent-tracing package.
Core tracing logic
tegg/core/agent-tracing/src/TracingService.ts, tegg/core/agent-tracing/src/ClaudeAgentTracer.ts, tegg/core/agent-tracing/src/LangGraphTracer.ts
TracingService: env-aware logging, OSS uploads, background tasks, log sync; ClaudeAgentTracer: SDK→Run conversion, TraceSession streaming + batch processing; LangGraphTracer: BaseTracer adapter emitting START/END/ERROR events to TracingService.
Interfaces
tegg/core/agent-tracing/src/IOssClient.ts, tegg/core/agent-tracing/src/ILogServiceClient.ts
Abstract client contracts for optional OSS uploads and log-service synchronization (DI-friendly, gracefully no-op when absent).
Types & utilities
tegg/core/agent-tracing/src/types.ts
Claude message models, Run/ILogRun/IRunCost/IResource types, FIELDS_TO_OSS, config interfaces, and applyTracerConfig helper.
Module exports
tegg/core/agent-tracing/src/index.ts, tegg/core/agent-tracing/src/claude.ts, tegg/core/agent-tracing/src/langgraph.ts
Centralized public API re-exports: types, TracingService, IOssClient, ILogServiceClient, plus claude/langgraph entry points.
Tests & test utils
tegg/core/agent-tracing/test/*.test.ts, tegg/core/agent-tracing/test/TestUtils.ts
Extensive unit/integration tests for ClaudeAgentTracer, LangGraphTracer, TracingService, configuration; test utilities for capturing logs and tracing events.
Dependency bumps
tegg/core/langchain-decorator/package.json, tegg/plugin/langchain/package.json
Bumped @langchain/core from ^1.1.1 → ^1.1.29.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant App as Application
    participant CAT as ClaudeAgentTracer
    participant TS as TracingService
    participant OSS as OSS Client
    participant LogSvc as Log Service Client

    User->>App: send Claude message sequence
    App->>CAT: createSession(sessionId)
    App->>CAT: processMessage(sdkMessage)
    CAT->>CAT: convertSDKMessage()
    alt Init message
        CAT->>CAT: handleInit() → create root Run
        CAT->>TS: logTrace(rootRun, START)
    else Assistant (LLM / tool)
        CAT->>CAT: create LLM run (+ tool runs if present)
        CAT->>TS: logTrace(llmRun, START)
        CAT->>TS: logTrace(toolRun, START/END)
    else Tool result
        CAT->>CAT: complete tool run
        CAT->>TS: logTrace(toolRun, END)
    else Final result
        CAT->>CAT: finalize root Run (attach outputs/costs)
        CAT->>TS: logTrace(rootRun, END)
    end

    TS->>TS: filterHiddenData(run)
    alt Field marked for OSS
        TS->>OSS: uploadToOss(key, content)
        OSS-->>TS: success
        TS->>TS: replace field with IResource ref
    end

    alt Local environment
        TS->>LogSvc: syncLocalToLogService(log)
        LogSvc-->>TS: ack
    end

    TS->>TS: emit final log line
Loading
sequenceDiagram
    actor User
    participant App as Application
    participant SG as StateGraph
    participant LGT as LangGraphTracer
    participant TS as TracingService

    User->>App: invoke state graph
    App->>SG: execute graph
    SG->>LGT: onChainStart(chainRun)
    LGT->>TS: logTrace(chainRun, START)
    SG->>SG: execute node
    alt LLM node
        SG->>LGT: onLLMStart(llmRun)
        LGT->>TS: logTrace(llmRun, START)
        SG->>LGT: onLLMEnd(llmRun)
        LGT->>TS: logTrace(llmRun, END)
    else Tool node
        SG->>LGT: onToolStart(toolRun)
        LGT->>TS: logTrace(toolRun, START)
        SG->>LGT: onToolEnd(toolRun)
        LGT->>TS: logTrace(toolRun, END)
    else Error
        SG->>LGT: onChainError(chainRun)
        LGT->>TS: logTrace(chainRun, ERROR)
    end
    SG->>LGT: onChainEnd(chainRun)
    LGT->>TS: logTrace(chainRun, END)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • gxkl
  • fengmk2

Poem

🐇 Hopping through traces with a joyful cheer,
I stitch Claude messages into runs so clear.
Streams and batches, tool calls on the way,
OSS and logs keep the stories at play.
A rabbit’s nod — the traces now appear!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding a new @eggjs/agent-tracing package for AI agent tracing, which is the primary objective reflected throughout the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/agent-tracing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Update lockfile to reflect the current state of tegg/core/agent-tracing/package.json,
fixing CI frozen-lockfile install failure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 5, 2026

Deploying egg-v3 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 822b9b6
Status: ✅  Deploy successful!
Preview URL: https://ab1663d5.egg-v3.pages.dev
Branch Preview URL: https://feat-agent-tracing.egg-v3.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 5, 2026

Deploying egg with  Cloudflare Pages  Cloudflare Pages

Latest commit: 822b9b6
Status: ✅  Deploy successful!
Preview URL: https://467d53ec.egg-cci.pages.dev
Branch Preview URL: https://feat-agent-tracing.egg-cci.pages.dev

View logs

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new package, @eggjs/agent-tracing, to provide tracing capabilities for AI agents, specifically supporting LangChain and the Claude Agent SDK. The implementation follows good design principles by using Dependency Injection for OSS and logging clients, making the system more modular and testable. The code is well-structured and includes a comprehensive set of tests for the new functionality.

My review identifies a critical issue with incorrect timestamping for child runs in the ClaudeAgentTracer, which would lead to inaccurate trace data. I've also included some suggestions to improve type safety and code clarity in a few areas. Overall, this is a solid contribution that adds valuable tracing features.

Note: Security Review did not run due to the size of the PR.

Comment on lines +81 to +88
const llmRun = this.tracer.createLLMRunInternal(
message,
this.rootRunId,
this.traceId,
this.executionOrder++,
this.startTime,
true,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The startTime argument for creating this child run is this.startTime, which corresponds to the start of the entire trace session. This results in incorrect timestamps for all child runs (LLM, tool runs), as they will all share the same initial timestamp. To accurately capture the timing of this event, you should use Date.now() instead. This issue occurs in multiple places within the TraceSession class when creating or completing child runs (e.g., in handleAssistant, handleUser, and handleResult).

Suggested change
const llmRun = this.tracer.createLLMRunInternal(
message,
this.rootRunId,
this.traceId,
this.executionOrder++,
this.startTime,
true,
);
const llmRun = this.tracer.createLLMRunInternal(
message,
this.rootRunId,
this.traceId,
this.executionOrder++,
Date.now(),
true,
);

Comment on lines +95 to +101
const toolRun = this.tracer.createToolRunStartInternal(
block,
this.rootRunId,
this.traceId,
this.executionOrder++,
this.startTime,
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similar to the LLM run, the start_time for this tool run is being set to this.startTime. This should be Date.now() to accurately capture when the tool run started.

Suggested change
const toolRun = this.tracer.createToolRunStartInternal(
block,
this.rootRunId,
this.traceId,
this.executionOrder++,
this.startTime,
);
const toolRun = this.tracer.createToolRunStartInternal(
block,
this.rootRunId,
this.traceId,
this.executionOrder++,
Date.now(),
);

if (block.type === 'tool_result') {
const toolRun = this.pendingToolUses.get(block.tool_use_id);
if (toolRun) {
this.tracer.completeToolRunInternal(toolRun, block, this.startTime);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The end_time for the tool run is being set to this.startTime. It should be Date.now() to reflect when the tool result was processed.

Suggested change
this.tracer.completeToolRunInternal(toolRun, block, this.startTime);
this.tracer.completeToolRunInternal(toolRun, block, Date.now());

// Complete any pending tool runs
for (const [toolUseId, toolRun] of this.pendingToolUses) {
this.tracer.logger.warn(`[ClaudeAgentTracer] Tool run ${toolUseId} did not receive result`);
toolRun.end_time = this.startTime;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The end_time for this pending tool run is being set to this.startTime. It should be Date.now() to accurately reflect that it's ending now due to not receiving a result.

Suggested change
toolRun.end_time = this.startTime;
toolRun.end_time = Date.now();

type: 'assistant',
uuid: msg.uuid,
session_id: msg.session_id,
message: msg.message as any,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The type cast as any for msg.message is unnecessary and weakens type safety. The type of msg.message from SDKAssistantMessage is ClaudeMessageContent, which is compatible with the message property in the ClaudeMessage type. You can remove the cast. This applies to other uses of as any in this function as well, which could be refactored to use type guards for better type safety.

Suggested change
message: msg.message as any,
message: msg.message,

Comment on lines +116 to +137
FIELDS_TO_OSS.forEach((field) => {
if (!runData[field]) {
return;
}
const jsonstr = JSON.stringify(runData[field]);
if (field === 'outputs') {
(runData as any).cost = runData?.outputs?.llmOutput;
}
delete runData[field];
const key = `agents/${name}/${env}/traces/${run.trace_id}/runs/${run.id}/${field}`;
this.backgroundTaskHelper.run(async () => {
try {
await this.uploadToOss(key, jsonstr);
} catch (e) {
this.logger.warn(
`[TraceLogErr] Failed to upload run data to OSS for run_id=${run.id}, field=${field}, error:`,
e,
);
}
});
(runData as any)[field] = { compress: 'none', key } as IResource;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for processing fields to be uploaded to OSS and adding the cost field involves in-place modification of the runData object and uses as any, which can make it difficult to follow and less type-safe. Consider refactoring this to build a new, strongly-typed log object. This would separate the concerns of data transformation and logging, improving readability and maintainability.

@codecov
Copy link

codecov bot commented Mar 5, 2026

Codecov Report

❌ Patch coverage is 91.05263% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.40%. Comparing base (ee3c309) to head (822b9b6).

Files with missing lines Patch % Lines
tegg/core/agent-tracing/src/ClaudeAgentTracer.ts 87.39% 14 Missing and 1 partial ⚠️
tegg/core/agent-tracing/src/TracingService.ts 95.65% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #5822      +/-   ##
==========================================
+ Coverage   85.31%   85.40%   +0.09%     
==========================================
  Files         655      659       +4     
  Lines       12591    12781     +190     
  Branches     1447     1480      +33     
==========================================
+ Hits        10742    10916     +174     
- Misses       1729     1744      +15     
- Partials      120      121       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (7)
tegg/core/agent-tracing/src/types.ts (3)

42-54: Consider replacing any with more specific types or unknown.

ClaudeMessageContent uses any in several places (context_management, container, and the index signature). While these may represent dynamic external SDK data, using any reduces type safety. Consider using unknown or more specific types where possible.

♻️ Proposed refinement
 export interface ClaudeMessageContent {
   id?: string;
   type?: string;
   role?: string;
   content?: ClaudeContentBlock[];
   model?: string;
   usage?: ClaudeTokenUsage;
-  context_management?: any;
+  context_management?: unknown;
   stop_reason?: string;
   stop_sequence?: string;
-  container?: any;
-  [key: string]: any;
+  container?: unknown;
+  [key: string]: unknown;
 }

As per coding guidelines: "Avoid any type; use unknown when type is truly unknown in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/types.ts` around lines 42 - 54, The
ClaudeMessageContent interface uses unsafe any types for context_management,
container, and the index signature; change those to safer types (e.g.,
context_management: unknown, container: unknown) and replace the loose index
signature [key: string]: any with a more specific form such as [key: string]:
unknown or Record<string, unknown> to preserve flexibility while restoring type
safety; update any consuming code to properly narrow these fields (type
guards/casts) where necessary.

166-175: The tracingService.configure({}) call appears to be a no-op.

The applyTracerConfig function always passes an empty object to tracingService.configure({}), which doesn't apply any configuration. If AgentTracingConfig is reserved for future use, consider documenting this or deferring the call until actual config values are available.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/types.ts` around lines 166 - 175, The call
tracingService.configure({}) in applyTracerConfig is a no-op because it always
passes an empty object; update applyTracerConfig to build and pass a proper
AgentTracingConfig derived from the TracerConfig (e.g., include agentName and
any other relevant fields) or only call tracingService.configure when there are
actual config values to apply, and if AgentTracingConfig is intentionally empty,
add a comment explaining it's reserved for future use; reference the
applyTracerConfig function, the tracer.agentName assignment, the
tracingService.configure method, TracerConfig param and AgentTracingConfig type
when making the change.

69-110: Consider replacing any with unknown in ClaudeMessage.

Similar to ClaudeMessageContent, this interface uses any for skills, plugins, permission_denials, and the index signature. These weaken type safety for downstream consumers.

♻️ Proposed refinement
   // System/init message fields
   cwd?: string;
   tools?: string[];
   mcp_servers?: Array<{ name: string; status: string }>;
   model?: string;
   permissionMode?: string;
   slash_commands?: string[];
   apiKeySource?: string;
   claude_code_version?: string;
   output_style?: string;
   agents?: string[];
-  skills?: any[];
-  plugins?: any[];
+  skills?: unknown[];
+  plugins?: unknown[];

   // ...

-  permission_denials?: any[];
+  permission_denials?: unknown[];

   // ...

-  [key: string]: any;
+  [key: string]: unknown;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/types.ts` around lines 69 - 110, The
ClaudeMessage interface uses wide any types (fields skills, plugins,
permission_denials and the index signature), reducing type safety; change those
to unknown (e.g., replace skills: any[] → skills: unknown[]; plugins: any[] →
plugins: unknown[]; permission_denials?: any[] → permission_denials?: unknown[];
and the catch‑all [key: string]: any → [key: string]: unknown) and update any
call sites that relied on implicit any to perform explicit type narrowing or
casts where necessary (search for usages of ClaudeMessage, skills, plugins,
permission_denials, and the index signature to add proper type guards or
asserts).
tegg/core/agent-tracing/vitest.config.ts (1)

1-9: Use a typed intermediate variable for isolatedDeclarations support.

The config should use a typed intermediate variable rather than a direct inline export to support isolatedDeclarations.

♻️ Proposed fix
-import { defineProject } from 'vitest/config';
+import { defineProject, type UserProjectConfigExport } from 'vitest/config';

-export default defineProject({
+const config: UserProjectConfigExport = defineProject({
   test: {
     testTimeout: 15000,
     include: ['test/**/*.test.ts'],
     exclude: ['**/test/fixtures/**', '**/node_modules/**', '**/dist/**'],
   },
 });
+
+export default config;

As per coding guidelines: "Use typed intermediate variables for vitest config exports to support isolatedDeclarations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/vitest.config.ts` around lines 1 - 9, Create a typed
intermediate variable (e.g., const config: UserConfig or ProjectConfig) to hold
the result of defineProject(...) instead of exporting the call inline; import
the corresponding type via "import type { UserConfig } from 'vitest' (or the
appropriate ProjectConfig type from 'vitest/config'), assign the object produced
by defineProject(...) to that typed variable (config) and then export default
config so isolatedDeclarations is supported; update references to defineProject
and the default export accordingly.
tegg/core/agent-tracing/test/LangGraphTracer.test.ts (1)

10-10: Replace fixed 500ms sleeps with deterministic async flushing.

Repeated hard waits increase suite time and still risk timing flakiness. Prefer deterministic completion signals/microtask flushes from the mocked async path.

Also applies to: 58-58, 86-86, 117-117, 164-164, 195-195, 234-234, 265-265, 297-297

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts` at line 10, The test
defines a fixed-delay helper sleep and uses it (sleep(500)) in multiple places
which causes slow/flaky tests; replace those hard waits by removing the sleep
helper and instead awaiting a deterministic async flush or the mocked async
completion signal (e.g., implement and call a flushPromises utility that returns
new Promise(r => setImmediate(r)) or await the tracer/mockedEmitter's completion
Promise), and update each assertion site that currently calls sleep(...) to
await that deterministic flush (reference the sleep constant and the test blocks
in LangGraphTracer.test.ts that call sleep).
tegg/core/agent-tracing/test/TestUtils.ts (1)

21-24: Avoid any in shared test helpers to keep type drift visible.

The current Promise<any> and (x as any) casts in utility code reduce the signal of type regressions across all tracer tests.

♻️ Suggested typed refactor
+type MockBackgroundTaskHelper = {
+  run: <T>(fn: () => Promise<T>) => Promise<T>;
+};
+
-export function createMockBackgroundTaskHelper(): { run: (fn: () => Promise<any>) => Promise<any> } {
+export function createMockBackgroundTaskHelper(): MockBackgroundTaskHelper {
   return {
-    run: async (fn: () => Promise<any>) => fn(),
+    run: async <T>(fn: () => Promise<T>) => fn(),
   };
 }
 
 export function createMockTracingService(logs?: string[]): TracingService {
   const tracingService = new TracingService();
-  (tracingService as any).logger = createMockLogger(logs);
-  (tracingService as any).backgroundTaskHelper = createMockBackgroundTaskHelper();
-  (tracingService as any).ossClient = createMockOssClient();
-  (tracingService as any).logServiceClient = createMockLogServiceClient(logs);
+  const mutableTracingService = tracingService as unknown as {
+    logger: Logger;
+    backgroundTaskHelper: MockBackgroundTaskHelper;
+    ossClient: IOssClient;
+    logServiceClient: ILogServiceClient;
+  };
+  mutableTracingService.logger = createMockLogger(logs);
+  mutableTracingService.backgroundTaskHelper = createMockBackgroundTaskHelper();
+  mutableTracingService.ossClient = createMockOssClient();
+  mutableTracingService.logServiceClient = createMockLogServiceClient(logs);
   return tracingService;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/TestUtils.ts` around lines 21 - 24,
createMockBackgroundTaskHelper currently uses Promise<any> which hides type
regressions; make the helper generic by adding a type parameter (e.g., <T>) and
change the run signature to accept and return Promise<T> so callers preserve
precise types (update the function signature and the returned run method
accordingly, referencing createMockBackgroundTaskHelper and its run property).
tegg/core/agent-tracing/src/ClaudeAgentTracer.ts (1)

261-307: Reduce any casts in message conversion/build paths.

convertSDKMessage and run-build helpers rely on multiple as any casts, which weakens safety exactly where SDK payloads are mapped into tracing schema.

Suggested direction
-        message: msg.message as any,
+        message: msg.message as ClaudeMessage['message'],
@@
-    if (msg.type === 'user' && 'message' in msg && !('isReplay' in msg && (msg as any).isReplay)) {
+    if (msg.type === 'user' && 'message' in msg && !(msg as { isReplay?: boolean }).isReplay) {
@@
-        message: msg.message as any,
-        parent_tool_use_id: (msg as any).parent_tool_use_id,
+        message: msg.message as ClaudeMessage['message'],
+        parent_tool_use_id: (msg as { parent_tool_use_id?: string }).parent_tool_use_id,
@@
-    const outputs: any = {};
+    const outputs: Record<string, unknown> = {};
@@
-    const toolUse = toolUseBlock as any;
+    const toolUse = toolUseBlock as Extract<ClaudeContentBlock, { type: 'tool_use' }>;
As per coding guidelines, "Avoid `any` type; use `unknown` when type is truly unknown in TypeScript".

Also applies to: 366-381, 420-430

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/ClaudeAgentTracer.ts` around lines 261 - 307, The
convertSDKMessage in ClaudeAgentTracer currently uses multiple "as any" casts
(e.g., for message, result, errors, usage, modelUsage); replace these with
proper narrowing: add type-guard functions (e.g., isSDKAssistantMessage,
isSDKUserMessage, isSDKResultMessage) that validate fields on SDKMessage and
narrow message/result/usage/modelUsage to concrete types, use unknown for
initially unknown payloads and only cast after successful guards, and in the
SDKResultMessage branch safely handle errors with
Array.isArray(resultMsg.errors) before joining; update any corresponding
run-build helpers to use the same guards and unknown->narrowing pattern instead
of "as any".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tegg/core/agent-tracing/src/claude.ts`:
- Line 1: Update the ESM export to use a .js extension: change the export
statement that re-exports ClaudeAgentTracer and TraceSession from
'./ClaudeAgentTracer.ts' to import from './ClaudeAgentTracer.js' so the runtime
uses the correct ESM module filename for ClaudeAgentTracer and TraceSession.

In `@tegg/core/agent-tracing/src/ClaudeAgentTracer.ts`:
- Around line 81-118: Child/tool runs are being created with the session-wide
this.startTime causing zero-duration runs; update the places that call
this.tracer.createLLMRunInternal and this.tracer.createToolRunStartInternal (and
the code that logs their START/END via this.tracer.logTrace) to use a fresh
timestamp for each sub-run (e.g., compute a local start/end time like const now
= Date.now() or similar) instead of this.startTime so each child/tool run gets
correct start and end times; apply the same change in the other occurrences
referenced (the additional
createLLMRunInternal/createToolRunStartInternal/logTrace sites).
- Around line 9-18: The local ESM imports in ClaudeAgentTracer.ts are using .ts
extensions which breaks runtime resolution; update the import specifiers to use
.js instead: change the import for TracingService (import type { TracingService
} from './TracingService.ts') to './TracingService.js' and change the grouped
import that brings in ClaudeMessage, ClaudeContentBlock, ClaudeTokenUsage,
IRunCost, RunStatus, TracerConfig, and applyTracerConfig (currently from
'./types.ts') to './types.js' so all local ESM imports use .js extensions.

In `@tegg/core/agent-tracing/src/langgraph.ts`:
- Line 1: The export uses a TypeScript file extension for an ESM import; update
the export statement that re-exports LangGraphTracer (symbol: LangGraphTracer)
to reference the compiled JS module by changing the path from
'./LangGraphTracer.ts' to './LangGraphTracer.js' so runtime ESM imports resolve
correctly.

In `@tegg/core/agent-tracing/src/LangGraphTracer.ts`:
- Around line 6-7: Change the local ESM import specifiers in LangGraphTracer to
use .js extensions instead of .ts; update the import of TracingService (from
'./TracingService.ts') and the import of RunStatus, TracerConfig,
applyTracerConfig (from './types.ts') to reference './TracingService.js' and
'./types.js' respectively so runtime module resolution follows the project's ESM
rules.

In `@tegg/core/agent-tracing/src/TracingService.ts`:
- Around line 8-10: Update the ESM import specifiers in TracingService.ts to use
.js extensions: change imports that reference './ILogServiceClient.ts',
'./IOssClient.ts', and './types.ts' to './ILogServiceClient.js',
'./IOssClient.js', and './types.js' respectively so symbols like
ILogServiceClient, IOssClient, AgentTracingConfig, FIELDS_TO_OSS, IResource, and
RunStatus are imported with valid ESM file extensions.
- Around line 116-137: The code currently deletes runData[field] and replaces it
with an IResource key before the OSS upload completes, causing loss of payloads
when IOssClient is absent or upload fails; change the flow in the loop over
FIELDS_TO_OSS (where runData[field] is read, jsonstr created and uploadToOss is
invoked inside backgroundTaskHelper.run) to keep the original runData[field]
intact until upload succeeds: check whether an OSS client is configured, perform
uploadToOss first (or await the backgroundTaskHelper-run result) and only on
successful upload set (runData as any)[field] = { compress: 'none', key } as
IResource; on upload failure or missing client, leave runData[field] untouched
and log via this.logger.warn (as in the existing catch) so trace payloads are
preserved.

In `@tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts`:
- Around line 28-31: The test helper createTestEnv mutates process.env.FAAS_ENV
(and similarly at lines 56-57) without restoring it, risking cross-test
contamination; update createTestEnv to capture the original process.env.FAAS_ENV
(and any other env keys you change), set the env for the test, and return or
register a cleanup callback that restores the original values (or use
beforeEach/afterEach to save and restore) so the global env is not permanently
mutated by ClaudeAgentTracer.test runs.
- Around line 356-359: The test only asserts that rootEnd!.run exists but
doesn't verify the propagated error details; update the error-path test (near
assert(rootEnd!.run, 'Root end run should exist')) to assert that the traced run
contains the expected error payload (e.g., check rootEnd!.run.error or
rootEnd!.run.attributes/errorMessage) and that it matches the simulated error
used in the test (create/use an expectedError or expectedErrorMessage derived
from the test's simulated failure or convertSDKMessage). Ensure you reference
the same conversion path (convertSDKMessage) and assert equality/containment
(strictEqual/deepEqual) so the error details are validated.

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts`:
- Line 5: The tests in LangGraphTracer.test.ts modify process.env.FAAS_ENV and
do not restore it; update the test suite to capture the original value (e.g.,
const originalFaasEnv = process.env.FAAS_ENV) before mutating and restore it in
an afterEach hook so each test resets process.env.FAAS_ENV; add an afterEach(()
=> { process.env.FAAS_ENV = originalFaasEnv }) alongside the existing
beforeEach/it blocks to prevent cross-test state leakage.

---

Nitpick comments:
In `@tegg/core/agent-tracing/src/ClaudeAgentTracer.ts`:
- Around line 261-307: The convertSDKMessage in ClaudeAgentTracer currently uses
multiple "as any" casts (e.g., for message, result, errors, usage, modelUsage);
replace these with proper narrowing: add type-guard functions (e.g.,
isSDKAssistantMessage, isSDKUserMessage, isSDKResultMessage) that validate
fields on SDKMessage and narrow message/result/usage/modelUsage to concrete
types, use unknown for initially unknown payloads and only cast after successful
guards, and in the SDKResultMessage branch safely handle errors with
Array.isArray(resultMsg.errors) before joining; update any corresponding
run-build helpers to use the same guards and unknown->narrowing pattern instead
of "as any".

In `@tegg/core/agent-tracing/src/types.ts`:
- Around line 42-54: The ClaudeMessageContent interface uses unsafe any types
for context_management, container, and the index signature; change those to
safer types (e.g., context_management: unknown, container: unknown) and replace
the loose index signature [key: string]: any with a more specific form such as
[key: string]: unknown or Record<string, unknown> to preserve flexibility while
restoring type safety; update any consuming code to properly narrow these fields
(type guards/casts) where necessary.
- Around line 166-175: The call tracingService.configure({}) in
applyTracerConfig is a no-op because it always passes an empty object; update
applyTracerConfig to build and pass a proper AgentTracingConfig derived from the
TracerConfig (e.g., include agentName and any other relevant fields) or only
call tracingService.configure when there are actual config values to apply, and
if AgentTracingConfig is intentionally empty, add a comment explaining it's
reserved for future use; reference the applyTracerConfig function, the
tracer.agentName assignment, the tracingService.configure method, TracerConfig
param and AgentTracingConfig type when making the change.
- Around line 69-110: The ClaudeMessage interface uses wide any types (fields
skills, plugins, permission_denials and the index signature), reducing type
safety; change those to unknown (e.g., replace skills: any[] → skills:
unknown[]; plugins: any[] → plugins: unknown[]; permission_denials?: any[] →
permission_denials?: unknown[]; and the catch‑all [key: string]: any → [key:
string]: unknown) and update any call sites that relied on implicit any to
perform explicit type narrowing or casts where necessary (search for usages of
ClaudeMessage, skills, plugins, permission_denials, and the index signature to
add proper type guards or asserts).

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts`:
- Line 10: The test defines a fixed-delay helper sleep and uses it (sleep(500))
in multiple places which causes slow/flaky tests; replace those hard waits by
removing the sleep helper and instead awaiting a deterministic async flush or
the mocked async completion signal (e.g., implement and call a flushPromises
utility that returns new Promise(r => setImmediate(r)) or await the
tracer/mockedEmitter's completion Promise), and update each assertion site that
currently calls sleep(...) to await that deterministic flush (reference the
sleep constant and the test blocks in LangGraphTracer.test.ts that call sleep).

In `@tegg/core/agent-tracing/test/TestUtils.ts`:
- Around line 21-24: createMockBackgroundTaskHelper currently uses Promise<any>
which hides type regressions; make the helper generic by adding a type parameter
(e.g., <T>) and change the run signature to accept and return Promise<T> so
callers preserve precise types (update the function signature and the returned
run method accordingly, referencing createMockBackgroundTaskHelper and its run
property).

In `@tegg/core/agent-tracing/vitest.config.ts`:
- Around line 1-9: Create a typed intermediate variable (e.g., const config:
UserConfig or ProjectConfig) to hold the result of defineProject(...) instead of
exporting the call inline; import the corresponding type via "import type {
UserConfig } from 'vitest' (or the appropriate ProjectConfig type from
'vitest/config'), assign the object produced by defineProject(...) to that typed
variable (config) and then export default config so isolatedDeclarations is
supported; update references to defineProject and the default export
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9c9d966a-62a9-4e20-93a2-9f07d03a41c7

📥 Commits

Reviewing files that changed from the base of the PR and between f64b818 and af169ed.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • tegg/core/agent-tracing/package.json
  • tegg/core/agent-tracing/src/ClaudeAgentTracer.ts
  • tegg/core/agent-tracing/src/ILogServiceClient.ts
  • tegg/core/agent-tracing/src/IOssClient.ts
  • tegg/core/agent-tracing/src/LangGraphTracer.ts
  • tegg/core/agent-tracing/src/TracingService.ts
  • tegg/core/agent-tracing/src/claude.ts
  • tegg/core/agent-tracing/src/index.ts
  • tegg/core/agent-tracing/src/langgraph.ts
  • tegg/core/agent-tracing/src/types.ts
  • tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts
  • tegg/core/agent-tracing/test/Configure.test.ts
  • tegg/core/agent-tracing/test/LangGraphTracer.test.ts
  • tegg/core/agent-tracing/test/TestUtils.ts
  • tegg/core/agent-tracing/tsconfig.json
  • tegg/core/agent-tracing/vitest.config.ts
  • tegg/core/langchain-decorator/package.json
  • tegg/plugin/langchain/package.json
  • tsconfig.json

@@ -0,0 +1 @@
export { ClaudeAgentTracer, TraceSession } from './ClaudeAgentTracer.ts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use .js extension instead of .ts for ESM import.

Same as langgraph.ts, the import should use .js extension for ESM runtime compatibility.

🔧 Proposed fix
-export { ClaudeAgentTracer, TraceSession } from './ClaudeAgentTracer.ts';
+export { ClaudeAgentTracer, TraceSession } from './ClaudeAgentTracer.js';

As per coding guidelines: "All imports should use .js extensions for ESM files".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export { ClaudeAgentTracer, TraceSession } from './ClaudeAgentTracer.ts';
export { ClaudeAgentTracer, TraceSession } from './ClaudeAgentTracer.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/claude.ts` at line 1, Update the ESM export to
use a .js extension: change the export statement that re-exports
ClaudeAgentTracer and TraceSession from './ClaudeAgentTracer.ts' to import from
'./ClaudeAgentTracer.js' so the runtime uses the correct ESM module filename for
ClaudeAgentTracer and TraceSession.

Comment on lines +9 to +18
import type { TracingService } from './TracingService.ts';
import {
type ClaudeMessage,
type ClaudeContentBlock,
type ClaudeTokenUsage,
type IRunCost,
RunStatus,
type TracerConfig,
applyTracerConfig,
} from './types.ts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use .js extensions for local ESM imports in this tegg module.

These imports currently use .ts specifiers, which violates the module’s ESM import convention and can break runtime resolution in emitted JS.

Suggested fix
-import type { TracingService } from './TracingService.ts';
+import type { TracingService } from './TracingService.js';
 import {
   type ClaudeMessage,
   type ClaudeContentBlock,
   type ClaudeTokenUsage,
   type IRunCost,
   RunStatus,
   type TracerConfig,
   applyTracerConfig,
-} from './types.ts';
+} from './types.js';
As per coding guidelines, "All imports should use `.js` extensions for ESM files".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { TracingService } from './TracingService.ts';
import {
type ClaudeMessage,
type ClaudeContentBlock,
type ClaudeTokenUsage,
type IRunCost,
RunStatus,
type TracerConfig,
applyTracerConfig,
} from './types.ts';
import type { TracingService } from './TracingService.js';
import {
type ClaudeMessage,
type ClaudeContentBlock,
type ClaudeTokenUsage,
type IRunCost,
RunStatus,
type TracerConfig,
applyTracerConfig,
} from './types.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/ClaudeAgentTracer.ts` around lines 9 - 18, The
local ESM imports in ClaudeAgentTracer.ts are using .ts extensions which breaks
runtime resolution; update the import specifiers to use .js instead: change the
import for TracingService (import type { TracingService } from
'./TracingService.ts') to './TracingService.js' and change the grouped import
that brings in ClaudeMessage, ClaudeContentBlock, ClaudeTokenUsage, IRunCost,
RunStatus, TracerConfig, and applyTracerConfig (currently from './types.ts') to
'./types.js' so all local ESM imports use .js extensions.

@@ -0,0 +1 @@
export { LangGraphTracer } from './LangGraphTracer.ts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use .js extension instead of .ts for ESM import.

The import path uses .ts extension, but ESM imports should use .js extensions for runtime compatibility when TypeScript compiles to JavaScript.

🔧 Proposed fix
-export { LangGraphTracer } from './LangGraphTracer.ts';
+export { LangGraphTracer } from './LangGraphTracer.js';

As per coding guidelines: "All imports should use .js extensions for ESM files".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export { LangGraphTracer } from './LangGraphTracer.ts';
export { LangGraphTracer } from './LangGraphTracer.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/langgraph.ts` at line 1, The export uses a
TypeScript file extension for an ESM import; update the export statement that
re-exports LangGraphTracer (symbol: LangGraphTracer) to reference the compiled
JS module by changing the path from './LangGraphTracer.ts' to
'./LangGraphTracer.js' so runtime ESM imports resolve correctly.

Comment on lines +6 to +7
import type { TracingService } from './TracingService.ts';
import { RunStatus, type TracerConfig, applyTracerConfig } from './types.ts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use .js specifiers for local ESM imports.

These local imports use .ts extensions, which is inconsistent with tegg ESM import rules and can break runtime module resolution after transpilation.

Suggested fix
-import type { TracingService } from './TracingService.ts';
-import { RunStatus, type TracerConfig, applyTracerConfig } from './types.ts';
+import type { TracingService } from './TracingService.js';
+import { RunStatus, type TracerConfig, applyTracerConfig } from './types.js';
As per coding guidelines, "All imports should use `.js` extensions for ESM files".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { TracingService } from './TracingService.ts';
import { RunStatus, type TracerConfig, applyTracerConfig } from './types.ts';
import type { TracingService } from './TracingService.js';
import { RunStatus, type TracerConfig, applyTracerConfig } from './types.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/LangGraphTracer.ts` around lines 6 - 7, Change
the local ESM import specifiers in LangGraphTracer to use .js extensions instead
of .ts; update the import of TracingService (from './TracingService.ts') and the
import of RunStatus, TracerConfig, applyTracerConfig (from './types.ts') to
reference './TracingService.js' and './types.js' respectively so runtime module
resolution follows the project's ESM rules.

Comment on lines +8 to +10
import { ILogServiceClient } from './ILogServiceClient.ts';
import { IOssClient } from './IOssClient.ts';
import { type AgentTracingConfig, FIELDS_TO_OSS, type IResource, RunStatus } from './types.ts';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Switch local ESM imports to .js extensions.

Current .ts specifiers violate tegg ESM import rules and can cause runtime import resolution issues in built output.

Suggested fix
-import { ILogServiceClient } from './ILogServiceClient.ts';
-import { IOssClient } from './IOssClient.ts';
-import { type AgentTracingConfig, FIELDS_TO_OSS, type IResource, RunStatus } from './types.ts';
+import { ILogServiceClient } from './ILogServiceClient.js';
+import { IOssClient } from './IOssClient.js';
+import { type AgentTracingConfig, FIELDS_TO_OSS, type IResource, RunStatus } from './types.js';
As per coding guidelines, "All imports should use `.js` extensions for ESM files".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { ILogServiceClient } from './ILogServiceClient.ts';
import { IOssClient } from './IOssClient.ts';
import { type AgentTracingConfig, FIELDS_TO_OSS, type IResource, RunStatus } from './types.ts';
import { ILogServiceClient } from './ILogServiceClient.js';
import { IOssClient } from './IOssClient.js';
import { type AgentTracingConfig, FIELDS_TO_OSS, type IResource, RunStatus } from './types.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/TracingService.ts` around lines 8 - 10, Update
the ESM import specifiers in TracingService.ts to use .js extensions: change
imports that reference './ILogServiceClient.ts', './IOssClient.ts', and
'./types.ts' to './ILogServiceClient.js', './IOssClient.js', and './types.js'
respectively so symbols like ILogServiceClient, IOssClient, AgentTracingConfig,
FIELDS_TO_OSS, IResource, and RunStatus are imported with valid ESM file
extensions.

Comment on lines +116 to +137
FIELDS_TO_OSS.forEach((field) => {
if (!runData[field]) {
return;
}
const jsonstr = JSON.stringify(runData[field]);
if (field === 'outputs') {
(runData as any).cost = runData?.outputs?.llmOutput;
}
delete runData[field];
const key = `agents/${name}/${env}/traces/${run.trace_id}/runs/${run.id}/${field}`;
this.backgroundTaskHelper.run(async () => {
try {
await this.uploadToOss(key, jsonstr);
} catch (e) {
this.logger.warn(
`[TraceLogErr] Failed to upload run data to OSS for run_id=${run.id}, field=${field}, error:`,
e,
);
}
});
(runData as any)[field] = { compress: 'none', key } as IResource;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid replacing trace fields with OSS keys when OSS is unavailable.

The current flow deletes runData[field] and replaces it with a resource key before upload completion. If IOssClient is not configured (or upload fails), detailed trace payloads are lost from logs.

Suggested fix
       FIELDS_TO_OSS.forEach((field) => {
         if (!runData[field]) {
           return;
         }
-        const jsonstr = JSON.stringify(runData[field]);
+        if (!this.ossClient) {
+          // Keep inline payload when OSS is unavailable to avoid data loss.
+          return;
+        }
+        const jsonStr = JSON.stringify(runData[field]);
         if (field === 'outputs') {
           (runData as any).cost = runData?.outputs?.llmOutput;
         }
         delete runData[field];
         const key = `agents/${name}/${env}/traces/${run.trace_id}/runs/${run.id}/${field}`;
         this.backgroundTaskHelper.run(async () => {
           try {
-            await this.uploadToOss(key, jsonstr);
+            await this.uploadToOss(key, jsonStr);
           } catch (e) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FIELDS_TO_OSS.forEach((field) => {
if (!runData[field]) {
return;
}
const jsonstr = JSON.stringify(runData[field]);
if (field === 'outputs') {
(runData as any).cost = runData?.outputs?.llmOutput;
}
delete runData[field];
const key = `agents/${name}/${env}/traces/${run.trace_id}/runs/${run.id}/${field}`;
this.backgroundTaskHelper.run(async () => {
try {
await this.uploadToOss(key, jsonstr);
} catch (e) {
this.logger.warn(
`[TraceLogErr] Failed to upload run data to OSS for run_id=${run.id}, field=${field}, error:`,
e,
);
}
});
(runData as any)[field] = { compress: 'none', key } as IResource;
});
FIELDS_TO_OSS.forEach((field) => {
if (!runData[field]) {
return;
}
if (!this.ossClient) {
// Keep inline payload when OSS is unavailable to avoid data loss.
return;
}
const jsonStr = JSON.stringify(runData[field]);
if (field === 'outputs') {
(runData as any).cost = runData?.outputs?.llmOutput;
}
delete runData[field];
const key = `agents/${name}/${env}/traces/${run.trace_id}/runs/${run.id}/${field}`;
this.backgroundTaskHelper.run(async () => {
try {
await this.uploadToOss(key, jsonStr);
} catch (e) {
this.logger.warn(
`[TraceLogErr] Failed to upload run data to OSS for run_id=${run.id}, field=${field}, error:`,
e,
);
}
});
(runData as any)[field] = { compress: 'none', key } as IResource;
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/TracingService.ts` around lines 116 - 137, The
code currently deletes runData[field] and replaces it with an IResource key
before the OSS upload completes, causing loss of payloads when IOssClient is
absent or upload fails; change the flow in the loop over FIELDS_TO_OSS (where
runData[field] is read, jsonstr created and uploadToOss is invoked inside
backgroundTaskHelper.run) to keep the original runData[field] intact until
upload succeeds: check whether an OSS client is configured, perform uploadToOss
first (or await the backgroundTaskHelper-run result) and only on successful
upload set (runData as any)[field] = { compress: 'none', key } as IResource; on
upload failure or missing client, leave runData[field] untouched and log via
this.logger.warn (as in the existing catch) so trace payloads are preserved.

Comment on lines +28 to +31
function createTestEnv() {
const logs: string[] = [];
process.env.FAAS_ENV = 'dev';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

createTestEnv() mutates global env without cleanup.

process.env.FAAS_ENV is set globally and never restored, which can contaminate other tests and produce non-local failures.

Also applies to: 56-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts` around lines 28 - 31,
The test helper createTestEnv mutates process.env.FAAS_ENV (and similarly at
lines 56-57) without restoring it, risking cross-test contamination; update
createTestEnv to capture the original process.env.FAAS_ENV (and any other env
keys you change), set the env for the test, and return or register a cleanup
callback that restores the original values (or use beforeEach/afterEach to save
and restore) so the global env is not permanently mutated by
ClaudeAgentTracer.test runs.

Comment on lines +356 to +359
// The root run should have error field populated
// (error is extracted from result message via convertSDKMessage)
assert(rootEnd!.run, 'Root end run should exist');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Assert the actual error payload in the error-path test.

The current check only verifies run existence; it does not validate that error details were propagated into the traced run.

✅ Suggested assertion strengthening
       // The root run should have error field populated
       // (error is extracted from result message via convertSDKMessage)
       assert(rootEnd!.run, 'Root end run should exist');
+      assert(rootEnd!.run.error, 'Root end run should include error details');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// The root run should have error field populated
// (error is extracted from result message via convertSDKMessage)
assert(rootEnd!.run, 'Root end run should exist');
});
// The root run should have error field populated
// (error is extracted from result message via convertSDKMessage)
assert(rootEnd!.run, 'Root end run should exist');
assert(rootEnd!.run.error, 'Root end run should include error details');
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts` around lines 356 -
359, The test only asserts that rootEnd!.run exists but doesn't verify the
propagated error details; update the error-path test (near assert(rootEnd!.run,
'Root end run should exist')) to assert that the traced run contains the
expected error payload (e.g., check rootEnd!.run.error or
rootEnd!.run.attributes/errorMessage) and that it matches the simulated error
used in the test (create/use an expectedError or expectedErrorMessage derived
from the test's simulated failure or convertSDKMessage). Ensure you reference
the same conversion path (convertSDKMessage) and assert equality/containment
(strictEqual/deepEqual) so the error details are validated.


import { FakeLLM } from '@langchain/core/utils/testing';
import { StateGraph, Annotation, START, END } from '@langchain/langgraph';
import { describe, it, beforeEach } from 'vitest';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restore process.env.FAAS_ENV after each test to avoid cross-test state leakage.

This suite mutates a global process env value and does not reset it, which can affect unrelated tests running in the same worker.

🛠️ Suggested fix
-import { describe, it, beforeEach } from 'vitest';
+import { describe, it, beforeEach, afterEach } from 'vitest';
@@
 describe('test/LangGraphTracer.test.ts', () => {
   let tracer: LangGraphTracer;
   let logs: string[] = [];
+  let previousFaasEnv: string | undefined;
 
   beforeEach(() => {
     logs = [];
+    previousFaasEnv = process.env.FAAS_ENV;
     process.env.FAAS_ENV = 'dev';
@@
     tracer = new LangGraphTracer();
     (tracer as any).tracingService = tracingService;
   });
+
+  afterEach(() => {
+    if (previousFaasEnv === undefined) {
+      delete process.env.FAAS_ENV;
+    } else {
+      process.env.FAAS_ENV = previousFaasEnv;
+    }
+  });

Also applies to: 31-39

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts` at line 5, The tests in
LangGraphTracer.test.ts modify process.env.FAAS_ENV and do not restore it;
update the test suite to capture the original value (e.g., const originalFaasEnv
= process.env.FAAS_ENV) before mutating and restore it in an afterEach hook so
each test resets process.env.FAAS_ENV; add an afterEach(() => {
process.env.FAAS_ENV = originalFaasEnv }) alongside the existing beforeEach/it
blocks to prevent cross-test state leakage.

jerryliang64 and others added 3 commits March 6, 2026 10:39
- Use ES private fields (#) for TraceSession instead of private keyword
- Remove unused OssConfig interface from types.ts
- Inline createLLMOutput into extractTokenUsage call site
- Switch test assertions to node:assert/strict
- Refactor test utils: replace log-string parsing with direct Run capture
  (createCapturingTracingService replaces createMockTracingService)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hTracer

Add comprehensive TracingService tests covering getEnv, isOnlineEnv,
getLogInfoPrefix, uploadToOss, syncLocalToLogService, and logTrace.
Add direct hook invocation tests in LangGraphTracer for tool, LLM,
retriever and agent callbacks to reach ~89% overall coverage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolve conflict in tsconfig.json by including both agent-tracing
and agent-runtime package references.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@InjectOptional()
private readonly logServiceClient: ILogServiceClient;

configure(_config: AgentTracingConfig): void {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里当前如果用不到,为什么要保留

…ession

Child runs (LLM, tool) were incorrectly using the session start time
(#startTime) instead of the actual event time. This caused all child
spans to have zero duration and be anchored to session creation,
making trace timeline analysis inaccurate.

- handleAssistant: capture eventTime = Date.now() per message
- handleUser: use Date.now() when completing tool runs
- handleResult: use Date.now() for orphaned pending tool runs
- Root run end_time (#startTime + duration_ms) remains unchanged

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts (2)

12-23: ⚠️ Potential issue | 🟠 Major

Restore FAAS_ENV in this suite.

createTestEnv() mutates global env and never cleans it up, so later tests can inherit dev unexpectedly.

Proposed fix
-import { describe, it } from 'vitest';
+import { afterEach, beforeEach, describe, it } from 'vitest';
@@
 describe('test/ClaudeAgentTracer.test.ts', () => {
+  let originalFaasEnv: string | undefined;
+
+  beforeEach(() => {
+    originalFaasEnv = process.env.FAAS_ENV;
+  });
+
+  afterEach(() => {
+    if (originalFaasEnv === undefined) {
+      delete process.env.FAAS_ENV;
+    } else {
+      process.env.FAAS_ENV = originalFaasEnv;
+    }
+  });
+
   describe('Streaming mode + tool use', () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts` around lines 12 - 23,
The test helper createTestEnv() changes process.env.FAAS_ENV to 'dev' but never
restores it; capture the original value (e.g., const prev =
process.env.FAAS_ENV) before setting it, set process.env.FAAS_ENV = 'dev' for
the test, and ensure you restore the original value after the test suite (use an
afterEach/afterAll hook or return a cleanup function from createTestEnv to reset
process.env.FAAS_ENV = prev). Update the test file so any code that calls
createTestEnv() also invokes the cleanup or relies on the suite-level teardown
to restore FAAS_ENV.

313-317: ⚠️ Potential issue | 🟡 Minor

Assert the propagated error payload too.

This still passes if the tracer emits RunStatus.ERROR but drops the actual error details. Please verify the traced run carries the simulated failure message as well.

Suggested assertion strengthening
       const rootError = capturedRuns.find((e) => !e.run.parent_run_id && e.status === RunStatus.ERROR);
       assert(rootError, 'Should have root_run with error status');
       assert(rootError.run, 'Root error run should exist');
+      assert(rootError.run.error, 'Root error run should include error details');
+      assert.match(String(rootError.run.error), /Something went wrong/);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts` around lines 313 -
317, The test currently only checks for a root run with RunStatus.ERROR but not
that the actual error details were propagated; update the assertion after
finding capturedRuns/rootError to also verify the traced run carries the
simulated failure message by asserting the rootError.run error payload contains
that message (e.g. check rootError.run.error.message or
rootError.run.error_message or the specific error field your tracer uses
includes the simulated failure string defined earlier in the test). Ensure you
reference capturedRuns, the rootError variable and the same simulated failure
message constant/string used in this test when adding the assertion.
tegg/core/agent-tracing/test/LangGraphTracer.test.ts (1)

46-54: ⚠️ Potential issue | 🟠 Major

Restore FAAS_ENV after each test.

Line 47 mutates process-wide state, and this suite never puts it back. That makes env-dependent tests order-sensitive across the worker.

Proposed fix
-import { describe, it, beforeEach } from 'vitest';
+import { afterEach, beforeEach, describe, it } from 'vitest';
@@
 describe('test/LangGraphTracer.test.ts', () => {
   let tracer: LangGraphTracer;
   let capturedRuns: CapturedEntry[];
+  let originalFaasEnv: string | undefined;
 
   beforeEach(() => {
+    originalFaasEnv = process.env.FAAS_ENV;
     process.env.FAAS_ENV = 'dev';
@@
     tracer = new LangGraphTracer();
     (tracer as any).tracingService = capturing.tracingService;
   });
+
+  afterEach(() => {
+    if (originalFaasEnv === undefined) {
+      delete process.env.FAAS_ENV;
+    } else {
+      process.env.FAAS_ENV = originalFaasEnv;
+    }
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts` around lines 46 - 54,
The beforeEach mutates process.env.FAAS_ENV and never restores it; capture the
original value (e.g., const _origFaasEnv = process.env.FAAS_ENV) before setting
it to 'dev' in beforeEach and add an afterEach that restores it (if _origFaasEnv
is undefined delete process.env.FAAS_ENV else set process.env.FAAS_ENV =
_origFaasEnv) so tests using beforeEach in LangGraphTracer.test.ts (and the
beforeEach symbol) do not leak env state across tests.
🧹 Nitpick comments (1)
tegg/core/agent-tracing/test/LangGraphTracer.test.ts (1)

34-34: Drop the fixed 500ms waits from these graph tests.

With createCapturingTracingService(), logTrace() appends to capturedRuns synchronously, so these sleeps do not flush anything real. They just add several seconds to the suite and make failures slower to diagnose.

Also applies to: 68-68, 92-92, 120-120, 158-158, 184-184, 212-212, 290-290, 316-316

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts` at line 34, Remove the
fixed 500ms sleeps used in LangGraphTracer tests: since
createCapturingTracingService()’s logTrace() appends to capturedRuns
synchronously, delete the sleep helper (const sleep = ...) and all await
sleep(...) calls in the test cases (references around lines where tests call
sleep) and instead assert directly against capturedRuns after invoking the
traced operation; ensure you still createCapturingTracingService(), call the
traced method, then immediately check capturedRuns for expected entries rather
than waiting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tegg/core/agent-tracing/src/types.ts`:
- Line 14: Replace all occurrences of broad any in the exported Claude message
type shapes (e.g., the input?: Record<string, any> field and the other
open-ended fields at the referenced ranges 49-53, 87-89, 99-109) with a safer
type such as Record<string, unknown> or a named extension generic (e.g.,
Extension = Record<string, unknown> or TExtension = Record<string, unknown>) so
downstream consumers still get type-checking; update the exported type
declarations (the message interfaces/types in types.ts) to use unknown or a
generic extension parameter and propagate that change to the related fields
(input, metadata/extra/other open fields) so the public API no longer uses any.
- Around line 148-150: Remove the empty interface AgentTracingConfig and replace
it with a clearer placeholder type alias to avoid collapsing to {}: change the
declaration for AgentTracingConfig in types.ts to use a type alias like type
AgentTracingConfig = Record<string, never> so static analysis treats it as an
intentionally empty config until fields are added; update any imports/usages
referencing AgentTracingConfig accordingly to accept the new type alias.

---

Duplicate comments:
In `@tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts`:
- Around line 12-23: The test helper createTestEnv() changes
process.env.FAAS_ENV to 'dev' but never restores it; capture the original value
(e.g., const prev = process.env.FAAS_ENV) before setting it, set
process.env.FAAS_ENV = 'dev' for the test, and ensure you restore the original
value after the test suite (use an afterEach/afterAll hook or return a cleanup
function from createTestEnv to reset process.env.FAAS_ENV = prev). Update the
test file so any code that calls createTestEnv() also invokes the cleanup or
relies on the suite-level teardown to restore FAAS_ENV.
- Around line 313-317: The test currently only checks for a root run with
RunStatus.ERROR but not that the actual error details were propagated; update
the assertion after finding capturedRuns/rootError to also verify the traced run
carries the simulated failure message by asserting the rootError.run error
payload contains that message (e.g. check rootError.run.error.message or
rootError.run.error_message or the specific error field your tracer uses
includes the simulated failure string defined earlier in the test). Ensure you
reference capturedRuns, the rootError variable and the same simulated failure
message constant/string used in this test when adding the assertion.

In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts`:
- Around line 46-54: The beforeEach mutates process.env.FAAS_ENV and never
restores it; capture the original value (e.g., const _origFaasEnv =
process.env.FAAS_ENV) before setting it to 'dev' in beforeEach and add an
afterEach that restores it (if _origFaasEnv is undefined delete
process.env.FAAS_ENV else set process.env.FAAS_ENV = _origFaasEnv) so tests
using beforeEach in LangGraphTracer.test.ts (and the beforeEach symbol) do not
leak env state across tests.

---

Nitpick comments:
In `@tegg/core/agent-tracing/test/LangGraphTracer.test.ts`:
- Line 34: Remove the fixed 500ms sleeps used in LangGraphTracer tests: since
createCapturingTracingService()’s logTrace() appends to capturedRuns
synchronously, delete the sleep helper (const sleep = ...) and all await
sleep(...) calls in the test cases (references around lines where tests call
sleep) and instead assert directly against capturedRuns after invoking the
traced operation; ensure you still createCapturingTracingService(), call the
traced method, then immediately check capturedRuns for expected entries rather
than waiting.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ca9c9dec-2625-4ed7-9637-e74261f83ad1

📥 Commits

Reviewing files that changed from the base of the PR and between af169ed and 822b9b6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (8)
  • tegg/core/agent-tracing/src/ClaudeAgentTracer.ts
  • tegg/core/agent-tracing/src/types.ts
  • tegg/core/agent-tracing/test/ClaudeAgentTracer.test.ts
  • tegg/core/agent-tracing/test/Configure.test.ts
  • tegg/core/agent-tracing/test/LangGraphTracer.test.ts
  • tegg/core/agent-tracing/test/TestUtils.ts
  • tegg/core/agent-tracing/test/TracingService.test.ts
  • tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • tsconfig.json
  • tegg/core/agent-tracing/test/TestUtils.ts
  • tegg/core/agent-tracing/test/Configure.test.ts
  • tegg/core/agent-tracing/src/ClaudeAgentTracer.ts

type: 'tool_use';
id: string;
name: string;
input?: Record<string, any>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Replace any in the exported Claude message types.

These are public package types, so any and [key: string]: any effectively turn off checking for downstream consumers. Use unknown or dedicated extension shapes for the open-ended fields instead.

Possible tightening
 export interface ClaudeToolUseContent {
   type: 'tool_use';
   id: string;
   name: string;
-  input?: Record<string, any>;
+  input?: Record<string, unknown>;
 }
@@
-  context_management?: any;
+  context_management?: unknown;
@@
-  container?: any;
-  [key: string]: any;
+  container?: unknown;
+  [key: string]: unknown;
@@
-  skills?: any[];
-  plugins?: any[];
+  skills?: unknown[];
+  plugins?: unknown[];
@@
-  permission_denials?: any[];
+  permission_denials?: unknown[];
@@
-  [key: string]: any;
+  [key: string]: unknown;

As per coding guidelines, "Avoid any type; use unknown when type is truly unknown in TypeScript".

Also applies to: 49-53, 87-89, 99-109

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/types.ts` at line 14, Replace all occurrences of
broad any in the exported Claude message type shapes (e.g., the input?:
Record<string, any> field and the other open-ended fields at the referenced
ranges 49-53, 87-89, 99-109) with a safer type such as Record<string, unknown>
or a named extension generic (e.g., Extension = Record<string, unknown> or
TExtension = Record<string, unknown>) so downstream consumers still get
type-checking; update the exported type declarations (the message
interfaces/types in types.ts) to use unknown or a generic extension parameter
and propagate that change to the related fields (input, metadata/extra/other
open fields) so the public API no longer uses any.

Comment on lines +148 to +150
export interface AgentTracingConfig {
// Reserved for future configuration options
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove the empty AgentTracingConfig interface.

This currently collapses to {} and static analysis is already flagging it. If there are no internal options yet, Record<string, never> is a clearer placeholder until real fields land.

Possible fix
-export interface AgentTracingConfig {
-  // Reserved for future configuration options
-}
+export type AgentTracingConfig = Record<string, never>;
🧰 Tools
🪛 Biome (2.4.4)

[error] 148-150: An empty interface is equivalent to {}.

(lint/suspicious/noEmptyInterface)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tegg/core/agent-tracing/src/types.ts` around lines 148 - 150, Remove the
empty interface AgentTracingConfig and replace it with a clearer placeholder
type alias to avoid collapsing to {}: change the declaration for
AgentTracingConfig in types.ts to use a type alias like type AgentTracingConfig
= Record<string, never> so static analysis treats it as an intentionally empty
config until fields are added; update any imports/usages referencing
AgentTracingConfig accordingly to accept the new type alias.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant