Skip to content

feat(channel): answer follow-ups after a mention subscribes - #30

Closed
BenTaylorDev wants to merge 1 commit into
mainfrom
ben1/subscribe-on-mention
Closed

feat(channel): answer follow-ups after a mention subscribes#30
BenTaylorDev wants to merge 1 commit into
mainfrom
ben1/subscribe-on-mention

Conversation

@BenTaylorDev

Copy link
Copy Markdown

What

onMention ran the agent but never subscribed the conversation, and no onMessage handler was registered at all — so OpenTag answered only when explicitly addressed, on every single turn.

  • A mention now subscribes the conversation and runs the agent.
  • Later messages in that conversation run the agent too, guarded by isSubscribed() so the bot stays silent in conversations it was never invited into.
  • The existing error handling (user-facing reply + reportRecoverableError, AggregateError when the reply itself fails) moves into a shared runTurn handler instead of being duplicated across both entry points.

Dispatch is exclusive in channels-core — a mentioned turn goes to onMention whenever any handler is registered, and to onMessage otherwise — so the mention that subscribes still runs the agent exactly once.

runAgent(managedRunInput(message)) is kept rather than a bare runAgent(): managedRunInput carries the multimodal content parts and the per-platform tools/context that a managed turn needs.

Testing

Two new tests in app/channel.test.ts, both driven through FakeAdapter's ingress sink with explicit operation.mentioned (turn dedup keys off logicalMessageId/revisionId, so each turn gets its own id):

  • stays quiet in a conversation that never addressed it — one non-mention turn, zero agent runs.
  • answers follow-ups once a mention subscribes that conversation — mention in c1, follow-up in c1, unrelated non-mention in c2; exactly 2 runs.

Red-checked — with app/channel.tsx stashed, the second test fails, so it genuinely covers the new wiring:

=== WITHOUT the onMessage wiring ===
AssertionError: expected [ 'run' ] to have a length of 2 but got 1
      Tests  1 failed | 12 skipped (13)

With the change:

 Test Files  1 passed (1)
      Tests  1 passed | 12 skipped (13)

Runs are counted from inside the FakeAgent script, not from a field on the agent: every turn runs on a clone, and FakeAgent.clone() copies the remaining script but resets its own counters, so CapturingAgent.calls reads 0 even when the agent did run.

Pre-existing red, unchanged by this PR

pnpm check-types and pnpm test are already failing on main from drift against @copilotkit/channels@0.6.0 (PlatformUser no longer exported, ProviderActor.kind now required, FakeAgent.clone() resetting counters). Measured before and after:

tsc errors Test files Tests
baseline (main) 20 3 failed / 17 passed 9 failed / 130 passed (139)
this branch 20 3 failed / 17 passed 9 failed / 132 passed (141)

The failing test names are byte-identical before and after (diff of the sorted failure list is empty), and no error is reported in app/channel.tsx. Fixing that drift is out of scope here.

🤖 Generated with Claude Code

`onMention` ran the agent but never subscribed the conversation, and no
`onMessage` handler was registered at all — so OpenTag answered only when
explicitly addressed, on every single turn.

A mention now subscribes the conversation and runs the agent; later messages
in that conversation run it too, guarded by `isSubscribed()` so the bot stays
silent in conversations it was never invited into. Dispatch is exclusive — a
mentioned turn goes to `onMention` whenever any is registered — so the mention
that subscribes still runs exactly once.

The existing error handling moves into a shared `runTurn` handler rather than
being duplicated across both entry points.

The tests count agent runs from inside the `FakeAgent` script rather than from
a field on the agent: every turn runs on a clone, and `FakeAgent.clone()`
copies the remaining script but resets its own counters, so instance state
under-reports.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@BenTaylorDev

Copy link
Copy Markdown
Author

Closing — redundant. main already subscribes on mention and gates onMessage on isSubscribed() (and additionally drops bot/app-authored messages, which this branch did not), and it already carries equivalent tests. I based this on the commit the channels-sdk submodule pins, which is 22 commits behind main; the wiring was added upstream in 44a8a49 and d67f23a.

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