Skip to content

feat(mastracode): support external tool injection and auth storage init#13561

Closed
Kitenite wants to merge 19 commits into
mastra-ai:mainfrom
superset-sh:main
Closed

feat(mastracode): support external tool injection and auth storage init#13561
Kitenite wants to merge 19 commits into
mastra-ai:mainfrom
superset-sh:main

Conversation

@Kitenite
Copy link
Copy Markdown
Contributor

@Kitenite Kitenite commented Feb 26, 2026

Summary

  • add createAuthStorage() export so auth providers can be initialized without creating a full createMastraCode instance
  • wire createMastraCode to use createAuthStorage
  • allow createDynamicTools to merge extraTools and wrap tool execution with HookManager pre/post hooks
  • rename imagesfiles in harness sendMessage to use AI SDK FilePart shape (mediaType + optional filename)
  • add unit tests for auth storage wiring, extra tool merging, and hook behavior

Conflict resolution (rebased onto latest main)

  • mastracode/src/agents/tools.ts — merged upstream's safe extra-tool merge (no-overwrite of built-ins) and permissionRules deny filtering with PR's wrapToolWithHooks and hookManager parameter
  • mastracode/src/index.ts — kept createAuthStorage export and agent-after-hooks ordering on top of upstream changes
  • packages/core/src/harness/harness.ts — combined images→files rename with upstream's new tracingContext/tracingOptions params

Validation

  • pnpm -C mastracode test --run src/__tests__/create-auth-storage.test.ts src/agents/__tests__/tools.test.ts

Summary by CodeRabbit

  • New Features

    • Pre/post hooks for tool execution with ability to inject extra tools
    • Centralized auth storage creation wired to providers
    • File attachment support in messages (files with mediaType and optional filename)
  • Tests

    • Tests verifying shared auth storage across providers
    • Tests covering tool execution flow, hooks, blocking, and error handling
  • Chores

    • Fork-sync GitHub Action, README note, and changesets for package bumps

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 26, 2026

🦋 Changeset detected

Latest commit: efdeda2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@mastra/core Patch
mastracode Minor
@mastra/mcp-docs-server Patch
@internal/playground Patch
@mastra/client-js Patch
@mastra/react Patch
@mastra/opencode Patch
@mastra/longmemeval Patch
mastra Patch
@mastra/deployer-cloud Patch
@mastra/playground-ui Patch
@mastra/server Patch
@mastra/deployer Patch
create-mastra Patch
@mastra/express Patch
@mastra/fastify Patch
@mastra/hono Patch
@mastra/koa Patch
@mastra/deployer-cloudflare Patch
@mastra/deployer-netlify Patch
@mastra/deployer-vercel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 26, 2026

@Kitenite is attempting to deploy a commit to the Mastra Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 26, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds exported createAuthStorage and wires it into provider modules; makes createDynamicTools accept extra tools and an optional HookManager and wraps tools with pre/post hooks; renames harness image payloads to files (including stream/type updates); adds related tests and a fork-sync GitHub Actions workflow.

Changes

