Skip to content

chore: remove outdated test files and update task documentation#51

Closed
ssdeanx wants to merge 2 commits intomainfrom
develop
Closed

chore: remove outdated test files and update task documentation#51
ssdeanx wants to merge 2 commits intomainfrom
develop

Conversation

@ssdeanx
Copy link
Owner

@ssdeanx ssdeanx commented Dec 14, 2025

  • Deleted the following test files as they are no longer needed:

    • src/mastra/tools/tests/serpapi-news-trends.tool.test.ts
    • src/mastra/tools/tests/serpapi-search.tool.test.ts
    • src/mastra/tools/tests/serpapi-shopping.tool.test.ts
    • src/mastra/tools/tests/weather-tool.test.ts
    • src/mastra/tools/tests/web-scraper-tool.test.ts
  • Added a new task documentation file memory-bank/tasks/TASK001-update-2025-12-14.md detailing updates made to align tools with the streaming and progress convention:

    • Replaced data-tool-agent messages with data-tool-progress in various tools.
    • Normalized nested-agent streaming patterns across tools.
    • Updated financial chart tools to use the new streaming pattern.
    • Updated client-side parsers to handle legacy data-tool-agent parts.
    • Documented changes in src/mastra/tools/AGENTS.md.
    • Noted that tests will be added to verify progress events and streaming behavior.

- Deleted the following test files as they are no longer needed:
  - `src/mastra/tools/tests/serpapi-news-trends.tool.test.ts`
  - `src/mastra/tools/tests/serpapi-search.tool.test.ts`
  - `src/mastra/tools/tests/serpapi-shopping.tool.test.ts`
  - `src/mastra/tools/tests/weather-tool.test.ts`
  - `src/mastra/tools/tests/web-scraper-tool.test.ts`

- Added a new task documentation file `memory-bank/tasks/TASK001-update-2025-12-14.md` detailing updates made to align tools with the streaming and progress convention:
  - Replaced `data-tool-agent` messages with `data-tool-progress` in various tools.
  - Normalized nested-agent streaming patterns across tools.
  - Updated financial chart tools to use the new streaming pattern.
  - Updated client-side parsers to handle legacy `data-tool-agent` parts.
  - Documented changes in `src/mastra/tools/AGENTS.md`.
  - Noted that tests will be added to verify progress events and streaming behavior.
Copilot AI review requested due to automatic review settings December 14, 2025 06:34
@continue
Copy link

continue bot commented Dec 14, 2025

All Green - Keep your PRs mergeable

Learn more

All Green is an AI agent that automatically:

✅ Addresses code review comments

✅ Fixes failing CI checks

✅ Resolves merge conflicts

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Sorry @ssdeanx, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@github-actions
Copy link

🤖 Hi @ssdeanx, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@coderabbitai
Copy link

coderabbitai bot commented Dec 14, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Summary by CodeRabbit

  • New Features

    • Tool streaming with progress events; new browser color-change tool; additional runtime agents and per-request context fields.
  • Bug Fixes

    • Normalized legacy progress-event formats; tightened progress/status handling and improved streaming error reporting.
  • Refactor

    • Switched many tools to streaming-first flows and standardized agent invocation and embedding workflows; metadata sanitization and weight normalization added.
  • Documentation

    • Added streaming/progress conventions, task updates, and agent changelog entries.
  • Tests

    • Large removal/cleanup of multiple tool test suites (reduced coverage).

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds standardized streaming support and data-tool-progress events across many Mastra tools and client providers, normalizes legacy progress formats, updates ESLint unused-var rules, registers new agents and middleware, introduces a browser color-change tool, refactors document chunking/embeddings, and removes many tool test files.

Changes

