Skip to content

fix(core): resolve stream options when a notification wakes an idle thread#18640

Open
CalebBarnes wants to merge 1 commit into
mainfrom
fix/notification-low-priority-persist
Open

fix(core): resolve stream options when a notification wakes an idle thread#18640
CalebBarnes wants to merge 1 commit into
mainfrom
fix/notification-low-priority-persist

Conversation

@CalebBarnes

@CalebBarnes CalebBarnes commented Jun 29, 2026

Copy link
Copy Markdown
Member

What

Fixes the "No model selected" error that occurred when a deferred notification woke an idle thread.

When a notification is due and its target thread is idle, the dispatcher starts a fresh run to deliver it. That run carried no request context or model selection, so it had no model to run with — surfacing as No model selected.

How

Signal providers can now resolve the stream options a woken run needs:

  • SignalProvider gains an optional getNotificationStreamOptions(target) method and a notificationSource getter (defaults to the provider id).
  • The dispatcher matches a due record back to the provider that produced it (record.source === provider.notificationSource) and calls that provider's resolver at send time, attaching the result to the wake target's ifIdle.streamOptions.
  • GithubSignals implements the resolver using its existing session → model/requestContext logic, and overrides notificationSource to 'github' (its records carry source: 'github' while its id is 'github-signals').
  • mastracode wires that single resolver into the provider — no agent-config duplication.

Resolved at dispatch time (not persisted on the record) because stream options carry live, non-serializable state such as a RequestContext and closures.

Why not persist / change defaults

Stream options can't be serialized to storage, so the resolution has to happen in-process at dispatch. The fix makes wake actually work rather than avoiding waking — no framework defaults, agent config, or summary behavior changed.

Tests

  • New dispatcher test asserts that when a provider exposes getNotificationStreamOptions, the wake target carries ifIdle: { behavior: 'wake', streamOptions } with the resolved options, and the resolver is called with (source, { resourceId, threadId }).
  • Existing default-wake behavior covered.

Verification

  • @mastra/core type-check clean; 59 notification tests pass.
  • @mastra/github-signals type-check clean; 58 tests pass.
  • mastracode type-check clean.

ELI5

Sometimes a notification wakes an idle worker, but the worker doesn’t know which “model/context” to use, so it errors. This PR teaches the system to figure out the right wake-up details at the moment of dispatch, so the worker can start correctly.

What changed

  • Added notificationSource and an optional getNotificationStreamOptions(target) hook to signal providers.
  • Updated the dispatcher/agent so that when a deferred “due” notification wakes an idle thread, it finds the provider that produced the record and resolves the wake-up streamOptions at dispatch time (instead of relying on persisted data).
  • Adjusted wake target construction (ifIdle.streamOptions) so the woken run receives the resolved request context/model selection when available.
  • Implemented the stream option resolver in GithubSignals by wiring it into the existing session-to-model/requestContext logic and setting notificationSource to github.
  • Added tests to verify getNotificationStreamOptions is called with the expected source/target identifiers and that wake delivery attaches the resolved streamOptions.
  • Added a changeset documenting the bug fix.

Result

Deferred notifications that wake idle threads now include the needed, correctly-resolved execution options—preventing the “No model selected” failure—while keeping default wake behavior covered.

@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mastra-docs-1.x Ready Ready Preview, Comment Jun 29, 2026 10:04pm
mastra-playground-ui Ready Ready Preview, Comment Jun 29, 2026 10:04pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
mastra-studio-preview Ignored Ignored Preview Jun 29, 2026 10:04pm

Request Review

@changeset-bot

changeset-bot Bot commented Jun 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 35f21ed

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

This PR includes changesets to release 22 packages
Name Type
@mastra/core Patch
mastracode Patch
@mastra/mcp-docs-server Patch
@internal/playground Patch
@mastra/client-js Patch
@mastra/opencode Patch
@mastra/longmemeval Patch
mastra Patch
@mastra/deployer-cloud Patch
@mastra/react 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/nestjs Patch
@mastra/next Patch
@mastra/tanstack-start Patch
@mastra/temporal 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

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f06be225-74c4-4630-9a11-268de751cfa2