Cohort / File(s) Summary
Auth Storage Tests
mastracode/src/__tests__/create-auth-storage.test.ts
Adds a test asserting createAuthStorage() returns a single shared AuthStorage instance and registers it with multiple provider modules.
Tool Execution Tests
mastracode/src/agents/__tests__/tools.test.ts
Adds tests for createDynamicTools covering merging extra tools, pre/post hook invocation and sequencing, access blocking by pre-hook, and post-hook behavior when tools throw.
Tool Execution Implementation
mastracode/src/agents/tools.ts
Introduces wrapToolWithHooks and updates createDynamicTools signature to accept extraTools?: Record<string, any> and hookManager?: HookManager; wraps tools to invoke pre/post hooks, support blocking, and propagate errors.
Integration & Auth Wiring
mastracode/src/index.ts
Adds exported createAuthStorage() that instantiates and registers AuthStorage with Claude/OpenAI providers; createMastraCode() now uses it and passes hookManager/extraTools into createDynamicTools.
TUI payload shape
mastracode/src/tui/mastra-tui.ts
Changes MastraTUI.fireMessage to map images from { data, mimeType } to file objects { data, mediaType } and send them under files instead of images.
Harness API & Stream
packages/core/src/harness/harness.ts
Updates Harness.sendMessage to accept files?: Array<{ data: string; mediaType: string; filename?: string }> instead of images; message construction and stream parser now handle file parts (including optional filename).
Harness Types
packages/core/src/harness/types.ts
Extends HarnessMessageContent with a file variant: { type: 'file'; data: string; mediaType: string; filename?: string }.
Repository metadata & workflows
.changeset/*, .github/workflows/sync-upstream-fork.yml, README.md
Adds changesets documenting the API/behavior changes and a scheduled GitHub Actions workflow to sync forks from upstream; README updated to mention the workflow.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: exporting createAuthStorage for standalone auth initialization and adding support for external tool injection via extraTools and HookManager.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
mastracode/src/__tests__/create-auth-storage.test.ts (1)

6-12: Consider test isolation for global state.

This test mutates module-level state in the provider modules. If other tests in the suite rely on auth storage being unset or differently configured, they could fail or behave unexpectedly.

Consider adding cleanup or running this test in isolation:

🧹 Optional: Add afterEach cleanup
+import { afterEach } from 'vitest';
+import { setAuthStorage as resetClaudeAuth } from '../providers/claude-max.js';
+import { setAuthStorage as resetOpenAIAuth } from '../providers/openai-codex.js';
+
 describe('createAuthStorage', () => {
+  afterEach(() => {
+    // Reset to undefined to avoid polluting other tests
+    resetClaudeAuth(undefined as any);
+    resetOpenAIAuth(undefined as any);
+  });
+
   it('wires a shared auth storage instance to provider modules', () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mastracode/src/__tests__/create-auth-storage.test.ts` around lines 6 - 12,
The test mutates global provider state via createAuthStorage and the getters
getClaudeAuthStorage and getOpenAIAuthStorage; add cleanup to restore isolation
by resetting those module-level storages after the test: either call the
appropriate reset/unset functions on the provider modules (or set their internal
storage back to undefined) in an afterEach, or use test framework isolation
(e.g., resetModules) so createAuthStorage only affects the current test,
ensuring other tests won't see the mutated state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@mastracode/src/__tests__/create-auth-storage.test.ts`:
- Around line 6-12: The test mutates global provider state via createAuthStorage
and the getters getClaudeAuthStorage and getOpenAIAuthStorage; add cleanup to
restore isolation by resetting those module-level storages after the test:
either call the appropriate reset/unset functions on the provider modules (or
set their internal storage back to undefined) in an afterEach, or use test
framework isolation (e.g., resetModules) so createAuthStorage only affects the
current test, ensuring other tests won't see the mutated state.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85b54c0 and 7e68adc.

📒 Files selected for processing (4)
  • mastracode/src/__tests__/create-auth-storage.test.ts
  • mastracode/src/agents/__tests__/tools.test.ts
  • mastracode/src/agents/tools.ts
  • mastracode/src/index.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/harness/harness.ts`:
- Around line 1289-1296: In the 'case "file"' branch inside harness.ts you are
silently coercing non-string part.data to '', which masks malformed file
payloads; instead validate that part.data is a string before calling
content.push (in the case 'file' block) and if it's not a string either throw a
descriptive Error or return/report a validation failure (do not replace with an
empty string), preserving mediaType and filename handling (the mediaType
property and filename spread logic) so callers can detect and handle the
malformed record upstream.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e68adc and fd312de.

📒 Files selected for processing (3)
  • mastracode/src/tui/mastra-tui.ts
  • packages/core/src/harness/harness.ts
  • packages/core/src/harness/types.ts

Comment thread packages/core/src/harness/harness.ts
Kitenite and others added 2 commits February 27, 2026 14:49
* feat(harness): rename images→files and use AI SDK FilePart shape

- sendMessage now accepts `files` (matching AI SDK FilePart: data, mediaType, filename)
  instead of `images` (custom shape with mimeType field mismatch)
- Mapping is now a direct passthrough instead of pointless field rename
- Add `type: 'file'` to HarnessMessageContent union for generic file parts
- Handle `file` parts in convertToHarnessMessage for history reload

* fix(mastracode): remap images→files in TUI fireMessage

The harness sendMessage param was renamed from `images` (custom shape)
to `files` (AI SDK FilePart shape). Remap at the TUI boundary so
clipboard paste still works.
Kitenite and others added 2 commits February 27, 2026 14:58
- Add afterEach cleanup in auth storage test for isolation
- Skip malformed file parts (non-string data) instead of silently coercing
- Add changesets for mastracode (minor) and @mastra/core (patch)

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.changeset/huge-boxes-travel.md:
- Line 6: Update the changelog entry to include a concise before/after migration
and a short code example showing how to change calls to the harness sendMessage
API from the old images field to the new files field that matches the AI SDK
FilePart shape (data, mediaType, filename); explicitly show the previous usage
with images and the new usage with files, mention any required import or type
changes (e.g., FilePart) and note that filenames and mediaType are now
required/expected by sendMessage to avoid regressions.

In @.changeset/real-wolves-thank.md:
- Around line 2-6: Update the changeset frontmatter and description so they
match: either add `@mastra/core` to the human-readable description (line
mentioning mastracode-facing behavior) or remove `@mastra/core` from the
frontmatter; ensure the description only refers to packages listed in the
frontmatter. Also add a short usage example for the new public API
createAuthStorage in the description (showing import and a one-line
instantiation/usage) so the changeset documents the new feature. Ensure the
final frontmatter reflects the intended version bumps ('mastracode': minor,
'@mastra/core': patch) and the body lists only applicable package changes plus
the createAuthStorage example.

In @.changeset/thin-walls-bet.md:
- Around line 1-5: The changeset file .changeset/thin-walls-bet.md has an empty
YAML frontmatter (the `---` block) which is invalid; either remove this
changeset file entirely (since it’s an infrastructure-only workflow change) or
replace the empty frontmatter with a valid package entry and change type (e.g.,
`package-name: patch`) so it becomes a proper release changeset; ensure the file
no longer contains only infrastructure notes outside the frontmatter.

In `@mastracode/src/__tests__/create-auth-storage.test.ts`:
- Around line 8-9: Update the setter signatures for setClaudeAuthStorage and
setOpenAIAuthStorage so they accept undefined: change their parameter type to
(storage: AuthStorage | undefined): void and adjust any related type annotations
so the functions assign the passed value directly to the internal nullable state
(which is declared AuthStorage | null); this lets tests call
setClaudeAuthStorage(undefined) and setOpenAIAuthStorage(undefined) without
using type assertions.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fd8e2c and 4811be2.

📒 Files selected for processing (7)
  • .changeset/huge-boxes-travel.md
  • .changeset/real-wolves-thank.md
  • .changeset/thin-walls-bet.md
  • .github/workflows/sync-upstream-fork.yml
  • README.md
  • mastracode/src/__tests__/create-auth-storage.test.ts
  • packages/core/src/harness/harness.ts

Comment thread .changeset/huge-boxes-travel.md Outdated
Comment thread .changeset/real-wolves-thank.md Outdated
Comment on lines +1 to +5
---
---

Added a daily GitHub Action workflow for forks to sync the default branch from `mastra-ai/mastra`.
This is an infrastructure-only change and does not modify published packages.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Empty changeset frontmatter is invalid for release notes.

Line 1–Line 2 has no package entries, and Line 4–Line 5 documents an infrastructure-only change. This should not ship as a package changeset.

potential_issue

As per coding guidelines: "Each changeset file contains a YAML frontmatter at the top. It will be one or more package names followed by a colon and the type of change."

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

In @.changeset/thin-walls-bet.md around lines 1 - 5, The changeset file
.changeset/thin-walls-bet.md has an empty YAML frontmatter (the `---` block)
which is invalid; either remove this changeset file entirely (since it’s an
infrastructure-only workflow change) or replace the empty frontmatter with a
valid package entry and change type (e.g., `package-name: patch`) so it becomes
a proper release changeset; ensure the file no longer contains only
infrastructure notes outside the frontmatter.

Comment on lines +8 to +9
setClaudeAuthStorage(undefined as any);
setOpenAIAuthStorage(undefined as any);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== 1. Locate and read the test file ==="
fd 'create-auth-storage\.test\.ts$' --type f

echo
echo "=== 2. Read the full test file to understand context ==="
cat -n mastracode/src/__tests__/create-auth-storage.test.ts

echo
echo "=== 3. Find auth storage setter functions ==="
find mastracode -name "*.ts" -type f | xargs rg -l "export.*setClaudeAuthStorage|export.*setOpenAIAuthStorage" 2>/dev/null || echo "Searching in broader context..."

echo
echo "=== 4. Search for setAuthStorage/setClaudeAuthStorage/setOpenAIAuthStorage signatures ==="
rg -n "setClaudeAuthStorage|setOpenAIAuthStorage" mastracode/src --type ts -A 2 -B 2

echo
echo "=== 5. Check if 'undefined' is ever used as valid input elsewhere ==="
rg -n "setClaudeAuthStorage|setOpenAIAuthStorage" --type ts -A 1 | grep -E "(undefined|null)" || echo "No undefined/null patterns found"

echo
echo "=== 6. Search for reset patterns in auth-related files ==="
fd 'auth' mastracode/src --type f --glob '*.ts' | head -20

Repository: mastra-ai/mastra

Length of output: 3425


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Find provider files ==="
fd 'claude-max\.ts|openai-codex\.ts' mastracode/src --type f

echo
echo "=== Read claude-max.ts to find setAuthStorage signature ==="
cat -n mastracode/src/providers/claude-max.ts

echo
echo "=== Read openai-codex.ts to find setAuthStorage signature ==="
cat -n mastracode/src/providers/openai-codex.ts

Repository: mastra-ai/mastra

Length of output: 16716


Update auth storage setters to accept undefined for test cleanup.

Lines 8–9 use undefined as any because the setter functions (from claude-max.js and openai-codex.js) are typed to accept only AuthStorage, not undefined. However, their internal state variables are declared as AuthStorage | null, indicating they support nullable values. Update both setter signatures to (storage: AuthStorage | undefined): void to allow typed cleanup without bypassing strict type checking.

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

In `@mastracode/src/__tests__/create-auth-storage.test.ts` around lines 8 - 9,
Update the setter signatures for setClaudeAuthStorage and setOpenAIAuthStorage
so they accept undefined: change their parameter type to (storage: AuthStorage |
undefined): void and adjust any related type annotations so the functions assign
the passed value directly to the internal nullable state (which is declared
AuthStorage | null); this lets tests call setClaudeAuthStorage(undefined) and
setOpenAIAuthStorage(undefined) without using type assertions.

@Kitenite
Copy link
Copy Markdown
Contributor Author

Kitenite commented Mar 3, 2026

Closing in favor of #13611 which includes all changes from this PR (createAuthStorage, extraTools/HookManager, images→files rename) plus the auth routing fix. Description merged into #13611.

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.

4 participants