Cohort / File(s) Summary
Tool streaming & progress events
src/mastra/tools/copywriter-agent-tool.ts, src/mastra/tools/editor-agent-tool.ts, src/mastra/tools/evaluateResultTool.ts, src/mastra/tools/extractLearningsTool.ts, src/mastra/tools/financial-chart-tools.ts
Add streaming-first agent handling (agent.stream → fallback agent.generate), pipe text/full streams to writer, emit standardized data-tool-progress events (in-progress/done), enhance error/span handling, and normalize response extraction.
Document chunking & embeddings
src/mastra/tools/document-chunking.tool.ts
Add metadata sanitization, embedding batching and model config, weight normalization helper, safer embedding/storage and reranker integration, added span-finalization and improved error fallbacks; expanded input schemas.
Client progress normalization
app/networks/providers/network-context.tsx, app/workflows/providers/workflow-context.tsx
Normalize legacy data-tool-agent/data-tool-workflow parts into data-tool-progress events by tolerant message/stage extraction, include agentId when present, and tighten custom progress status checks.
Mastra bootstrap & agents
src/mastra/index.ts, src/mastra/agents/researchAgent.ts, src/mastra/AGENTS.md
Register new agents (calendarAgent, bgColorAgent, danePackagePublisher), add RequestContext middleware population/logging, extend ResearchRuntimeContext with userId/researchPhase, and update docs/changelog.
New browser tool
src/mastra/tools/color-change-tool.ts
Add changeBgColor and exported colorChangeTool to set CSS --background in browser contexts.
Chat provider minor rename
app/chat/providers/chat-context.tsx
Rename internal parameter _filesfiles in ChatProvider.sendMessage (no behavior change).
ESLint config change
eslint.config.js
Remove argsIgnorePattern/varsIgnorePattern for no-unused-vars and @typescript-eslint/no-unused-vars, enabling warnings for previously-ignored underscore-prefixed vars.
Memory-bank docs / TASK updates
memory-bank/copilot-rules.md, memory-bank/memory-bank-instructions.md, memory-bank/tasks/TASK001-tool-streaming.md, memory-bank/tasks/TASK001-update-2025-12-14.md
Add tool-streaming guidance, prefer agent.stream, emit standardized progress events, and record TASK001 updates.
Large test deletions
src/mastra/tools/tests/*
src/mastra/tools/tests/copywriter-agent-tool.test.ts, .../csv-to-json.tool.test.ts, .../data-file-manager.test.ts, .../data-validator.tool.test.ts, .../document-chunking.tool.test.ts, .../editor-agent-tool.test.ts, .../evaluateResultTool.test.ts, .../extractLearningsTool.test.ts, .../json-to-csv.tool.test.ts, .../serpapi-*.tool.test.ts, .../weather-tool.test.ts, .../web-scraper-tool.test.ts
Remove many comprehensive Vitest test suites for tools (reduces test coverage across numerous modules).

Sequence Diagram(s)

sequenceDiagram
    participant Tool as Tool (e.g., Copywriter)
    participant Mastra as Mastra/AgentRegistry
    participant Agent as Mastra Agent
    participant Writer as Writer/Client Stream
    participant Tracer as Tracing/Span

    Tool->>Mastra: getAgent(name) or fallback local
    Mastra-->>Tool: Agent (may be undefined)
    Tool->>Agent: check for stream()
    alt stream available
        Tool->>Agent: agent.stream(prompt)
        activate Agent
        Agent-->>Tool: MastraModelOutput (textStream/fullStream/object)
        Tool->>Writer: emit data-tool-progress (in-progress)
        Tool->>Writer: pipe textStream/fullStream -> client
        Tool->>Tool: accumulate resultText / parse object
        deactivate Agent
    else fallback
        Tool->>Agent: agent.generate(prompt)
        Agent-->>Tool: response (text/object)
        Tool->>Tool: parse response text/object
    end
    alt error
        Tool->>Tracer: record exception, set span ERROR
        Tool->>Writer: emit data-tool-progress (done/error)
        Tool-->>Client: return failure
    else success
        Tool->>Tracer: record metrics, end span
        Tool->>Writer: emit data-tool-progress (done)
        Tool-->>Client: return result
    end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

  • Reasoning: widespread, heterogeneous functional changes touching many tool implementations, document chunking/embedding refactor with schema surface changes, client/provider normalization, Mastra bootstrap/middleware updates, plus large-scale deletion of tests requiring careful verification.
  • Areas needing focused review:
    • Consistency of streaming/fallback/error handling and progress event shapes across tools.
    • Document chunking embedding/upsert logic and schema compatibility.
    • ESLint rule impact on the codebase (new unused-var warnings).
    • Test removals: assess coverage gaps and planned replacement tests.

Possibly related PRs

Poem

🐰 Streams hum softly, progress lights the way,

Agent whispers steady, piping night to day,
Chunks get tidy, vectors find their place,
Tests took a nap — the rabbit keeps the pace,
Hop on, code, with a carrot-shaped embrace!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary changes: removing outdated test files and updating task documentation related to streaming conventions.
Description check ✅ Passed The description is directly related to the changeset, providing specific details about deleted test files and the new task documentation added.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89b9eb4 and 1579228.

📒 Files selected for processing (4)
  • src/mastra/AGENTS.md (1 hunks)
  • src/mastra/agents/researchAgent.ts (3 hunks)
  • src/mastra/index.ts (4 hunks)
  • src/mastra/tools/color-change-tool.ts (1 hunks)

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.

@github-actions
Copy link

🤖 I'm sorry @ssdeanx, but I was unable to process your request. Please see the logs for more details.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ssdeanx, 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 significant standardization effort for streaming and progress event conventions across various tools and client-side components. It involves refactoring several agent-based tools to adopt a unified streaming pattern and updating client-side parsers to handle these new events. Additionally, the document chunking and reranking capabilities have been enhanced, and a substantial number of outdated test files have been removed to clean up the codebase and align with current development practices. Documentation has also been updated to reflect these changes.

Highlights

  • Standardized Streaming & Progress Events: Refactored multiple tools (copywriter, editor, evaluation, learning extraction, financial chart tools) to consistently use data-tool-progress events and a normalized nested-agent streaming pattern, prioritizing runtime agent instances.
  • Client-Side Parser Updates: Updated client-side parsers in network-context.tsx and workflow-context.tsx to normalize legacy data-tool-agent messages into the new data-tool-progress event format, ensuring backward compatibility and consistent UI feedback.
  • Document Chunking & Reranking Enhancements: Improved the document-chunking.tool.ts with batching for embedding generation, robust error handling, metadata sanitization, and flexible reranking options including configurable weights and model selection.
  • Outdated Test File Removal: Removed numerous outdated test files across various tools, streamlining the test suite and focusing on current testing methodologies.
  • Documentation Updates: Added a new task documentation file (TASK001-update-2025-12-14.md) detailing the streaming and progress convention changes, and updated AGENTS.md and memory-bank-instructions.md to reflect these new standards.
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.

@greptile-apps
Copy link

greptile-apps bot commented Dec 14, 2025

Greptile Overview

Greptile Summary

This PR standardizes streaming and progress event patterns across the codebase by replacing data-tool-agent events with data-tool-progress and normalizing agent streaming patterns across multiple tools.

Key Changes

  • Tool streaming standardization: Updated copywriter-agent-tool.ts, editor-agent-tool.ts, evaluateResultTool.ts, extractLearningsTool.ts, and financial-chart-tools.ts to use MastraModelOutput streaming pattern with consistent agent fallback imports
  • Client-side compatibility: Modified network-context.tsx and workflow-context.tsx to normalize legacy data-tool-agent events into data-tool-progress format for backward compatibility
  • Documentation updates: Added new task documentation file TASK001-update-2025-12-14.md and updated AGENTS.md with progress event conventions
  • Test cleanup: Removed 16 test files (4,991 lines) including serpapi, weather, and web-scraper tests, with a note that tests will be re-added to verify progress events
  • Additional improvements: Added metadata sanitization and weight normalization utilities to document-chunking.tool.ts

Issues Found

  • Documentation example in AGENTS.md contains malformed template string syntax
  • ESLint config removed ignore patterns for underscore-prefixed variables, which will trigger warnings for intentionally unused parameters

Confidence Score: 3/5

  • This PR is mostly safe but has significant test coverage loss and two syntax/config issues that need fixing
  • Score reflects: (1) loss of substantial test coverage (16 test files deleted without replacement), (2) malformed documentation example that could confuse developers, (3) ESLint config change that will cause warnings across the codebase. The streaming pattern refactoring itself is well-executed and consistent, but the supporting changes reduce code quality safeguards.
  • Pay close attention to eslint.config.js (will cause linting warnings) and src/mastra/tools/AGENTS.md (has syntax error in documentation). Monitor test coverage after deleted test files are restored.

Important Files Changed

File Analysis

Filename Score Overview
src/mastra/tools/AGENTS.md 4/5 Updated documentation with progress event format example showing malformed message template string
eslint.config.js 5/5 Removed argsIgnorePattern and varsIgnorePattern from unused vars rules; cleaner but less permissive
src/mastra/tools/copywriter-agent-tool.ts 4/5 Updated to use standard streaming pattern with MastraModelOutput, improved agent validation and fallback logic
src/mastra/tools/financial-chart-tools.ts 4/5 Updated all chart tools to use MastraModelOutput streaming pattern with agent fallback imports
app/networks/providers/network-context.tsx 4/5 Updated to normalize legacy data-tool-agent events into data-tool-progress format for backward compatibility
src/mastra/tools/tests/serpapi-search.tool.test.ts 3/5 Test file deleted - loses test coverage for serpapi search tool
src/mastra/tools/tests/weather-tool.test.ts 3/5 Test file deleted - loses test coverage for weather tool
src/mastra/tools/tests/web-scraper-tool.test.ts 3/5 Test file deleted - loses test coverage for web scraper tool

Sequence Diagram

sequenceDiagram
    participant Client
    participant Tool as Tool (e.g. copywriter-agent-tool)
    participant Context as RuntimeContext
    participant Agent as Agent (copywriter/editor/etc)
    participant Writer as Context Writer

    Client->>Tool: execute(inputData, context)
    Tool->>Writer: custom({ type: 'data-tool-progress', status: 'in-progress' })
    
    Tool->>Context: mastra.getAgent('agentName')
    alt Agent found in context
        Context-->>Tool: return agent instance
    else Agent not found
        Tool->>Tool: fallback to local import
    end
    
    Tool->>Tool: validate agent has generate or stream method
    alt No valid methods
        Tool->>Writer: custom({ type: 'data-tool-progress', status: 'done', message: 'error' })
        Tool-->>Client: return error
    end
    
    alt Agent has stream method
        Tool->>Agent: stream(prompt)
        Agent-->>Tool: MastraModelOutput { textStream, fullStream, text, object }
        Tool->>Writer: custom({ type: 'data-tool-progress', message: 'Streaming...' })
        
        alt Has textStream
            Tool->>Writer: textStream.pipeTo(writer)
        else Has fullStream
            Tool->>Writer: fullStream.pipeTo(writer)
        end
        
        Agent-->>Tool: await stream.text
        Tool->>Tool: parse response object or text
    else Agent has generate only
        Tool->>Agent: generate(prompt)
        Agent-->>Tool: { text, object }
        Tool->>Tool: parse response object or text
    end
    
    Tool->>Writer: custom({ type: 'data-tool-progress', status: 'done' })
    Tool-->>Client: return result
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

30 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

data: {
status: "in-progress", // "in-progress" | "done"
message: "Descriptive progress message...",
message: "Descriptive progress message ${inputData.context}....`,",
Copy link

Choose a reason for hiding this comment

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

syntax: malformed template string in documentation example - has mismatched quotes and backticks

Suggested change
message: "Descriptive progress message ${inputData.context}....`,",
message: "Descriptive progress message...",
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/mastra/tools/AGENTS.md
Line: 105:105

Comment:
**syntax:** malformed template string in documentation example - has mismatched quotes and backticks

```suggestion
    message: "Descriptive progress message...",
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +65 to +66
'no-unused-vars': ['warn', { }],
'@typescript-eslint/no-unused-vars': ['warn', {}],
Copy link

Choose a reason for hiding this comment

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

logic: removed ignore patterns for underscore-prefixed variables/args - this will cause warnings for intentionally unused parameters like _context or _req

Suggested change
'no-unused-vars': ['warn', { }],
'@typescript-eslint/no-unused-vars': ['warn', {}],
'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
Prompt To Fix With AI
This is a comment left during a code review.
Path: eslint.config.js
Line: 65:66

Comment:
**logic:** removed ignore patterns for underscore-prefixed variables/args - this will cause warnings for intentionally unused parameters like `_context` or `_req`

```suggestion
            'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
            '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
```

How can I resolve this? If you propose a fix, please make it concise.

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 primarily focuses on standardizing tool streaming and progress event conventions across various agents and client-side providers, as detailed in the newly added TASK001-update-2025-12-14.md documentation. Key changes include updating copywriter-agent-tool.ts, editor-agent-tool.ts, evaluateResultTool.ts, extractLearningsTool.ts, and financial-chart-tools.ts to use streaming APIs (agent.stream) with MastraModelOutput and emit data-tool-progress events, replacing older data-tool-agent messages. Client-side parsers in app/networks/providers/network-context.tsx and app/workflows/providers/workflow-context.tsx were updated to normalize these legacy agent events into the new progress event format. The document-chunking.tool.ts received significant updates, including new helper functions for metadata sanitization and weight normalization, batching for embedding generation, improved error handling, and refined chunking strategies. Additionally, eslint.config.js was modified to remove argsIgnorePattern and varsIgnorePattern from unused variable rules, and AGENTS.md was updated with the new conventions and a typo fix. Review comments highlighted the complexity of message extraction logic in client-side providers, a typo in the AGENTS.md example, inconsistency in JSON parsing fallbacks in copywriter-agent-tool.ts, and verbosity in text extraction from metadata in document-chunking.tool.ts.

Comment on lines +304 to +308
const msg = typeof dataObj?.text === 'string' ? dataObj.text
: typeof dataObj?.message === 'string' ? dataObj.message
: typeof eventData?.message === 'string' ? eventData.message
: typeof eventData?.text === 'string' ? eventData.text
: ''
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 to extract the message msg is a bit complex and could be simplified. Using a helper function or a more streamlined approach might improve readability and maintainability, especially since similar logic is repeated in app/workflows/providers/workflow-context.tsx.

Comment on lines +65 to +66
'no-unused-vars': ['warn', { }],
'@typescript-eslint/no-unused-vars': ['warn', {}],
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Removing the argsIgnorePattern and varsIgnorePattern options means we can no longer mark intentionally unused variables with an underscore to suppress warnings. This might lead to unnecessary warnings for variables that are required by an interface but not used in the implementation. Was this change intentional? If so, what is the new convention for handling such cases?

Suggested change
'no-unused-vars': ['warn', { }],
'@typescript-eslint/no-unused-vars': ['warn', {}],
'no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],

data: {
status: "in-progress", // "in-progress" | "done"
message: "Descriptive progress message...",
message: "Descriptive progress message ${inputData.context}....`,",
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There appears to be a typo in the example message string. It contains an extra backtick and a comma at the end, which could be confusing for developers referencing this documentation.

Suggested change
message: "Descriptive progress message ${inputData.context}....`,",
message: `Descriptive progress message ${inputData.context}....`,

if (writer && typeof agentWithStream.stream === 'function') {
const stream = await agentWithStream.stream(prompt)
const text = (await stream?.text) ?? ''
const responseObject = stream?.object ?? (() => { try { return JSON.parse(text) } catch { return {} } })()
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 fallback for JSON parsing in the streaming path returns an empty object ({}) on failure, while the fallback in the generate path (line 233) returns undefined. For consistency and clearer intent, it would be better to have both fallbacks return undefined and then handle the undefined case explicitly.

Suggested change
const responseObject = stream?.object ?? (() => { try { return JSON.parse(text) } catch { return {} } })()
const responseObject = stream?.object ?? (() => { try { return JSON.parse(text) } catch { return undefined } })()

initialResults.map((result) => ({
id: result.id,
text: result.metadata?.text as string,
text: (result.metadata?.text as string) ?? (typeof result.metadata?.text === 'undefined' ? '' : String(result.metadata?.text)),
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This logic to safely extract text from metadata is a bit verbose. It can be simplified using String() and nullish coalescing, which would be more concise and achieve the same goal of safely converting the value to a string, handling null, undefined, and other types gracefully.

Suggested change
text: (result.metadata?.text as string) ?? (typeof result.metadata?.text === 'undefined' ? '' : String(result.metadata?.text)),
text: String(result.metadata?.text ?? ''),

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR performs maintenance and standardization work by removing 11 outdated test files and documenting streaming/progress convention updates. The changes align tool implementations with a new data-tool-progress event pattern and normalize nested-agent streaming across multiple tools.

Key Changes

  • Test File Removal: Deleted 11 test files for various tools (web-scraper, weather, serpapi, data validation, document chunking, etc.)
  • Streaming Convention Updates: Standardized tools to use data-tool-progress events and MastraModelOutput typing
  • Client-Side Normalization: Updated UI providers to handle legacy data-tool-agent events

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/mastra/tools/tests/*.test.ts (11 files) Removed outdated test files - tests appear comprehensive but deletion reduces coverage
memory-bank/tasks/TASK001-update-2025-12-14.md Added documentation of streaming convention changes
src/mastra/tools/financial-chart-tools.ts Updated to use new streaming pattern with agent fallbacks
src/mastra/tools/extractLearningsTool.ts Migrated from data-tool-agent to data-tool-progress events
src/mastra/tools/evaluateResultTool.ts Added streaming support with MastraModelOutput
src/mastra/tools/editor-agent-tool.ts Implemented nested agent streaming pattern
src/mastra/tools/document-chunking.tool.ts Enhanced with embedding batching and metadata sanitization
src/mastra/tools/copywriter-agent-tool.ts Updated streaming implementation
src/mastra/tools/AGENTS.md Updated documentation with progress event format
app/workflows/providers/workflow-context.tsx Normalized legacy event handling
app/networks/providers/network-context.tsx Normalized legacy event handling
app/chat/providers/chat-context.tsx Minor parameter rename
eslint.config.js Removed underscore ignore patterns for unused variables
memory-bank/*.md (3 files) Updated memory bank with streaming conventions


const sendMessage = useCallback(
(text: string, _files?: File[]) => {
(text: string, files?: File[]) => {
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

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

The unused parameter files (renamed from _files) will now trigger ESLint warnings due to the ESLint configuration change that removed the underscore ignore pattern. If this parameter is intentionally unused but required by the function signature, it should be prefixed with underscore to document this intent.

Suggested change
(text: string, files?: File[]) => {
(text: string, _files?: File[]) => {

Copilot uses AI. Check for mistakes.
data: {
status: "in-progress", // "in-progress" | "done"
message: "Descriptive progress message...",
message: "Descriptive progress message ${inputData.context}....`,",
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

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

The string literal template interpolation syntax has incorrect quoting. The backtick for template literal starts mid-string and ends with a mismatched quote character. This appears to be:

message: "Descriptive progress message ${inputData.context}....`,",

Should likely be either a full template literal or a regular string without interpolation.

Suggested change
message: "Descriptive progress message ${inputData.context}....`,",
message: `Descriptive progress message ${inputData.context}....`,

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +66
'no-unused-vars': ['warn', { }],
'@typescript-eslint/no-unused-vars': ['warn', {}],
Copy link

Copilot AI Dec 14, 2025

Choose a reason for hiding this comment

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

The ESLint configuration change removes important ignore patterns for unused variables starting with underscore. The empty object {} means ALL unused variables will now trigger warnings, even those intentionally prefixed with _ to indicate they're unused but required (e.g., function signatures matching interfaces).

This will likely cause numerous false-positive warnings throughout the codebase where developers intentionally use _ prefix to indicate "I know this parameter is unused but it's required by the signature".

Suggested change
'no-unused-vars': ['warn', { }],
'@typescript-eslint/no-unused-vars': ['warn', {}],
'no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],

Copilot uses AI. Check for mistakes.
Copy link

@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: 23

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
src/mastra/tools/document-chunking.tool.ts (4)

198-201: mastraChunker never emits a done progress event (success/error).

Guidelines require tools to emit data-tool-progress with status: 'done'. mastraChunker only emits in-progress. Add done on both success and failure.

       logStepEnd('mastra-chunker', output, totalProcessingTime)
-
+      await context?.writer?.custom({
+        type: 'data-tool-progress',
+        data: { status: 'done', message: `✅ Processed ${chunks.length} chunks successfully`, stage: 'mastra:chunker' },
+        id: 'mastra:chunker',
+      })
       return output
     } catch (error) {
@@
       span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
+
+      await context?.writer?.custom({
+        type: 'data-tool-progress',
+        data: { status: 'done', message: `❌ Failed: ${errorMessage}`, stage: 'mastra:chunker' },
+        id: 'mastra:chunker',
+      })
 
       return {
         success: false,

As per coding guidelines, tools must emit data-tool-progress with status and stage.

Also applies to: 384-411


652-699: Index creation + dimension mismatch is being swallowed; logging should be actionable.

If createIndex fails due to dimension mismatch (or perms), continuing to upsert can produce confusing runtime failures. At minimum, log indexName, intended dimension, and decide whether to skip upsert when the index cannot be ensured.

         try {
           await pgVector.createIndex({ indexName: inputData.indexName, dimension: embeddings[0]?.length || 0 })
         } catch (idxErr) {
-          log.info('createIndex skipped or failed', { error: (idxErr as Error)?.message ?? idxErr })
+          logError('mdocument-chunker-createIndex', idxErr, {
+            indexName: inputData.indexName,
+            dimension: embeddings[0]?.length || 0,
+          })
         }

Based on coding guidelines, keep comments/logging accurate and actionable.


719-747: Emit done progress on error paths too (mdocument chunker).

mdocumentChunker emits done only on success; in errors it returns without a final progress event. Mirror the success behavior in catch (and consider including the error message).


940-965: Emit done progress on reranker failures as well.

documentRerankerTool emits done on success and “no results”, but not in the error path. Add a final done event in catch before returning. As per coding guidelines, tools must emit data-tool-progress completion consistently.

src/mastra/tools/AGENTS.md (1)

1-1: Inconsistent date format in metadata.

The last_updated field was changed from ISO 8601 format with time and timezone (2025-11-27T00:00:00Z) to a plain date (2025-12-14). This inconsistency may break tooling that parses this metadata and expects a standardized format.

Apply this diff to maintain consistent ISO 8601 formatting:

-<!-- AGENTS-META {\"title\":\"Mastra Tools\",\"version\":\"2.2.0\",\"last_updated\":\"2025-11-27T00:00:00Z\",\"applies_to\":\"/src/mastra/tools\",\"tags\":[\"layer:backend\",\"domain:rag\",\"type:tools\",\"status\":\"stable\"]} -->
+<!-- AGENTS-META {\"title\":\"Mastra Tools\",\"version\":\"2.2.0\",\"last_updated\":\"2025-12-14T00:00:00Z\",\"applies_to\":\"/src/mastra/tools\",\"tags\":[\"layer:backend\",\"domain:rag\",\"type:tools\",\"status\":\"stable\"]} -->
app/workflows/providers/workflow-context.tsx (1)

322-340: Legacy event normalization implemented correctly.

The normalization logic effectively handles multiple legacy event formats by:

  • Extracting message text from various nested field paths with fallbacks
  • Deriving stage from available metadata or part type
  • Only emitting progress events when meaningful message content exists

The type guards (typeof === 'string') ensure type safety, and the tolerant extraction pattern handles variations in legacy event structures appropriately.

For improved readability, consider extracting the message derivation into a helper function:

// Before the loop or as a module-level helper
function extractMessageFromLegacyEvent(eventData?: Record<string, unknown>): string {
  const dataObj = eventData?.data as Record<string, unknown> | undefined
  
  if (typeof dataObj?.text === 'string') return dataObj.text
  if (typeof dataObj?.message === 'string') return dataObj.message
  if (typeof eventData?.message === 'string') return eventData.message
  if (typeof eventData?.text === 'string') return eventData.text
  
  return 'Agent executing tool'
}

// In the event handler
const msg = extractMessageFromLegacyEvent(eventData)

This reduces the cognitive complexity of the inline ternary chain on lines 327-328.

app/networks/providers/network-context.tsx (1)

298-324: Legacy event normalization correctly implemented for network context.

The normalization logic properly handles legacy event formats and appropriately extracts agentId for multi-agent network scenarios. The pattern is consistent with the workflow-context.tsx implementation.

For improved maintainability, consider extracting the message derivation into a shared helper function (similar to the suggestion for workflow-context.tsx):

// Could be shared between network-context.tsx and workflow-context.tsx
function extractLegacyEventMessage(eventData?: Record<string, unknown>): string {
  const dataObj = eventData?.data as Record<string, unknown> | undefined
  
  return (
    (typeof dataObj?.text === 'string' ? dataObj.text : null) ??
    (typeof dataObj?.message === 'string' ? dataObj.message : null) ??
    (typeof eventData?.message === 'string' ? eventData.message : null) ??
    (typeof eventData?.text === 'string' ? eventData.text : null) ??
    ''
  )
}

This would reduce duplication across context providers and make the extraction logic easier to test and maintain.

src/mastra/tools/copywriter-agent-tool.ts (1)

180-183: Incomplete implementation: 'general' contentType throws an error.

The contentType input schema includes 'general' as a valid option (Line 27), but the switch statement throws an error for this case. This will cause runtime failures for users selecting 'general'.

Either implement the 'general' case or remove it from the input schema:

         case 'general': {
-          throw new Error('Not implemented yet: "general" case')
+          prompt +=
+            '\n\nCreate clear, well-structured content appropriate for the topic and audience.'
+          break
         }
src/mastra/tools/financial-chart-tools.ts (2)

1-736: Significant code duplication across all four chart tools.

The streaming logic, JSON parsing with ```json regex extraction, and progress event emission are nearly identical in all four tools. Consider extracting shared helpers.

Example helpers:

// Shared streaming helper
async function streamFromAgent(
  agent: Agent,
  prompt: string,
  writer?: WritableStream
): Promise<string> {
  if (typeof agent.stream === 'function') {
    const stream = await agent.stream(prompt) as MastraModelOutput | undefined;
    if (stream?.fullStream && writer) {
      await stream.fullStream.pipeTo(writer);
    } else if (stream?.textStream && writer) {
      await stream.textStream.pipeTo(writer);
    }
    return (await stream?.text) ?? '';
  }
  const result = await agent.generate(prompt);
  return result.text;
}

// Shared JSON extraction
function extractJsonFromResponse(text: string): unknown {
  const jsonMatch = /```json\s*([\s\S]*?)\s*```/.exec(text);
  if (jsonMatch?.[1]) return JSON.parse(jsonMatch[1]);
  return JSON.parse(text);
}

196-198: Use SpanStatusCode.ERROR instead of magic number 2.

Other tools use the named constant SpanStatusCode.ERROR from @opentelemetry/api. Using the magic number 2 reduces readability and maintainability.

-      span.setStatus({ code: 2, message: errorMsg })
+      span.setStatus({ code: SpanStatusCode.ERROR, message: errorMsg })

Note: This pattern appears at Lines 197, 362, 546, 724 - all should use the named constant. You'll need to add SpanStatusCode to the import on Line 1.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f144f5 and 89b9eb4.

📒 Files selected for processing (30)
  • app/chat/providers/chat-context.tsx (1 hunks)
  • app/networks/providers/network-context.tsx (2 hunks)
  • app/workflows/providers/workflow-context.tsx (1 hunks)
  • eslint.config.js (1 hunks)
  • memory-bank/copilot-rules.md (1 hunks)
  • memory-bank/memory-bank-instructions.md (1 hunks)
  • memory-bank/tasks/TASK001-tool-streaming.md (1 hunks)
  • memory-bank/tasks/TASK001-update-2025-12-14.md (1 hunks)
  • src/mastra/tools/AGENTS.md (4 hunks)
  • src/mastra/tools/copywriter-agent-tool.ts (3 hunks)
  • src/mastra/tools/document-chunking.tool.ts (16 hunks)
  • src/mastra/tools/editor-agent-tool.ts (4 hunks)
  • src/mastra/tools/evaluateResultTool.ts (3 hunks)
  • src/mastra/tools/extractLearningsTool.ts (3 hunks)
  • src/mastra/tools/financial-chart-tools.ts (10 hunks)
  • src/mastra/tools/tests/copywriter-agent-tool.test.ts (0 hunks)
  • src/mastra/tools/tests/csv-to-json.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/data-file-manager.test.ts (0 hunks)
  • src/mastra/tools/tests/data-validator.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/document-chunking.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/editor-agent-tool.test.ts (0 hunks)
  • src/mastra/tools/tests/evaluateResultTool.test.ts (0 hunks)
  • src/mastra/tools/tests/extractLearningsTool.test.ts (0 hunks)
  • src/mastra/tools/tests/json-to-csv.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/serpapi-academic-local.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/serpapi-news-trends.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/serpapi-search.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/serpapi-shopping.tool.test.ts (0 hunks)
  • src/mastra/tools/tests/weather-tool.test.ts (0 hunks)
  • src/mastra/tools/tests/web-scraper-tool.test.ts (0 hunks)
💤 Files with no reviewable changes (15)
  • src/mastra/tools/tests/json-to-csv.tool.test.ts
  • src/mastra/tools/tests/extractLearningsTool.test.ts
  • src/mastra/tools/tests/serpapi-academic-local.tool.test.ts
  • src/mastra/tools/tests/evaluateResultTool.test.ts
  • src/mastra/tools/tests/serpapi-news-trends.tool.test.ts
  • src/mastra/tools/tests/csv-to-json.tool.test.ts
  • src/mastra/tools/tests/editor-agent-tool.test.ts
  • src/mastra/tools/tests/copywriter-agent-tool.test.ts
  • src/mastra/tools/tests/web-scraper-tool.test.ts
  • src/mastra/tools/tests/document-chunking.tool.test.ts
  • src/mastra/tools/tests/serpapi-shopping.tool.test.ts
  • src/mastra/tools/tests/serpapi-search.tool.test.ts
  • src/mastra/tools/tests/weather-tool.test.ts
  • src/mastra/tools/tests/data-file-manager.test.ts
  • src/mastra/tools/tests/data-validator.tool.test.ts
🧰 Additional context used
📓 Path-based instructions (22)
**/*.md