📥 Commits

Reviewing files that changed from the base of the PR and between 9d03640 and 35f21ed.

📒 Files selected for processing (6)
  • .changeset/notification-wake-stream-options.md
  • packages/core/src/agent/agent.ts
  • packages/core/src/notifications/dispatcher.ts
  • packages/core/src/notifications/notifications.test.ts
  • packages/core/src/signals/signal-provider.ts
  • signals/github/src/index.ts

Walkthrough

Adds notification stream-option hooks to SignalProvider and Agent, resolves and attaches wake-time ifIdle.streamOptions during dispatch, wires GithubSignals to the resolver, and adds a test plus changeset entry for the wake delivery path.

Changes

Notification wake stream options dispatch

Layer / File(s) Summary
SignalProvider and Agent hook contracts
packages/core/src/signals/signal-provider.ts, packages/core/src/agent/agent.ts
SignalProvider adds notificationSource and optional getNotificationStreamOptions(target), with resolver storage behind it. Agent adds getNotificationStreamOptions(source, target) and delegates to the matching signal provider.
Dispatcher wake target resolution
packages/core/src/notifications/dispatcher.ts
buildWakeTarget resolves stream options at dispatch time and attaches ifIdle: { behavior: 'wake', streamOptions } when present. sendNotificationRecord and sendNotificationSummary now use it.
GithubSignals wiring
signals/github/src/index.ts
GithubSignals overrides notificationSource to 'github' and registers options.getNotificationStreamOptions with setNotificationStreamOptionsResolver(...).
Tests and changeset
packages/core/src/notifications/notifications.test.ts, .changeset/notification-wake-stream-options.md
Adds a wake dispatch test that asserts resolved stream options are forwarded in sendSignal, and a changeset entry describing the notification wake fix.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • mastra-ai/mastra#18244: Related notification dispatch plumbing around preserving and forwarding ifIdle data through the signal path.
  • mastra-ai/mastra#18636: Adds complementary wiring for getNotificationStreamOptions in the notification wake flow.
  • mastra-ai/mastra#18637: Touches the same agent.ts and dispatcher.ts notification wake logic.

Suggested reviewers

  • abhiaiyer91
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: resolving notification stream options when a wake target is used.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/notification-low-priority-persist

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

@dane-ai-mastra dane-ai-mastra Bot added the complexity: low Low-complexity PR label Jun 29, 2026
@dane-ai-mastra

dane-ai-mastra Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR triage

Linked issue check skipped for core contributor @CalebBarnes.


PR complexity score

Factor Value Score impact
Files changed 6 +12
Lines changed 155 +9
Author merged PRs 230 -20
Test files changed Yes -10
Final score -9

Applied label: complexity: low


Changed test gate

Changed tests passed against the base branch; they should fail before the PR code is applied.

Label: tests: failing ❌

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/notification-low-priority-persist.md:
- Line 5: Rewrite the changeset summary to focus on the user-visible outcome and
the bug fix: describe that low-priority notifications are now safely delayed
instead of triggering a failed processing attempt that could cause a “No model
selected” error. Remove internal implementation terms from the description, and
keep the wording outcome-focused and non-technical while still noting that
higher-priority notifications continue to be handled immediately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a7b35c35-87b2-40c5-9527-e5437dc3fb61

📥 Commits

Reviewing files that changed from the base of the PR and between 07bf909 and 219a148.

📒 Files selected for processing (3)
  • .changeset/notification-low-priority-persist.md
  • packages/core/src/notifications/dispatcher.ts
  • packages/core/src/notifications/notifications.test.ts

'@mastra/core': patch
---

