Skip to content

Commit ee59b74

Browse files
fix(core): fix passing sendSignal through ProcessorRunner and update temporal markers to use sendSignal (#16927)
## Description Adds integration tests for the `sendSignal()` processor API and the `AgentsMDInjector` auto-loading processor, exercising the real `ProcessorRunner` + `MessageList` path (no mocks/test doubles for the message list). **Key finding:** All 16 tests pass at the core processor level, indicating the `sendSignal` mechanism and `AgentsMDInjector` work correctly through `ProcessorRunner` with real `MessageList`. The AGENTS.md auto-loading regression reported in mastracode likely originates at a higher layer (harness, agent loop, or message persistence/rehydration). ### sendSignal-integration.test.ts (9 tests) - Signal from `processInputStep` appears in LLM prompt - Signal metadata preserved through `MessageList` round-trip - Data part emitted to stream writer (`data-system-reminder`) - Response message ID rotation before signal addition - Multiple processors' signals all preserved in message list - `sendSignal` available in `processOutputResult` context - `sendSignal` available in `processAPIError` context - Works without writer - Works without `rotateResponseMessageId` ### agents-md-autoload-integration.test.ts (7 tests) - Auto-loads AGENTS.md when tool call references path near an instruction file - Injected AGENTS.md content appears in LLM prompt (via signal → prompt projection) - Stream data part emitted for the AGENTS.md signal - Duplicate suppression across multiple processor runs (signal-based dedup) - Directory-based tool calls trigger injection - No injection when tool call path has no nearby AGENTS.md - Injection survives across multiple LLM steps ## Related issue(s) Investigates AGENTS.md auto-loading regression after the signals refactor (PR #16438). ## Type of change - [ ] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Code refactoring - [ ] Performance improvement - [x] Test update ## Checklist - [x] I have linked the related issue(s) in the description above - [ ] I have made corresponding changes to the documentation (if applicable) - [x] I have added tests that prove my fix is effective or that my feature works - [ ] I have addressed all Coderabbit comments on this PR Link to Devin session: https://app.devin.ai/sessions/7f81a6b1c3454fe78fe7e6a730cb744d Requested by: @TylerBarnes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## ELI5 This PR adds integration tests that confirm processors can emit persistent "signal" reminders (visible to the model and optionally streamed) and that AGENTS.md files found near tool-call paths are auto-injected as those reminders; it also wires a sendSignal helper into workflow paths so processors get the same sendSignal API as ProcessorRunner. ## Overview - Adds 16 Vitest integration tests exercising sendSignal() and AgentsMDInjector through the real ProcessorRunner + MessageList (no MessageList mocks). - Ensures processors invoked via workflow bridges receive a sendSignal API by exporting and wiring createProcessorSendSignal into workflow/step execution. - Tests indicate sendSignal and AgentsMDInjector behave correctly at the core processor level; the AGENTS.md auto-load regression likely originates above core (harness/agent loop, or message persistence/rehydration). ## Test coverage - sendSignal integration (9 tests — packages/core/src/processors/sendSignal-integration.test.ts) - Verifies sendSignal from processInputStep persists a `signal`-role message and appears in the constructed LLM prompt. - Confirms signal metadata (type/attributes/path) survives a real MessageList round-trip. - Verifies sendSignal emits a `data-system-reminder` stream part when a writer is provided. - Asserts response message ID rotation occurs before the signal is added and propagates to the step result. - Multiple processors can emit signals and all are preserved in prompts. - sendSignal is available in processOutputResult and processAPIError contexts. - Signals persist even without a writer and when rotateResponseMessageId is not supplied. - AgentsMDInjector auto-load integration (7 tests — packages/core/src/processors/agents-md-autoload-integration.test.ts) - Confirms AGENTS.md near tool-call paths is detected and injected once as a `system-reminder` signal with `dynamic-agents-md` metadata. - Injected AGENTS.md content appears in later LLM prompt text via signal→prompt projection. - A `data-system-reminder` stream chunk is emitted for injected AGENTS.md signals. - Duplicate suppression prevents re-injection across subsequent processor runs (signal-based dedup). - Directory-based tool-call arguments trigger injection; no injection occurs when no nearby AGENTS.md (readFile not called). - Injection survives across multiple LLM steps and persisted tool results. ## Code changes - Tests added - packages/core/src/processors/sendSignal-integration.test.ts (+409 lines) - packages/core/src/processors/agents-md-autoload-integration.test.ts (+539 lines) - Changeset - .changeset/khaki-cougars-hammer.md (patch bump for `@mastra/core`) - Production code - packages/core/src/processors/runner.ts - Exports createProcessorSendSignal (previously local) so workflows can construct sendSignal. - packages/core/src/processors/index.ts - Re-exports createProcessorSendSignal. - packages/core/src/workflows/workflow.ts and packages/core/src/workflows/evented/workflow.ts - Inject sendSignal into processor baseContext when a messageList is present, created with rotateResponseMessageId and the processor writer. - packages/core/src/workflows/processor-step.test.ts - New unit test ensuring createStep provides sendSignal to processors and that rotateResponseMessageId and writer emission behave as expected. - packages/core/src/processors/tool-result-reminder.ts - Minor refactor: uses getCurrentStepResponseMessages(messageList) to compute completed tool calls. - (Behavior-preserving) fallback persistence path preserved so reminders are recorded/streamed even when args.sendSignal is absent. ## Impact & scope - ~947 lines of tests added; small production surface change to export and wire sendSignal into workflow contexts. - No breaking public API changes; one new re-export (createProcessorSendSignal). - Confirms core-level sendSignal and AgentsMDInjector functionality; remaining AGENTS.md regression likely lies in higher-level orchestration or persistence/rehydration layers. ## Related - Investigates AGENTS.md auto-load regression after signals refactor (related to PR `#16438`). Devin session attached in PR for reproduction details. <!-- review_stack_entry_start --> [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/mastra-ai/mastra/pull/16927?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: tyler <tylerdbarnes@gmail.com>
1 parent df1947a commit ee59b74

15 files changed

Lines changed: 1173 additions & 113 deletions

File tree

.changeset/khaki-cougars-hammer.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@mastra/core': patch
3+
'@mastra/memory': patch
4+
---
5+
6+
Fixed processor workflow steps so `sendSignal` is available when processors inject Agent signals, and updated Observational Memory temporal gap markers to use Agent signals.

packages/core/src/agent/__tests__/agent-signals.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ describe('Agent signals', () => {
126126
attributes: { priority: 'high' },
127127
metadata: { source: 'test', signal: { userProvided: true } },
128128
},
129+
transient: true,
129130
});
130131

131132
const dbMessage = signal.toDBMessage({ threadId: 'thread-1', resourceId: 'resource-1' });
@@ -689,6 +690,7 @@ describe('Agent signals', () => {
689690
acceptedAt: signalResult.signal.acceptedAt?.toISOString(),
690691
});
691692
expect(signalPart?.data.createdAt).toBeDefined();
693+
expect(signalPart?.transient).toBe(true);
692694

693695
subscription.unsubscribe();
694696
});

packages/core/src/agent/signals.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export type AgentSignalDataPart = {
5353
attributes?: AgentSignalAttributes;
5454
metadata?: Record<string, unknown>;
5555
};
56+
transient: true;
5657
};
5758

5859
/**
@@ -372,6 +373,7 @@ function signalToDataPart(signal: ReturnType<typeof normalizeSignal>, parts: Sig
372373
...(signal.attributes ? { attributes: signal.attributes } : {}),
373374
...(signal.metadata ? { metadata: signal.metadata } : {}),
374375
},
376+
transient: true,
375377
};
376378
}
377379

0 commit comments

Comments
 (0)