📄 CodeRabbit inference engine (.github/instructions/markdown.instructions.md)

**/*.md: Use appropriate heading levels (H2, H3, etc.) to structure markdown content. Do not use H1 headings, as these will be generated from the title. Use ## for H2 and ### for H3 in a hierarchical manner. Recommend restructuring if content includes H4 or higher levels.
Use bullet points (with -) or numbered lists (with 1.) for lists in markdown. Indent nested lists with two spaces and ensure proper indentation and spacing.
Use fenced code blocks (triple backticks) for code snippets in markdown. Specify the language after the opening backticks for syntax highlighting (e.g., csharp).
Use proper markdown syntax for links: [link text](URL). Ensure that link text is descriptive and URLs are valid and accessible.
Use proper markdown syntax for images: ![alt text](image URL). Include a brief description of the image in the alt text for accessibility.
Use markdown tables (with | delimiters) for tabular data. Ensure proper formatting, alignment, and inclusion of headers.
Limit line length to 80 characters in markdown for readability. Use soft line breaks for long paragraphs.
Use appropriate whitespace in markdown to separate sections and improve readability. Use blank lines between sections and avoid excessive whitespace.
Include YAML front matter at the beginning of markdown files with required metadata fields: post_title, author1, post_slug, microsoft_alias, featured_image, categories (from /categories.txt), tags, ai_note, summary, and post_date.

Files:

  • memory-bank/memory-bank-instructions.md
  • memory-bank/tasks/TASK001-tool-streaming.md
  • memory-bank/copilot-rules.md
  • src/mastra/tools/AGENTS.md
  • memory-bank/tasks/TASK001-update-2025-12-14.md
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

**/*.{js,jsx,ts,tsx}: Use next/dynamic for dynamic imports to load components only when needed, improving initial load time.
Use next/image component for automatic image optimization, including lazy loading and responsive images.
Use React.memo to prevent unnecessary re-renders of components.
Use the <Link prefetch> tag to prefetch pages that are likely to be visited.
Use getServerSideProps, getStaticProps, or server components for fetching data on the server-side.
Use SWR or React Query for client-side data fetching and caching.
Use CSS Modules, Styled Components, or Tailwind CSS for component-level styling. Prefer Tailwind CSS for rapid development.
Use React Context, Zustand, Jotai, or Recoil for managing global state. Avoid Redux unless necessary.
Use react-hook-form for managing forms and validation.
Only fetch the data that is needed by the component to avoid over-fetching.
Avoid long-running synchronous operations in the main thread to prevent blocking.
Always use setState or hooks to update state instead of mutating state directly.
Include a complete dependency array in useEffect hooks to prevent unexpected behavior.
Avoid writing server-side code in client components to prevent exposing secrets or causing unexpected behavior.
Use try...catch blocks for handling errors in asynchronous operations.
Implement error boundary components using getDerivedStateFromError or componentDidCatch lifecycle methods.
Sanitize user input to prevent Cross-Site Scripting (XSS) attacks. Be especially careful when rendering HTML directly from user input.
Store authentication tokens in HTTP-only cookies or local storage securely.
Implement role-based access control to restrict access to sensitive resources.
Clean up event listeners and timers in useEffect hooks to avoid memory leaks.
Only update state when necessary to reduce the number of re-renders and improve performance.
Use immutable data structures and avoid mutating data directly to prevent unexpected...

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • eslint.config.js
  • src/mastra/tools/editor-agent-tool.ts
  • app/networks/providers/network-context.tsx
  • src/mastra/tools/copywriter-agent-tool.ts
  • app/workflows/providers/workflow-context.tsx
  • src/mastra/tools/document-chunking.tool.ts
  • app/chat/providers/chat-context.tsx