Persist low-priority notifications instead of waking idle threads. The notification dispatcher's individual-record path defaulted to the `wake` idle behavior, which starts a run that requires a model/requestContext the dispatcher does not carry — surfacing as a "No model selected" error. Low-priority records now use `ifIdle: { behavior: 'persist' }`, mirroring the existing low-priority summary path, while higher-priority records keep the default wake behavior.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make the changeset outcome-focused.

Line 5 reads like an implementation note. Please rewrite it around the behavior change and the failure it fixes, instead of internal terms like wake, ifIdle, and requestContext.

Suggested rewrite
-Persist low-priority notifications instead of waking idle threads. The notification dispatcher's individual-record path defaulted to the `wake` idle behavior, which starts a run that requires a model/requestContext the dispatcher does not carry — surfacing as a "No model selected" error. Low-priority records now use `ifIdle: { behavior: 'persist' }`, mirroring the existing low-priority summary path, while higher-priority records keep the default wake behavior.
+Fixed low-priority notifications failing on idle threads.
+
+Low-priority notifications now stay queued when a thread is idle instead of waking the thread and failing with "No model selected." Higher-priority notifications still wake the thread immediately.

As per path instructions, changeset descriptions should "Avoid technical jargon" and "Highlight outcomes! What does change for the end user? Do not focus on internal implementation details."

potential_issue

📝 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
Persist low-priority notifications instead of waking idle threads. The notification dispatcher's individual-record path defaulted to the `wake` idle behavior, which starts a run that requires a model/requestContext the dispatcher does not carry — surfacing as a "No model selected" error. Low-priority records now use `ifIdle: { behavior: 'persist' }`, mirroring the existing low-priority summary path, while higher-priority records keep the default wake behavior.
Fixed low-priority notifications failing on idle threads.
Low-priority notifications now stay queued when a thread is idle instead of waking the thread and failing with "No model selected." Higher-priority notifications still wake the thread immediately.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/notification-low-priority-persist.md at line 5, Rewrite the
changeset summary to focus on the user-visible outcome and the bug fix: describe
that low-priority notifications are now safely delayed instead of triggering a
failed processing attempt that could cause a “No model selected” error. Remove
internal implementation terms from the description, and keep the wording
outcome-focused and non-technical while still noting that higher-priority
notifications continue to be handled immediately.

Source: Path instructions