**/*.{js,ts}

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

Use parameterized queries or an ORM to prevent SQL injection attacks.

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • eslint.config.js
  • src/mastra/tools/editor-agent-tool.ts
  • src/mastra/tools/copywriter-agent-tool.ts
  • src/mastra/tools/document-chunking.tool.ts
src/mastra/tools/**/*.ts

📄 CodeRabbit inference engine (src/mastra/AGENTS.md)

src/mastra/tools/**/*.ts: Use the createTool pattern with Zod schemas when adding new tools under src/mastra/tools
Use explicit Zod schemas for every tool input/output

Implement tools using createTool({ id, inputSchema, outputSchema, execute }) pattern with strict Zod schemas

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • src/mastra/tools/copywriter-agent-tool.ts
  • src/mastra/tools/document-chunking.tool.ts
src/mastra/{tools,workflows}/**/*.ts

📄 CodeRabbit inference engine (src/mastra/AGENTS.md)

Use RuntimeContext to enforce access control in tools and workflows

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • src/mastra/tools/copywriter-agent-tool.ts
  • src/mastra/tools/document-chunking.tool.ts
**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}

📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)

**/*.{ts,tsx,js,jsx,py,java,cs,rb,go,rs,cpp,c,h,hpp,swift,kotlin,php,scala,clj,groovy,lua,sh,bash}: Write code that speaks for itself. Comment only when necessary to explain WHY, not WHAT. Avoid obvious comments that state what the code literally does.
Avoid redundant comments that simply repeat what the code is doing
Keep comments accurate and up-to-date with code changes. Remove or update outdated comments that no longer match the implementation.
Write comments for complex business logic that explain the WHY behind specific calculations or business rules
Document non-obvious algorithms with comments explaining the algorithm choice and its reasoning
Add comments explaining what regex patterns match, especially for complex patterns
Document API constraints, rate limits, gotchas, and external dependencies with explanatory comments
Avoid commenting out dead code. Use version control instead of maintaining commented code blocks.
Do not maintain code change history or modification logs as comments. Rely on git history and commit messages instead.
Avoid decorative divider comments (e.g., lines of equals signs or asterisks) for section separation
Ensure comments are placed appropriately above or adjacent to the code they describe
Write comments using proper grammar, spelling, and professional language
Prefer self-documenting code with clear variable/function names over adding comments to explain unclear code

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • eslint.config.js
  • src/mastra/tools/editor-agent-tool.ts
  • app/networks/providers/network-context.tsx
  • src/mastra/tools/copywriter-agent-tool.ts
  • app/workflows/providers/workflow-context.tsx
  • src/mastra/tools/document-chunking.tool.ts
  • app/chat/providers/chat-context.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)

**/*.{ts,tsx,js,jsx}: Document public APIs with TSDoc/JSDoc comments including parameter descriptions, return types, examples, and thrown exceptions
Add TSDoc comments to configuration constants and environment variables explaining their source, reasoning, or constraints
Use TSDoc annotation tags (TODO, FIXME, HACK, NOTE, WARNING, PERF, SECURITY, BUG, REFACTOR, DEPRECATED) to mark special comments
Include file headers with @fileoverview, @author, @copyright, and @license tags to document file purpose and ownership
Document function parameters with @param tags, return values with @returns tags, and exceptions with @throws tags in TSDoc comments
Use @see tags in TSDoc comments to reference related functions, methods, or documentation
Include @example tags in public API documentation with code examples showing typical usage