@dane-ai-mastra dane-ai-mastra Bot added the tests: green ✅ Changed tests failed against base as expected label Jun 29, 2026
@CalebBarnes CalebBarnes force-pushed the fix/notification-low-priority-persist branch from 219a148 to 977b08c Compare June 29, 2026 21:23
@CalebBarnes CalebBarnes changed the title fix(core): persist low-priority notifications instead of waking idle threads fix(core): resolve stream options when a notification wakes an idle thread Jun 29, 2026
@CalebBarnes CalebBarnes force-pushed the fix/notification-low-priority-persist branch from 977b08c to 2444cb5 Compare June 29, 2026 21:28
@dane-ai-mastra dane-ai-mastra Bot added tests: failing ❌ Changed tests passed against base and removed tests: green ✅ Changed tests failed against base as expected labels Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mastracode/src/index.ts`:
- Around line 485-515: The wake-time controller context stored in requestContext
is not JSON-safe because AgentControllerRequestContext includes closures and
live objects like getState, setState, session.state.update, and workspace.
Update the streamOptions/requestContext construction in index.ts to send only
serializable identifiers and plain data, and move rehydration of
controller/session methods to the receiving side that consumes the controller
context. Make sure the later agentControllerContext access in this flow no
longer depends on serialized function handles, and keep the UnixSocketPubSub
boundary limited to codec-safe values only.

In `@packages/core/src/notifications/dispatcher.ts`:
- Around line 134-146: The current `dispatcher.ts` target selection always falls
back to wake/default behavior and ignores low-priority individual records.
Update the `target` construction in the notification dispatch flow so records
marked low-priority use persistence instead of `ifIdle.behavior: 'wake'`, while
keeping the existing `agent.getNotificationStreamOptions` resolution for
wakeable cases. Use the existing `current` record fields and
`SendAgentSignalOptions` assembly to route low-priority notifications to persist
and only attach `streamOptions` when waking is intended.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fd6e2776-1345-4591-87a5-3d57ad0b1548

📥 Commits

Reviewing files that changed from the base of the PR and between 219a148 and 977b08c.

📒 Files selected for processing (7)
  • .changeset/notification-wake-stream-options.md
  • mastracode/src/index.ts
  • packages/core/src/agent/agent.ts
  • packages/core/src/notifications/dispatcher.ts
  • packages/core/src/notifications/notifications.test.ts
  • packages/core/src/signals/signal-provider.ts
  • signals/github/src/index.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/notification-wake-stream-options.md

Comment thread mastracode/src/index.ts Outdated
Comment on lines +485 to +515
const requestContext = new RequestContext();
const agentControllerContext: AgentControllerRequestContext = {
controllerId: controller.id,
state: session.state.get(),
getState: () => session.state.get(),
setState: updates => session.state.set(updates),
threadId,
resourceId,
session: {
id: session.identity.getId(),
ownerId: session.identity.getOwnerId(),
modeId,
modelId,
state: {
get: () => session.state.get(),
set: updates => session.state.set(updates),
update: updater => session.state.update(updater),
},
},
workspace: controller.getWorkspace(),
getSubagentModelId: params => session.subagents.model.get(params ?? {}),
};
requestContext.set('controller', agentControllerContext);

return {
memory: { thread: threadId, resource: resourceId },
requestContext,
maxSteps: 1000,
savePerStep: false,
requireToolApproval: (session.state.get() as Record<string, unknown>).yolo !== true,
modelSettings: { temperature: 1 },

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.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Keep wake requestContext JSON-safe.

Line 507 stores an AgentControllerRequestContext with live closures (getState, setState, session.state.update) and workspace inside the wake streamOptions. That works in-process, but the UnixSocketPubSub path cannot carry those handles. After serialization, the controller entry is reduced to plain data, so the later agentControllerContext?.getState() call in this file will fail on notification-driven wakes.

Please send only serializable identifiers here and rehydrate the live controller/session methods on the receiving side instead. As per coding guidelines, "Rely on the codec at the UnixSocketPubSub boundary to handle Date, Error, Map, Set, and GeneratedFile; do not pass live handles or closures there."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mastracode/src/index.ts` around lines 485 - 515, The wake-time controller
context stored in requestContext is not JSON-safe because
AgentControllerRequestContext includes closures and live objects like getState,
setState, session.state.update, and workspace. Update the
streamOptions/requestContext construction in index.ts to send only serializable
identifiers and plain data, and move rehydration of controller/session methods
to the receiving side that consumes the controller context. Make sure the later
agentControllerContext access in this flow no longer depends on serialized
function handles, and keep the UnixSocketPubSub boundary limited to codec-safe
values only.

Source: Coding guidelines

Comment on lines +134 to +146
// A wake starts a fresh run, but the dispatcher carries no request context or
// model selection, which surfaces as "No model selected". Resolve the stream
// options from the signal provider that produced this record (matched by
// `source`) and attach them so the woken run has the context it needs.
// Resolved here because stream options carry live, non-serializable state
// (e.g. a RequestContext) that cannot be persisted on the record.
const streamOptions = await agent.getNotificationStreamOptions?.(current.source, {
resourceId: current.resourceId,
threadId: current.threadId,
});
const target: SendAgentSignalOptions = streamOptions
? { resourceId: current.resourceId, threadId: current.threadId, ifIdle: { behavior: 'wake', streamOptions } }
: { resourceId: current.resourceId, threadId: current.threadId };

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve persist for low-priority individual records.

Line 140 resolves wake stream options for every record, and Line 144 falls back to default target behavior for low-priority records. That misses the PR’s intended fix: low-priority individual notifications should persist instead of waking idle runs.