**/*.{ts,tsx,js,jsx}: Use Mastra mcp tools (#mastradocs, #mastraChanges, #mastraexamples, #mastraBlog) for Mastra framework development to stay updated with latest features and best practices
When working with Next.js projects, always utilize the next-devtools-mcp server for all Next.js related queries

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • eslint.config.js
  • src/mastra/tools/editor-agent-tool.ts
  • app/networks/providers/network-context.tsx
  • src/mastra/tools/copywriter-agent-tool.ts
  • app/workflows/providers/workflow-context.tsx
  • src/mastra/tools/document-chunking.tool.ts
  • app/chat/providers/chat-context.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/instructions/self-explanatory-code-commenting.instructions.md)

**/*.{ts,tsx}: Document interface and type definitions with TSDoc comments explaining their purpose and usage context
Document interface properties with /** */ comments explaining each field's purpose and constraints
Document generic type parameters with @template tags explaining what each type parameter represents
Use type guards with comments explaining the runtime validation logic being performed
Document advanced/complex TypeScript types with explanatory comments about their purpose and use cases

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • app/networks/providers/network-context.tsx
  • src/mastra/tools/copywriter-agent-tool.ts
  • app/workflows/providers/workflow-context.tsx
  • src/mastra/tools/document-chunking.tool.ts
  • app/chat/providers/chat-context.tsx
src/mastra/**/*

📄 CodeRabbit inference engine (src/AGENTS.md)

mastra modules can import from utils, but must not import from app or cli (except types)

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/AGENTS.md
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • src/mastra/tools/copywriter-agent-tool.ts
  • src/mastra/tools/document-chunking.tool.ts
**/*.{css,tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS 4 with oklch color variables for styling

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • app/networks/providers/network-context.tsx
  • src/mastra/tools/copywriter-agent-tool.ts
  • app/workflows/providers/workflow-context.tsx
  • src/mastra/tools/document-chunking.tool.ts
  • app/chat/providers/chat-context.tsx
src/mastra/{tools,agents,workflows}/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use Zod schemas for strict input/output validation in tools, agents, and workflows

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • src/mastra/tools/copywriter-agent-tool.ts
  • src/mastra/tools/document-chunking.tool.ts
src/mastra/tools/**/*.{ts,tool.ts}

📄 CodeRabbit inference engine (src/mastra/tools/AGENTS.md)

All tool exports must be named exports matching the pattern {descriptiveName}Tool and must include Zod input/output schemas

Files:

  • src/mastra/tools/extractLearningsTool.ts
  • src/mastra/tools/evaluateResultTool.ts
  • src/mastra/tools/financial-chart-tools.ts
  • src/mastra/tools/editor-agent-tool.ts
  • src/mastra/tools/copywriter-agent-tool.ts
  • src/mastra/tools/document-chunking.tool.ts
src/mastra/tools/*financial-chart*.ts

📄 CodeRabbit inference engine (src/mastra/tools/AGENTS.md)

Financial chart tools must orchestrate data processing through dedicated processors before chart generation

Files:

  • src/mastra/tools/financial-chart-tools.ts
**/app/**

📄 CodeRabbit inference engine (.github/instructions/next-js.instructions.md)

Use the app/ directory structure for route handlers, server components, and client components (Next.js 13+). Prefer this over the pages/ directory for new projects.

Files:

  • app/networks/providers/network-context.tsx
  • app/workflows/providers/workflow-context.tsx
  • app/chat/providers/chat-context.tsx
app/**/*.{tsx,ts}

📄 CodeRabbit inference engine (app/AGENTS.md)

app/**/*.{tsx,ts}: Use Tailwind CSS 4 with oklch color variables for styling in Next.js App Router pages and layouts
Use React 19 latest features in component implementations within the app directory

Files:

  • app/networks/providers/network-context.tsx
  • app/workflows/providers/workflow-context.tsx
  • app/chat/providers/chat-context.tsx
app/networks/**/*.tsx

📄 CodeRabbit inference engine (app/networks/AGENTS.md)

app/networks/**/*.tsx: Use useChat from @ai-sdk/react with DefaultChatTransport for streaming responses from the /network route in the networks feature
Support real-time streaming with stop/cancel functionality, reasoning visualization for chain-of-thought models, and tool invocation display showing agent tool calls
Provide a responsive layout with collapsible sidebar on mobile for the networks feature

Files:

  • app/networks/providers/network-context.tsx
app/networks/providers/network-context.tsx

📄 CodeRabbit inference engine (app/networks/AGENTS.md)

Implement state management using useNetworkContext() hook that provides selectedNetwork, networkConfig, networkStatus, messages, streamingOutput, routingSteps, and control functions (sendMessage, stopExecution, clearHistory)

Files:

  • app/networks/providers/network-context.tsx
app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Frontend uses Next.js 16 App Router with React 19; use shadcn/ui base components (34 components) from ui/ directory

Files:

  • app/networks/providers/network-context.tsx
  • app/workflows/providers/workflow-context.tsx
  • app/chat/providers/chat-context.tsx
app/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Use @ai-sdk/react for streaming and AI interactions in React components

Files:

  • app/networks/providers/network-context.tsx
  • app/workflows/providers/workflow-context.tsx
  • app/chat/providers/chat-context.tsx
app/workflows/providers/workflow-context.tsx

📄 CodeRabbit inference engine (app/workflows/AGENTS.md)

app/workflows/providers/workflow-context.tsx: State management in workflow-context.tsx should use useChat hook from @ai-sdk/react with DefaultChatTransport for real-time streaming
Workflow-context.tsx should provide WorkflowContextValue interface with state management for selectedWorkflow, workflowStatus, currentRun, activeStepIndex, and streaming data

Files:

  • app/workflows/providers/workflow-context.tsx
src/mastra/tools/**/*.tool.ts

📄 CodeRabbit inference engine (src/mastra/tools/AGENTS.md)

src/mastra/tools/**/*.tool.ts: All tools must emit progress events with type 'data-tool-progress' containing status ('in-progress' or 'done'), message, and stage fields, with id placed outside the data object
Data validation in tools must use Zod schemas for runtime validation

Files:

  • src/mastra/tools/document-chunking.tool.ts
app/chat/providers/chat-context.tsx

📄 CodeRabbit inference engine (app/chat/AGENTS.md)

app/chat/providers/chat-context.tsx: Use ChatContext provider with AI SDK v5 types in chat-context.tsx to manage chat state, agent selection, and streaming messages across the application
Use DefaultChatTransport from @ai-sdk/react with the Mastra /chat route endpoint, configure prepareSendMessagesRequest to include resourceId and agentId in the request body for proper agent routing

Files:

  • app/chat/providers/chat-context.tsx
🧬 Code graph analysis (5)
src/mastra/tools/extractLearningsTool.ts (2)
src/mastra/index.ts (1)
  • mastra (95-488)
src/mastra/config/logger.ts (1)
  • log (14-18)
src/mastra/tools/evaluateResultTool.ts (1)
src/mastra/agents/evaluationAgent.ts (1)
  • evaluationAgent (18-140)
src/mastra/tools/financial-chart-tools.ts (1)
src/mastra/agents/recharts.ts (4)
  • chartSupervisorAgent (378-539)
  • chartGeneratorAgent (237-372)
  • chartDataProcessorAgent (131-231)
  • chartTypeAdvisorAgent (44-125)
src/mastra/tools/editor-agent-tool.ts (1)
src/mastra/agents/editorAgent.ts (1)
  • editorAgent (18-133)
src/mastra/tools/document-chunking.tool.ts (2)
src/mastra/config/logger.ts (3)
  • logStepStart (72-88)
  • logError (153-174)
  • log (14-18)
src/mastra/config/pg-storage.ts (1)
  • pgVector (77-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: CodeQL analysis (javascript-typescript)
  • GitHub Check: Agent
  • GitHub Check: Codacy Security Scan
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (12)
eslint.config.js (1)

65-66: No breaking change from previous configuration - this is a new ESLint setup.

The eslint.config.js file is newly created (not modifying an existing configuration), and the codebase already has no underscore-prefixed unused variables in the linted source files. The concern about a breaking change requiring widespread refactoring is unfounded, as the strict no-unused-vars rules are already compatible with the current codebase.

Likely an incorrect or invalid review comment.

src/mastra/tools/document-chunking.tool.ts (2)

511-517: The review incorrectly targets the code. Lines 511–517 are correct; the bug exists elsewhere.

According to Mastra RAG documentation, MDocument.chunk() expects separators: string[] (plural, array) for the character strategy.

  • Lines 511–517 (mdocumentChunker): Already correctly use separators: ['\n']
  • Lines ~255–261 (mastraChunker): Incorrectly use separator: '\n' (singular) and should be fixed to separators: ['\n']

The review points to the wrong location and its suggested fix would make correct code incorrect.

Likely an incorrect or invalid review comment.


883-897: Verify the rerank() function contract and result shape to ensure defensive text mapping is necessary.

The defensive text selection pattern (result.metadata?.text as string) ?? (typeof result.metadata?.text === 'undefined' ? '' : String(result.metadata?.text)) suggests potential type safety issues between what rerank() returns and what this tool expects. Without clear type definitions for the rerank result shape (specifically where text, score, metadata, and id fields are located), this pattern may indicate either:

  • A type mismatch that needs addressing in the rerank() contract
  • Unnecessary defensive code that can be simplified

If the rerank input/output types are documented but complex, consider extracting this mapping logic into a dedicated adapter function to improve readability and maintainability.

Also applies to lines 911-925.

src/mastra/tools/AGENTS.md (1)

135-136: LGTM!

The added note effectively cross-references the task documentation and provides helpful context about the standardization effort.

src/mastra/tools/evaluateResultTool.ts (3)

78-89: LGTM: Error handling in streaming path is thorough.

The error path correctly records the exception, sets span status to ERROR, ends the span, emits a final progress event, and returns a consistent failure response.


54-56: LGTM: Agent retrieval pattern is correct.

The fallback pattern context?.mastra?.getAgent?.('evaluationAgent') ?? evaluationAgent correctly prefers the runtime-registered agent while falling back to the imported agent.


64-70: The pipeTo() + await text pattern is valid and documented as the standard approach.

The codebase documentation (copilot-rules.md) explicitly recommends this exact pattern: pipe textStream / fullStream to the writer for UI updates, then await stream.text for final text. The MastraModelOutput buffers text independently, so await stream.text does not fail after pipeTo(). This pattern is consistently used across 10+ tool and workflow files.

The type cast as unknown as WritableStream is a pragmatic workaround used throughout the codebase. While WritableStream compatibility should ideally be enforced at the context type level, this is a localized code quality issue rather than a runtime bug—most implementations function correctly. Consider using runtime type checks (as shown in weather-workflow.ts) for additional safety, but this is not blocking.

src/mastra/tools/editor-agent-tool.ts (1)

149-155: LGTM: Return value construction with fallbacks.

The return statement correctly provides fallback values for all fields, ensuring a valid response shape even when the agent returns unexpected data.

src/mastra/tools/copywriter-agent-tool.ts (3)

225-227: Unusual defensive try-catch around span.setStatus.

This defensive pattern isn't used in other tools and may mask underlying issues with the span's state. If setStatus can fail, consider investigating why rather than silently ignoring.

Is there a known issue where span.setStatus can throw? If not, this try-catch may hide bugs.


212-222: LGTM: Response object handling with null guard.

The Boolean(responseObject) && typeof responseObject === 'object' check correctly handles the JavaScript quirk where typeof null === 'object'.


108-130: LGTM: Thorough agent capability validation.

The validation for generate and stream methods with a graceful fallback return provides a good user experience when the agent is unavailable.

src/mastra/tools/extractLearningsTool.ts (1)

59-74: LGTM: Graceful handling when Mastra or agent is unavailable.

The early returns with meaningful messages and proper span cleanup provide a good user experience when the runtime context is incomplete.


const sendMessage = useCallback(
(text: string, _files?: File[]) => {
(text: string, files?: File[]) => {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent parameter naming: removed underscore from unused parameter.

The parameter name was changed from _files to files, but:

  1. The parameter is not used in the function body (lines 325-328)
  2. The interface definition at line 95 still uses _files with the underscore prefix
  3. Removing the underscore suggests the parameter should be used, but it isn't

The underscore prefix is a convention for intentionally unused parameters (especially important with no-unused-vars ESLint rules).

Either keep the underscore prefix for consistency:

-    (text: string, files?: File[]) => {
+    (text: string, _files?: File[]) => {

Or implement file handling if the parameter is meant to be used:

     (text: string, files?: File[]) => {
       if (!text.trim() || isLoading) {return}
       setChatError(null)
-      aiSendMessage({ text: text.trim() })
+      aiSendMessage({ 
+        text: text.trim(),
+        // Handle files if needed
+      })
     },

Note: The interface at line 95 should also be updated to match whichever approach you choose.

🤖 Prompt for AI Agents
In app/chat/providers/chat-context.tsx around line 324, the parameter name was
changed from `_files` to `files` but the parameter is unused (and the interface
at line 95 still uses `_files`), causing inconsistent naming and confusing
intent; restore the underscore to indicate an intentionally unused parameter by
renaming the parameter back to `_files` here and update the interface at line 95
to match, OR if file handling is intended, implement the file processing logic
inside the function and update the interface at line 95 to use `files` (ensuring
ESLint no-unused-vars compliance and consistent names across both declaration
and implementation).

const eventData = progressPart.data

if (eventData?.status && (eventData.status === "in-progress" || eventData.status === "done" || eventData.status === "error")) {
if (typeof eventData?.status === 'string' && (eventData.status === "in-progress" || eventData.status === "done")) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd /repo && head -50 app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

cd /repo && sed -n '30,45p' app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

cd /repo && sed -n '325,340p' app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

cd /repo && rg -n 'data-tool-progress' --type=tsx -A 8

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

cd /repo && rg -n 'ProgressEvent' --type=tsx -B 2 -A 5

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

cd /repo && rg -n 'data-tool-error' --type=tsx -A 5

Repository: ssdeanx/AgentStack

Length of output: 117


🏁 Script executed:

wc -l app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 108


🏁 Script executed:

sed -n '30,45p' app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 324


🏁 Script executed:

sed -n '325,340p' app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 937


🏁 Script executed:

rg -n 'data-tool-progress' --type=tsx -A 8

Repository: ssdeanx/AgentStack

Length of output: 89


🏁 Script executed:

rg -n 'ProgressEvent' --type=tsx -B 2 -A 5

Repository: ssdeanx/AgentStack

Length of output: 89


🏁 Script executed:

rg -n 'status.*error' app/networks/providers/network-context.tsx -B 2 -A 2

Repository: ssdeanx/AgentStack

Length of output: 692


🏁 Script executed:

rg -n 'data-tool-error' app/networks/providers/network-context.tsx -B 2 -A 5

Repository: ssdeanx/AgentStack

Length of output: 44


🏁 Script executed:

rg -n 'status.*error\|error.*status' app/networks/providers/network-context.tsx -B 3 -A 3

Repository: ssdeanx/AgentStack

Length of output: 44


🏁 Script executed:

grep -n 'part\.type' app/networks/providers/network-context.tsx | head -20

Repository: ssdeanx/AgentStack

Length of output: 728


🏁 Script executed:

sed -n '275,360p' app/networks/providers/network-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 3772


🏁 Script executed:

find . -name "workflow-context.tsx" -o -name "workflow-context.ts"

Repository: ssdeanx/AgentStack

Length of output: 108


🏁 Script executed:

sed -n '380,430p' app/workflows/providers/workflow-context.tsx

Repository: ssdeanx/AgentStack

Length of output: 2606


🏁 Script executed:

grep -n 'status.*error\|error.*status' app/workflows/providers/workflow-context.tsx -B 2 -A 2

Repository: ssdeanx/AgentStack

Length of output: 945


Include "error" status in the data-tool-progress condition to match the ProgressEvent interface and workflow-context.tsx pattern.

The status check at line 331 excludes "error", causing progress events with status: "error" to be silently dropped. The ProgressEvent interface (line 37) defines status as "in-progress" | "done" | "error", and workflow-context.tsx (line 399-400) explicitly includes all three statuses when handling similar data-workflow-progress events.

Change line 331 from:

if (typeof eventData?.status === 'string' && (eventData.status === "in-progress" || eventData.status === "done"))

To:

if (typeof eventData?.status === 'string' && (eventData.status === "in-progress" || eventData.status === "done" || eventData.status === "error"))
🤖 Prompt for AI Agents
In app/networks/providers/network-context.tsx around line 331, the conditional
that filters data-tool-progress events only allows "in-progress" and "done"
statuses and therefore drops "error" events; update the check to also accept
eventData.status === "error" so it matches the ProgressEvent interface and the
pattern used in workflow-context.tsx, ensuring error status events are processed
the same way as the other statuses.

Comment on lines +167 to +177
```typescript
await context?.writer?.custom({
type: 'data-tool-progress',
data: {
status: 'in-progress',
message: `📈 Fetching tool-id data for ${inputData.symbol}/${inputData.market}`,
stage: 'tool-id'
},
id: 'tool-id'
});
```
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Improve consistency of placeholder values in example.

The progress event example mixes generic placeholders ("tool-id") with specific financial API fields (inputData.symbol, inputData.market), creating confusion about what values should be used.

Either use fully generic placeholders:

 await context?.writer?.custom({
   type: 'data-tool-progress',
   data: {
     status: 'in-progress',
-    message: `📈 Fetching tool-id data for ${inputData.symbol}/${inputData.market}`,
+    message: `Processing ${toolName} with input: ${inputData.param}`,
     stage: 'tool-id'
   },
   id: 'tool-id'
 });

Or use a complete real-world example:

 await context?.writer?.custom({
   type: 'data-tool-progress',
   data: {
     status: 'in-progress',
     message: `📈 Fetching Alpha Vantage crypto data for ${inputData.symbol}/${inputData.market}`,
-    stage: 'tool-id'
+    stage: 'alpha-vantage-crypto'
   },
-  id: 'tool-id'
+  id: 'alpha-vantage-crypto'
 });

The second approach matches the real example shown in AGENTS.md (lines 124-132) and provides clearer guidance.

📝 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
```typescript
await context?.writer?.custom({
type: 'data-tool-progress',
data: {
status: 'in-progress',
message: `📈 Fetching tool-id data for ${inputData.symbol}/${inputData.market}`,
stage: 'tool-id'
},
id: 'tool-id'
});
```
🤖 Prompt for AI Agents
In memory-bank/copilot-rules.md around lines 167 to 177, the progress event
example mixes generic placeholders ("tool-id") with concrete fields
(inputData.symbol/inputData.market); update the example for consistency by
choosing one style and applying it throughout—either replace the specific fields
with generic placeholders (e.g., ${symbol}/${market}) and keep id as 'tool-id',
or convert id to a realistic value and use a complete real-world example
matching AGENTS.md (lines 124-132); ensure the chosen approach is applied to all
keys (type, data.status, data.message, data.stage, id) and update the message
text accordingly so placeholders are consistent across the snippet.

- Status check → + progress.md
```

Note: For tool implementation tasks, consult `memory-bank/tasks/TASK001-tool-streaming.md` which documents the standard streaming and progress-event conventions (use `context.writer` with `data-tool-progress` start/in-progress/done events, and prefer `agent.stream()` with `MastraModelOutput` when available). Update the task scratchpad with any deviations or agent-specific details.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Excessive line length in markdown documentation.

Line 40 exceeds 300 characters, violating the project's markdown guideline to limit lines to 80 characters for readability.

Apply this diff to reformat the note with proper line breaks:

-Note: For tool implementation tasks, consult `memory-bank/tasks/TASK001-tool-streaming.md` which documents the standard streaming and progress-event conventions (use `context.writer` with `data-tool-progress` start/in-progress/done events, and prefer `agent.stream()` with `MastraModelOutput` when available). Update the task scratchpad with any deviations or agent-specific details.
+Note: For tool implementation tasks, consult
+`memory-bank/tasks/TASK001-tool-streaming.md` which documents the standard
+streaming and progress-event conventions (use `context.writer` with
+`data-tool-progress` start/in-progress/done events, and prefer
+`agent.stream()` with `MastraModelOutput` when available). Update the task
+scratchpad with any deviations or agent-specific details.

As per coding guidelines, limit line length to 80 characters in markdown for readability.

📝 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
Note: For tool implementation tasks, consult `memory-bank/tasks/TASK001-tool-streaming.md` which documents the standard streaming and progress-event conventions (use `context.writer` with `data-tool-progress` start/in-progress/done events, and prefer `agent.stream()` with `MastraModelOutput` when available). Update the task scratchpad with any deviations or agent-specific details.
Note: For tool implementation tasks, consult
`memory-bank/tasks/TASK001-tool-streaming.md` which documents the standard
streaming and progress-event conventions (use `context.writer` with
`data-tool-progress` start/in-progress/done events, and prefer
`agent.stream()` with `MastraModelOutput` when available). Update the task
scratchpad with any deviations or agent-specific details.
🤖 Prompt for AI Agents
In memory-bank/memory-bank-instructions.md around line 40, the Note paragraph
exceeds the project's 80-character markdown line-length rule; reflow the
sentence into multiple lines no longer than 80 characters, preserving all
content and inline code/backticks (e.g.,
`memory-bank/tasks/TASK001-tool-streaming.md`, `context.writer`,
`data-tool-progress`, `agent.stream()`, `MastraModelOutput`), and ensure the
final wrapped paragraph reads naturally and keeps the instruction to update the
task scratchpad with any deviations.

@@ -1 +1 @@
# [Task 001] - Implement Tool Streaming with Writer in ALL Tools\n\n**Status:** In Progress \n**Added:** 2025-11-22 \n**Updated:** 2025-11-22\n\n## Original Request\n\nUser: Fetch Mastra tool streaming docs, implement in #file:tools. Clarified: ALL tools use writer directly, no utility.\n\n## Thought Process\n\nMastra docs: execute({context, writer?}): await writer?.write({type:'custom-event'| 'progress', ...}); return result. 12 tools need surgical updates: add writer param, emit start/progress/end.\n\n## Implementation Plan\n\n- Create tasks structure\n- Update all 12 .tool.ts executes\n- Add streaming tests\n- Update AGENTS.md\n\n## Progress Tracking\n\n**Overall Status:** In Progress - 10%\n\n### Subtasks\n\n| ID | Description | Status | Updated | Notes \n|-----|--------------------------------------|-------------|-------------|-------\n| 1.1 | Create tasks/ folder & files | Complete | 2025-11-22 | Done\n| 1.2 | Read all tool files | In Progress | 2025-11-22 | 3 read, 9 pending\n| 1.3 | Edit weather-tool.ts | Not Started | | \n| 1.4 | Edit serpapi-search.tool.ts | Not Started | | \n| ... | Edit remaining tools | Not Started | | \n| 1.x | Tests & AGENTS.md | Not Started | | \n\n## Progress Log\n\n### 2025-11-22\n- Created tasks structure\n- Read 3 sample tools\n- Planning batch edits\n No newline at end of file
# [Task 001] - Implement Tool Streaming with Writer in ALL Tools\n\n**Status:** In Progress \n**Added:** 2025-11-22 \n**Updated:** 2025-11-22\n\n## Original Request\n\nUser: Fetch Mastra tool streaming docs, implement in #file:tools. Clarified: ALL tools use writer directly, no utility.\n\n## Thought Process\n\nMastra docs: execute({context, writer?}): await writer?.write({type:'custom-event'| 'progress', ...}); return result. 12 tools need surgical updates: add writer param, emit start/progress/end.\n\n## Implementation Plan\n\n- Create tasks structure\n- Update all 12 .tool.ts executes\n- Add streaming tests\n- Update AGENTS.md\n\n## Progress Tracking\n\n**Overall Status:** In Progress - 10%\n\n### Subtasks\n\n| ID | Description | Status | Updated | Notes \n|-----|--------------------------------------|-------------|-------------|-------\n| 1.1 | Create tasks/ folder & files | Complete | 2025-11-22 | Done\n| 1.2 | Read all tool files | In Progress | 2025-11-22 | 3 read, 9 pending\n| 1.3 | Edit weather-tool.ts | Not Started | | \n| 1.4 | Edit serpapi-search.tool.ts | Not Started | | \n| ... | Edit remaining tools | Not Started | | \n| 1.x | Tests & AGENTS.md | Not Started | | \n\n## Progress Log\n\n### 2025-11-22\n- Created tasks structure\n- Read 3 sample tools\n- Planning batch edits\n
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect file format: markdown stored as escaped single-line string.

This markdown file is stored as a single line with \n escape sequences instead of actual line breaks. Markdown files should use proper multi-line formatting for readability and maintainability.

The content should be reformatted as a proper multi-line markdown file. For example, the beginning should be:

-# [Task 001] - Implement Tool Streaming with Writer in ALL Tools\n\n**Status:** In Progress  \n**Added:** 2025-11-22  \n**Updated:** 2025-11-22\n\n## Original Request\n\nUser: Fetch Mastra tool streaming docs, implement in #file:tools. Clarified: ALL tools use writer directly, no utility.\n\n## Thought Process\n\nMastra docs: execute({context, writer?}): await writer?.write({type:'custom-event'| 'progress', ...}); return result. 12 tools need surgical updates: add writer param, emit start/progress/end.\n\n## Implementation Plan\n\n- Create tasks structure\n- Update all 12 .tool.ts executes\n- Add streaming tests\n- Update AGENTS.md\n\n## Progress Tracking\n\n**Overall Status:** In Progress - 10%\n\n### Subtasks\n\n| ID  | Description                          | Status      | Updated     | Notes \n|-----|--------------------------------------|-------------|-------------|-------\n| 1.1 | Create tasks/ folder & files         | Complete    | 2025-11-22 | Done\n| 1.2 | Read all tool files                  | In Progress | 2025-11-22 | 3 read, 9 pending\n| 1.3 | Edit weather-tool.ts                 | Not Started |             | \n| 1.4 | Edit serpapi-search.tool.ts          | Not Started |             | \n| ... | Edit remaining tools                 | Not Started |             | \n| 1.x | Tests & AGENTS.md                    | Not Started |             | \n\n## Progress Log\n\n### 2025-11-22\n- Created tasks structure\n- Read 3 sample tools\n- Planning batch edits\n
+# [Task 001] - Implement Tool Streaming with Writer in ALL Tools
+
+**Status:** In Progress  
+**Added:** 2025-11-22  
+**Updated:** 2025-11-22
+
+## Original Request
+
+User: Fetch Mastra tool streaming docs, implement in #file:tools. Clarified: ALL tools use writer directly, no utility.
+
+## Thought Process
+
+Mastra docs: execute({context, writer?}): await writer?.write({type:'custom-event'| 'progress', ...}); return result. 12 tools need surgical updates: add writer param, emit start/progress/end.
+
+## Implementation Plan
+
+- Create tasks structure
+- Update all 12 .tool.ts executes
+- Add streaming tests
+- Update AGENTS.md
+
+## Progress Tracking
+
+**Overall Status:** In Progress - 10%
+
+### Subtasks
+
+| ID  | Description                          | Status      | Updated     | Notes |
+|-----|--------------------------------------|-------------|-------------|-------|
+| 1.1 | Create tasks/ folder & files         | Complete    | 2025-11-22 | Done  |
+| 1.2 | Read all tool files                  | In Progress | 2025-11-22 | 3 read, 9 pending |
+| 1.3 | Edit weather-tool.ts                 | Not Started |             |       |
+| 1.4 | Edit serpapi-search.tool.ts          | Not Started |             |       |
+| ... | Edit remaining tools                 | Not Started |             |       |
+| 1.x | Tests & AGENTS.md                    | Not Started |             |       |
+
+## Progress Log
+
+### 2025-11-22
+- Created tasks structure
+- Read 3 sample tools
+- Planning batch edits

As per coding guidelines, limit line length to 80 characters in markdown for readability and use proper whitespace between sections.

🤖 Prompt for AI Agents
In memory-bank/tasks/TASK001-tool-streaming.md around lines 1 to 1, the markdown
content is stored as a single-line string containing literal "\n" sequences
instead of real line breaks; convert it into a proper multi-line markdown file
by replacing the escaped "\n" with actual newlines, restoring the intended
headings/paragraphs and list formatting, break long lines to a maximum of ~80
characters for readability, and ensure proper blank lines between sections
(headings, lists, code blocks) per markdown conventions.

Comment on lines +54 to +56
const truncatedContent = (result?.content ?? '').slice(0, 8000);
const contentWithTruncation = (result?.content ?? '').length > 8000 ? truncatedContent + 'AAAA...' : truncatedContent;

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Likely typo: 'AAAA...' as truncation indicator.

The string 'AAAA...' appended to truncated content looks like a typo. Consider using a more descriptive indicator.

       const truncatedContent = (result?.content ?? '').slice(0, 8000);
-      const contentWithTruncation = (result?.content ?? '').length > 8000 ? truncatedContent + 'AAAA...' : truncatedContent;
+      const contentWithTruncation = (result?.content ?? '').length > 8000 ? truncatedContent + '... [truncated]' : truncatedContent;
📝 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
const truncatedContent = (result?.content ?? '').slice(0, 8000);
const contentWithTruncation = (result?.content ?? '').length > 8000 ? truncatedContent + 'AAAA...' : truncatedContent;
const truncatedContent = (result?.content ?? '').slice(0, 8000);
const contentWithTruncation = (result?.content ?? '').length > 8000 ? truncatedContent + '... [truncated]' : truncatedContent;
🤖 Prompt for AI Agents
In src/mastra/tools/extractLearningsTool.ts around lines 54 to 56, the
truncation suffix currently uses the string 'AAAA...' which appears to be a
typo; replace it with a clear truncation indicator such as '... (truncated)' or
'… (truncated)' to make it obvious content was cut off, e.g., compute
truncatedContent as before and set contentWithTruncation to truncatedContent +
'... (truncated)' when the original length exceeds 8000.

Comment on lines +77 to +92
if (typeof agent.stream === 'function') {
// Use MastraModelOutput for accurate typing and pipe fullStream into the writer (Mastra nested-agent pattern)
await writer?.custom({ type: 'data-tool-progress', data: { status: 'in-progress', message: '🔁 Streaming learnings from agent', stage: 'extract-learnings' }, id: 'extract-learnings' });
const stream = await agent.stream(prompt) as MastraModelOutput | undefined;
if (stream?.fullStream !== undefined && writer) { await stream.fullStream.pipeTo(writer as unknown as WritableStream) }

if (stream) {
const text = (await stream.text) ?? '';
try { responseObject = stream.object ?? (text ? JSON.parse(text) : {}) } catch { responseObject = {} }
} else {
responseObject = {}
}
} else {
const response = await agent.generate(prompt);
try { responseObject = response.object ?? (response.text ? JSON.parse(response.text) : {}) } catch { responseObject = {} }
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing textStream fallback in streaming path.

Unlike other tools (e.g., editorTool, evaluateResultTool), this tool only checks fullStream and doesn't fall back to textStream. This may result in lost streaming output for agents that only provide textStream.

Add textStream fallback:

       if (typeof agent.stream === 'function') {
         await writer?.custom({ type: 'data-tool-progress', data: { status: 'in-progress', message: '🔁 Streaming learnings from agent', stage: 'extract-learnings' }, id: 'extract-learnings' });
         const stream = await agent.stream(prompt) as MastraModelOutput | undefined;
-        if (stream?.fullStream !== undefined && writer) { await stream.fullStream.pipeTo(writer as unknown as WritableStream) }
+        if (stream?.fullStream && writer) {
+          await stream.fullStream.pipeTo(writer as unknown as WritableStream);
+        } else if (stream?.textStream && writer) {
+          await stream.textStream.pipeTo(writer as unknown as WritableStream);
+        }
📝 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
if (typeof agent.stream === 'function') {
// Use MastraModelOutput for accurate typing and pipe fullStream into the writer (Mastra nested-agent pattern)
await writer?.custom({ type: 'data-tool-progress', data: { status: 'in-progress', message: '🔁 Streaming learnings from agent', stage: 'extract-learnings' }, id: 'extract-learnings' });
const stream = await agent.stream(prompt) as MastraModelOutput | undefined;
if (stream?.fullStream !== undefined && writer) { await stream.fullStream.pipeTo(writer as unknown as WritableStream) }
if (stream) {
const text = (await stream.text) ?? '';
try { responseObject = stream.object ?? (text ? JSON.parse(text) : {}) } catch { responseObject = {} }
} else {
responseObject = {}
}
} else {
const response = await agent.generate(prompt);
try { responseObject = response.object ?? (response.text ? JSON.parse(response.text) : {}) } catch { responseObject = {} }
}
if (typeof agent.stream === 'function') {
// Use MastraModelOutput for accurate typing and pipe fullStream into the writer (Mastra nested-agent pattern)
await writer?.custom({ type: 'data-tool-progress', data: { status: 'in-progress', message: '🔁 Streaming learnings from agent', stage: 'extract-learnings' }, id: 'extract-learnings' });
const stream = await agent.stream(prompt) as MastraModelOutput | undefined;
if (stream?.fullStream && writer) {
await stream.fullStream.pipeTo(writer as unknown as WritableStream);
} else if (stream?.textStream && writer) {
await stream.textStream.pipeTo(writer as unknown as WritableStream);
}
if (stream) {
const text = (await stream.text) ?? '';
try { responseObject = stream.object ?? (text ? JSON.parse(text) : {}) } catch { responseObject = {} }
} else {
responseObject = {}
}
} else {
const response = await agent.generate(prompt);
try { responseObject = response.object ?? (response.text ? JSON.parse(response.text) : {}) } catch { responseObject = {} }
}

Comment on lines +129 to +130
const learningLength = parsed.data.learning.length ?? 0;
const followUpQuestionsCount = parsed.data.followUpQuestions?.length ?? 0;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Minor: Redundant nullish coalescing on learning.length.

Since parsed.data.learning is validated as a string by the Zod schema, .length will always be a number. The ?? 0 is unnecessary for Line 129 (though correct for Line 130 with the optional chaining).

-      const learningLength = parsed.data.learning.length ?? 0;
+      const learningLength = parsed.data.learning.length;
📝 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
const learningLength = parsed.data.learning.length ?? 0;
const followUpQuestionsCount = parsed.data.followUpQuestions?.length ?? 0;
const learningLength = parsed.data.learning.length;
const followUpQuestionsCount = parsed.data.followUpQuestions?.length ?? 0;
🤖 Prompt for AI Agents
In src/mastra/tools/extractLearningsTool.ts around lines 129-130, remove the
redundant nullish coalescing on the validated string length: change the
learningLength assignment to use parsed.data.learning.length (drop the "?? 0"),
and keep the followUpQuestionsCount line unchanged since it needs the optional
chaining and fallback.

Comment on lines +140 to 152
if (typeof agent.stream === 'function') {
const stream = await agent.stream(prompt) as MastraModelOutput | undefined
if (stream?.fullStream) {
await stream.fullStream.pipeTo(writer as unknown as WritableStream)
} else if (stream.textStream) {
} else if (stream?.textStream) {
await stream.textStream.pipeTo(writer as unknown as WritableStream)
}
resultText = (await stream.text) ?? ''
const text = stream?.text ? await stream.text : undefined
resultText = text ?? ''
} else {
const result = await agentWithStream.generate(prompt)
const result = await agent.generate(prompt)
resultText = result.text
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing null check on writer before pipeTo.

Lines 143 and 145 call pipeTo(writer as unknown as WritableStream) without first verifying writer is defined. While the outer context may ensure it exists, explicit guards would prevent potential runtime errors.

Add writer check before piping:

       if (typeof agent.stream === 'function') {
         const stream = await agent.stream(prompt) as MastraModelOutput | undefined
-        if (stream?.fullStream) {
+        if (stream?.fullStream && writer) {
           await stream.fullStream.pipeTo(writer as unknown as WritableStream)
-        } else if (stream?.textStream) {
+        } else if (stream?.textStream && writer) {
           await stream.textStream.pipeTo(writer as unknown as WritableStream)
         }
📝 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
if (typeof agent.stream === 'function') {
const stream = await agent.stream(prompt) as MastraModelOutput | undefined
if (stream?.fullStream) {
await stream.fullStream.pipeTo(writer as unknown as WritableStream)
} else if (stream.textStream) {
} else if (stream?.textStream) {
await stream.textStream.pipeTo(writer as unknown as WritableStream)
}
resultText = (await stream.text) ?? ''
const text = stream?.text ? await stream.text : undefined
resultText = text ?? ''
} else {
const result = await agentWithStream.generate(prompt)
const result = await agent.generate(prompt)
resultText = result.text
}
if (typeof agent.stream === 'function') {
const stream = await agent.stream(prompt) as MastraModelOutput | undefined
if (stream?.fullStream && writer) {
await stream.fullStream.pipeTo(writer as unknown as WritableStream)
} else if (stream?.textStream && writer) {
await stream.textStream.pipeTo(writer as unknown as WritableStream)
}
const text = stream?.text ? await stream.text : undefined
resultText = text ?? ''
} else {
const result = await agent.generate(prompt)
resultText = result.text
}
🤖 Prompt for AI Agents
In src/mastra/tools/financial-chart-tools.ts around lines 140 to 152, the code
calls stream.fullStream.pipeTo(writer as unknown as WritableStream) and
stream.textStream.pipeTo(...) without checking writer; add an explicit guard so
you only call pipeTo when writer is defined (e.g., if (writer) { await
stream.fullStream.pipeTo(writer as unknown as WritableStream) } else { /*
fallback: skip piping or handle error */ }), and ensure the fallback path still
obtains text from stream.text (or throws/returns a meaningful error) so you
avoid runtime exceptions when writer is undefined.

Comment on lines 277 to 282
try {
const agent = context?.mastra?.getAgent('chartGeneratorAgent')
if (!agent) {
const agent = context?.mastra?.getAgent?.('chartGeneratorAgent') ?? chartGeneratorAgent
if (typeof agent.generate !== 'function' && typeof agent.stream !== 'function') {
await context?.writer?.custom({ type: 'data-tool-progress', data: { status: 'done', message: '❌ chartGeneratorAgent not found', stage: 'chart-generator' }, id: 'chart-generator' })
throw new Error('Agent chartGeneratorAgent not found');
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Inconsistent error handling: chartGeneratorTool throws while chartSupervisorTool returns error.

chartSupervisorTool (Line 112-117) returns { success: false, error: ... } when the agent is unavailable, but chartGeneratorTool throws an error. This inconsistency may confuse callers expecting uniform behavior.

Consider standardizing: either all tools return error objects or all throw. Given the output schema includes an optional error field for some tools, returning error objects may be more consistent.

🤖 Prompt for AI Agents
In src/mastra/tools/financial-chart-tools.ts around lines 277 to 282, the code
currently throws an Error when the chartGeneratorAgent is unavailable which is
inconsistent with chartSupervisorTool that returns an error object; change the
behavior to return a standardized error response (e.g., { success: false, error:
'Agent chartGeneratorAgent not found' }) instead of throwing, keep the existing
context.writer.custom call that emits the progress message, and ensure the
returned object matches the same shape used by chartSupervisorTool so callers
can handle errors uniformly.

- Updated access control enforcement in tools and workflows to use `RequestContext` and agent-specific runtime context types.
- Added optional fields `userId` and `researchPhase` to `ResearchRuntimeContext` for improved context handling.
- Imported new agents: `calendarAgent`, `bgColorAgent`, and `danePackagePublisher` into the main index.
- Implemented a new tool `colorChangeTool` to change the background color with a defined input schema.
@ssdeanx ssdeanx closed this Dec 14, 2025
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