Proposed fix
-  const streamOptions = await agent.getNotificationStreamOptions?.(current.source, {
-    resourceId: current.resourceId,
-    threadId: current.threadId,
-  });
-  const target: SendAgentSignalOptions = streamOptions
-    ? { resourceId: current.resourceId, threadId: current.threadId, ifIdle: { behavior: 'wake', streamOptions } }
-    : { resourceId: current.resourceId, threadId: current.threadId };
+  const baseTarget = { resourceId: current.resourceId, threadId: current.threadId };
+  let target: SendAgentSignalOptions;
+  if (current.priority === 'low') {
+    target = { ...baseTarget, ifIdle: { behavior: 'persist' } };
+  } else {
+    const streamOptions = await agent.getNotificationStreamOptions?.(current.source, baseTarget);
+    target = streamOptions ? { ...baseTarget, ifIdle: { behavior: 'wake', streamOptions } } : baseTarget;
+  }
📝 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
// A wake starts a fresh run, but the dispatcher carries no request context or
// model selection, which surfaces as "No model selected". Resolve the stream
// options from the signal provider that produced this record (matched by
// `source`) and attach them so the woken run has the context it needs.
// Resolved here because stream options carry live, non-serializable state
// (e.g. a RequestContext) that cannot be persisted on the record.
const streamOptions = await agent.getNotificationStreamOptions?.(current.source, {
resourceId: current.resourceId,
threadId: current.threadId,
});
const target: SendAgentSignalOptions = streamOptions
? { resourceId: current.resourceId, threadId: current.threadId, ifIdle: { behavior: 'wake', streamOptions } }
: { resourceId: current.resourceId, threadId: current.threadId };
// A wake starts a fresh run, but the dispatcher carries no request context or
// model selection, which surfaces as "No model selected". Resolve the stream
// options from the signal provider that produced this record (matched by
// `source`) and attach them so the woken run has the context it needs.
// Resolved here because stream options carry live, non-serializable state
// (e.g. a RequestContext) that cannot be persisted on the record.
const baseTarget = { resourceId: current.resourceId, threadId: current.threadId };
let target: SendAgentSignalOptions;
if (current.priority === 'low') {
target = { ...baseTarget, ifIdle: { behavior: 'persist' } };
} else {
const streamOptions = await agent.getNotificationStreamOptions?.(current.source, baseTarget);
target = streamOptions ? { ...baseTarget, ifIdle: { behavior: 'wake', streamOptions } } : baseTarget;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/notifications/dispatcher.ts` around lines 134 - 146, The
current `dispatcher.ts` target selection always falls back to wake/default
behavior and ignores low-priority individual records. Update the `target`
construction in the notification dispatch flow so records marked low-priority
use persistence instead of `ifIdle.behavior: 'wake'`, while keeping the existing
`agent.getNotificationStreamOptions` resolution for wakeable cases. Use the
existing `current` record fields and `SendAgentSignalOptions` assembly to route
low-priority notifications to persist and only attach `streamOptions` when
waking is intended.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@signals/github/src/index.ts`:
- Around line 1132-1134: The deprecated addAgent(agent, options) path updates
`#agentOptions` but does not keep the notification stream resolver in sync, unlike
the constructor path in the index.ts class. Update addAgent to also call
setNotificationStreamOptionsResolver whenever
options.getNotificationStreamOptions is provided so deferred GitHub
notifications wake with streamOptions and avoid the “No model selected” failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ded2f740-9789-4d49-8ab9-6ca61086639d

📥 Commits

Reviewing files that changed from the base of the PR and between 374783b and 9d03640.

📒 Files selected for processing (6)
  • .changeset/notification-wake-stream-options.md
  • packages/core/src/agent/agent.ts
  • packages/core/src/notifications/dispatcher.ts
  • packages/core/src/notifications/notifications.test.ts
  • packages/core/src/signals/signal-provider.ts
  • signals/github/src/index.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/notification-wake-stream-options.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/core/src/agent/agent.ts
  • packages/core/src/notifications/notifications.test.ts
  • packages/core/src/signals/signal-provider.ts
  • packages/core/src/notifications/dispatcher.ts

Comment thread signals/github/src/index.ts Outdated
Comment on lines +1132 to +1134
if (options.getNotificationStreamOptions) {
this.#agentOptions = { getNotificationStreamOptions: options.getNotificationStreamOptions };
this.setNotificationStreamOptionsResolver(options.getNotificationStreamOptions);

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep the resolver in sync for the deprecated addAgent(...) path.

This only installs the wake-time resolver when it comes from the constructor. addAgent(agent, options) below still updates #agentOptions without calling setNotificationStreamOptionsResolver(...), so deferred GitHub notifications configured through the backward-compatible API will still wake idle threads without streamOptions and can hit the same “No model selected” failure again.

Suggested fix
   constructor(options: GithubSignalsOptions = {}) {
     super();
     this.#options = options;
     this.#syncClient = options.syncClient ?? new GitcrawlSyncClient({ command: options.gitcrawlCommand });
     this.#repositoryResolver = options.repositoryResolver ?? new GitRemoteRepositoryResolver();
     if (options.getNotificationStreamOptions) {
-      this.#agentOptions = { getNotificationStreamOptions: options.getNotificationStreamOptions };
-      this.setNotificationStreamOptionsResolver(options.getNotificationStreamOptions);
+      this.#agentOptions = { getNotificationStreamOptions: options.getNotificationStreamOptions };
+      this.setNotificationStreamOptionsResolver(options.getNotificationStreamOptions);
     }
   }
@@
   addAgent(agent: GithubSignalAgent, options: GithubSignalAgentOptions = {}): void {
     this.#agent = agent;
     this.#agentOptions = options;
+    this.setNotificationStreamOptionsResolver(options.getNotificationStreamOptions);
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@signals/github/src/index.ts` around lines 1132 - 1134, The deprecated
addAgent(agent, options) path updates `#agentOptions` but does not keep the
notification stream resolver in sync, unlike the constructor path in the
index.ts class. Update addAgent to also call
setNotificationStreamOptionsResolver whenever
options.getNotificationStreamOptions is provided so deferred GitHub
notifications wake with streamOptions and avoid the “No model selected” failure.

…hread

A deferred notification that wakes an idle thread starts a fresh run, but
the dispatcher carries no request context or model selection. That run had
no model, surfacing as "No model selected".

Signal providers can now implement getNotificationStreamOptions(target),
routed by a notificationSource getter that defaults to the provider id. The
dispatcher matches a due record back to the provider that produced it
(record.source === provider.notificationSource) and resolves the stream
options at send time, attaching them to the wake target's
ifIdle.streamOptions so the woken run has the request context and model it
needs.

Resolved at dispatch rather than persisted because stream options carry
live, non-serializable state (e.g. a RequestContext) that cannot be stored
on the record. GithubSignals implements the resolver from its existing
session->model logic; mastracode wires that single resolver into the
provider with no agent-config duplication.

Co-Authored-By: Mastra Code (anthropic/claude-opus-4-8) <noreply@mastra.ai>
@CalebBarnes CalebBarnes force-pushed the fix/notification-low-priority-persist branch from 9d03640 to 35f21ed Compare June 29, 2026 22:02
@dane-ai-mastra dane-ai-mastra Bot added tests: failing ❌ Changed tests passed against base and removed tests: green ✅ Changed tests failed against base as expected labels Jun 29, 2026
@dane-ai-mastra dane-ai-mastra Bot added tests: green ✅ Changed tests failed against base as expected and removed tests: failing ❌ Changed tests passed against base labels Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

complexity: low Low-complexity PR tests: green ✅ Changed tests failed against base as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant