Skip to content

Comments

AG-UI CustomEvents#306

Closed
jherr wants to merge 3 commits intomainfrom
ag-ui-customevents-v2
Closed

AG-UI CustomEvents#306
jherr wants to merge 3 commits intomainfrom
ag-ui-customevents-v2

Conversation

@jherr
Copy link
Contributor

@jherr jherr commented Feb 20, 2026

🎯 Changes

Moving to the AG-UI standard for custom events.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Refactor

    • The CustomEvent payload property has been renamed from data to value across TypeScript and Python APIs — update code that reads event payloads.
  • Documentation

    • Reference docs and examples updated to use value instead of data.
  • Tests

    • Test suites and test utilities updated to expect value in emitted events.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 20, 2026

📝 Walkthrough

Walkthrough

This PR renames the CustomEvent payload property from data to value across TypeScript and Python implementations, updating type declarations, event emission, stream processing, tests, docs, and migration guidance to use value consistently.

Changes

Cohort / File(s) Summary
Type Definitions
packages/typescript/ai/src/types.ts, packages/python/tanstack-ai/src/tanstack_ai/types.py
Renamed public CustomEvent field: datavalue in TypeScript interface and Python TypedDict.
Event Emission
packages/typescript/ai/src/activities/chat/index.ts, packages/python/tanstack-ai/src/tanstack_ai/chat.py
CUSTOM events (e.g., tool-input-available, approval-requested) now emit payload under value instead of data.
Event Processing
packages/typescript/ai/src/activities/chat/stream/processor.ts, packages/typescript/smoke-tests/adapters/src/harness.ts
Stream processor and AG-UI harness updated to read chunk.value (not chunk.data) for CUSTOM events.
Tests & Test Utilities
packages/typescript/ai/tests/*, packages/typescript/ai-client/tests/test-utils.ts, packages/typescript/smoke-tests/adapters/src/tests/tools/*
Test fixtures, helpers, and assertions updated to expect value on CUSTOM chunks instead of data.
Documentation
docs/reference/interfaces/CustomEvent.md
Docs and examples updated to reference value? and "Custom event value" in place of data?.
Changeset
.changeset/perky-sails-brush.md
Migration guidance added: replace usages of CustomEvent.data with CustomEvent.value across handlers, tests, and stream code.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • AlemTuzlak

Poem

🐰 I hop from data to value, light and spry,
Across TypeScript fields and Python sky;
Events now carry what rabbits prize,
A cleaner name beneath fresh skies,
Hooray — a small change, with a joyful cry! 🎉

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'AG-UI CustomEvents' is vague and doesn't clearly convey the specific change—renaming the CustomEvent payload property from 'data' to 'value'. Provide a more specific title such as 'Rename CustomEvent.data to CustomEvent.value for AG-UI compliance' to clearly communicate the core change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description follows the required template with all sections completed, including motivation, checklist items marked, and release impact noted.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ag-ui-customevents-v2

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.

@nx-cloud
Copy link

nx-cloud bot commented Feb 20, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 8c2d0a4

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ❌ Failed 6s View ↗
nx run-many --targets=build --exclude=examples/** ❌ Failed 3s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-20 23:49:25 UTC

@jherr jherr force-pushed the ag-ui-customevents-v2 branch from 0e52ef8 to 8c2d0a4 Compare February 20, 2026 23:44
Copy link
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

Caution

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

⚠️ Outside diff range comments (1)
packages/typescript/ai-client/tests/test-utils.ts (1)

189-199: ⚠️ Potential issue | 🔴 Critical

Update processor.ts to use chunk.value instead of chunk.data for CUSTOM events.

The refactoring is incomplete. While test-utils.ts correctly renamed the field to value, packages/typescript/ai/src/activities/chat/stream/processor.ts lines 866–867 still access chunk.data when handling CUSTOM events:

this.events.onCustomEvent?.(chunk.name, chunk.data, {
  toolCallId: (chunk.data as any)?.toolCallId,
})

This must be updated to use chunk.value to match the new event structure.

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

In `@packages/typescript/ai-client/tests/test-utils.ts` around lines 189 - 199,
The CUSTOM event handling in processor.ts still reads chunk.data but the event
shape was renamed to chunk.value; update the handler in the relevant method
(where events.onCustomEvent is invoked) to pass chunk.value instead of
chunk.data and extract the toolCallId from (chunk.value as any)?.toolCallId when
calling this.events.onCustomEvent?.(chunk.name, ...). Ensure all occurrences in
the processor's CUSTOM branch that reference chunk.data are changed to
chunk.value so onCustomEvent receives the new event payload.
🧹 Nitpick comments (1)
packages/typescript/smoke-tests/adapters/src/harness.ts (1)

292-308: Consider renaming the local variable data for consistency with the rename.

After extracting chunk.value, assigning it to a variable named data re-introduces the old name immediately, which is likely to confuse readers during maintenance.

♻️ Proposed rename
-      if (chunk.name === 'approval-requested' && chunk.value) {
-        const data = chunk.value as {
+      if (chunk.name === 'approval-requested' && chunk.value) {
+        const payload = chunk.value as {
           toolCallId: string
           toolName: string
           input: any
           approval: any
         }
         const approval: ApprovalCapture = {
-          toolCallId: data.toolCallId,
-          toolName: data.toolName,
-          input: data.input,
-          approval: data.approval,
+          toolCallId: payload.toolCallId,
+          toolName: payload.toolName,
+          input: payload.input,
+          approval: payload.approval,
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/smoke-tests/adapters/src/harness.ts` around lines 292 -
308, Local variable "data" reintroduces the old name after chunk.value was
extracted; rename it to something consistent like "chunkValue" (or "valueObj")
in the approval-requested branch where you build the ApprovalCapture so readers
use the same conceptual name as chunkData/value. Update the block that checks if
(chunk.name === 'approval-requested' && chunk.value) to declare const chunkValue
= chunk.value as { toolCallId: string; toolName: string; input: any; approval:
any } and then construct the ApprovalCapture using chunkValue.toolCallId,
chunkValue.toolName, chunkValue.input, chunkValue.approval before pushing to
approvalRequests.
🤖 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/perky-sails-brush.md:
- Around line 2-5: The changeset wrongly marks a breaking rename
(CustomEvent.data → CustomEvent.value) as a patch; update the .changeset so that
'@tanstack/ai' and '@tanstack/ai-client' are bumped to at least "minor" (or
"major" if you follow strict SemVer) while keeping '@tanstack/tests-adapters' as
"patch", and while you’re here consider adding a compatibility note or a
temporary shim (e.g., map event.data to event.value) in the code paths that emit
CustomEvent so consumers reading event.data won’t silently break; reference the
symbols CustomEvent.data, CustomEvent.value and the package names '@tanstack/ai'
and '@tanstack/ai-client' when making these edits.

---

Outside diff comments:
In `@packages/typescript/ai-client/tests/test-utils.ts`:
- Around line 189-199: The CUSTOM event handling in processor.ts still reads
chunk.data but the event shape was renamed to chunk.value; update the handler in
the relevant method (where events.onCustomEvent is invoked) to pass chunk.value
instead of chunk.data and extract the toolCallId from (chunk.value as
any)?.toolCallId when calling this.events.onCustomEvent?.(chunk.name, ...).
Ensure all occurrences in the processor's CUSTOM branch that reference
chunk.data are changed to chunk.value so onCustomEvent receives the new event
payload.

---

Nitpick comments:
In `@packages/typescript/smoke-tests/adapters/src/harness.ts`:
- Around line 292-308: Local variable "data" reintroduces the old name after
chunk.value was extracted; rename it to something consistent like "chunkValue"
(or "valueObj") in the approval-requested branch where you build the
ApprovalCapture so readers use the same conceptual name as chunkData/value.
Update the block that checks if (chunk.name === 'approval-requested' &&
chunk.value) to declare const chunkValue = chunk.value as { toolCallId: string;
toolName: string; input: any; approval: any } and then construct the
ApprovalCapture using chunkValue.toolCallId, chunkValue.toolName,
chunkValue.input, chunkValue.approval before pushing to approvalRequests.

Comment on lines +2 to +5
'@tanstack/tests-adapters': patch
'@tanstack/ai-client': patch
'@tanstack/ai': patch
---
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Breaking API change incorrectly versioned as patch.

Renaming CustomEvent.dataCustomEvent.value silently breaks any consumer that reads event.data (they get undefined with no error). This is a breaking change and must be versioned accordingly:

  • @tanstack/ai and @tanstack/ai-client: should be minor at minimum (or major if following strict SemVer). A patch bump gives consumers no semver signal that their code may break.
  • @tanstack/tests-adapters: patch is acceptable since it is a test/dev-only package.
🔧 Suggested fix
 ---
-'@tanstack/tests-adapters': patch
-'@tanstack/ai-client': patch
-'@tanstack/ai': patch
+'@tanstack/tests-adapters': patch
+'@tanstack/ai-client': minor
+'@tanstack/ai': minor
 ---
📝 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
'@tanstack/tests-adapters': patch
'@tanstack/ai-client': patch
'@tanstack/ai': patch
---
'@tanstack/tests-adapters': patch
'@tanstack/ai-client': minor
'@tanstack/ai': minor
---
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.changeset/perky-sails-brush.md around lines 2 - 5, The changeset wrongly
marks a breaking rename (CustomEvent.data → CustomEvent.value) as a patch;
update the .changeset so that '@tanstack/ai' and '@tanstack/ai-client' are
bumped to at least "minor" (or "major" if you follow strict SemVer) while
keeping '@tanstack/tests-adapters' as "patch", and while you’re here consider
adding a compatibility note or a temporary shim (e.g., map event.data to
event.value) in the code paths that emit CustomEvent so consumers reading
event.data won’t silently break; reference the symbols CustomEvent.data,
CustomEvent.value and the package names '@tanstack/ai' and '@tanstack/ai-client'
when making these edits.

@jherr jherr closed this Feb 20, 2026
@jherr jherr deleted the ag-ui-customevents-v2 branch February 20, 2026 23:50
Copy link
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.

Caution

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

⚠️ Outside diff range comments (2)
packages/typescript/ai/src/activities/chat/index.ts (1)

1095-1106: ⚠️ Potential issue | 🔴 Critical

createCustomEventChunk still emits data instead of value — TypeScript error and runtime bug.

createCustomEventChunk was not updated as part of this rename. It returns { ..., data } (shorthand for data: data), but CustomEvent only declares value?: unknown — there is no data property. This causes:

  1. TypeScript compile error: object literal excess-property check will reject data on a CustomEvent return type.
  2. Runtime bug: tools that call context.emitCustomEvent(...) will produce events with data set and value undefined, silently breaking every consumer reading chunk.value.
🐛 Proposed fix
 private createCustomEventChunk(
   eventName: string,
   data: Record<string, any>,
 ): CustomEvent {
   return {
     type: 'CUSTOM',
     timestamp: Date.now(),
     model: this.params.model,
     name: eventName,
-    data,
+    value: data,
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai/src/activities/chat/index.ts` around lines 1095 -
1106, The createCustomEventChunk function is returning an object with a data
property which mismatches the CustomEvent type (which expects value) and causes
TS and runtime errors; update createCustomEventChunk to return the event with
value: data (i.e., replace the shorthand data property with value) so the
returned object matches CustomEvent, and run a quick search for uses of
createCustomEventChunk / context.emitCustomEvent to ensure callers expect
chunk.value (adjust if any caller relied on chunk.data).
packages/typescript/ai-client/tests/test-utils.ts (1)

149-162: ⚠️ Potential issue | 🟠 Major

Update createCustomEventChunks to use value instead of data.

The PR renames the CUSTOM event payload property from data to value, but this helper was missed. The StreamChunk CUSTOM type now defines value?: unknown, and createToolCallChunks (line 224) already uses the new property. createCustomEventChunks still uses data in both the parameter type (line 149) and the emitted chunk (line 160), causing a type mismatch and breaking any tests that use this helper.

Proposed fix
 export function createCustomEventChunks(
-  events: Array<{ name: string; data?: unknown }>,
+  events: Array<{ name: string; value?: unknown }>,
   model: string = 'test',
 ): Array<StreamChunk> {
   const chunks: Array<StreamChunk> = []

   for (const event of events) {
     chunks.push({
       type: 'CUSTOM',
       model,
       timestamp: Date.now(),
       name: event.name,
-      data: event.data,
+      value: event.value,
     })
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai-client/tests/test-utils.ts` around lines 149 - 162,
The helper createCustomEventChunks is still using the old `data` property in its
parameter type and when emitting StreamChunk objects, causing a type mismatch
with the updated StreamChunk CUSTOM shape that uses `value?: unknown`; update
the events parameter type to use `value?: unknown` and change the emitted chunk
property from `data: event.data` to `value: event.value` (consistent with how
createToolCallChunks uses `value`) so the returned Array<StreamChunk> matches
the new CUSTOM type.
🧹 Nitpick comments (1)
packages/typescript/ai/src/types.ts (1)

351-373: emitCustomEvent parameter and JSDoc still reference data.

The callback parameter is named data and its JSDoc says @param data - Event payload data. After this rename the argument is stored as value in the emitted CustomEvent. The mismatch is harmless (it's a local param name), but it can mislead tool authors who inspect the signature and expect the emitted event to carry a data field.

♻️ Suggested rename for clarity
-  emitCustomEvent: (eventName: string, data: Record<string, any>) => void
+  emitCustomEvent: (eventName: string, value: Record<string, any>) => void

And in the JSDoc:

-   * `@param` data - Event payload data
+   * `@param` value - Custom event value
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai/src/types.ts` around lines 351 - 373, The
emitCustomEvent signature and JSDoc are inconsistent with the actual emitted
payload field; update the ToolExecutionContext.emitCustomEvent parameter name
from "data" to "value" and change the JSDoc `@param` description accordingly so it
documents the event payload as "value" (matching the emitted CustomEvent payload
field), e.g., update the function declaration in ToolExecutionContext and the
corresponding JSDoc param line to use "value" and describe it as the event
payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/typescript/ai-client/tests/test-utils.ts`:
- Around line 149-162: The helper createCustomEventChunks is still using the old
`data` property in its parameter type and when emitting StreamChunk objects,
causing a type mismatch with the updated StreamChunk CUSTOM shape that uses
`value?: unknown`; update the events parameter type to use `value?: unknown` and
change the emitted chunk property from `data: event.data` to `value:
event.value` (consistent with how createToolCallChunks uses `value`) so the
returned Array<StreamChunk> matches the new CUSTOM type.

In `@packages/typescript/ai/src/activities/chat/index.ts`:
- Around line 1095-1106: The createCustomEventChunk function is returning an
object with a data property which mismatches the CustomEvent type (which expects
value) and causes TS and runtime errors; update createCustomEventChunk to return
the event with value: data (i.e., replace the shorthand data property with
value) so the returned object matches CustomEvent, and run a quick search for
uses of createCustomEventChunk / context.emitCustomEvent to ensure callers
expect chunk.value (adjust if any caller relied on chunk.data).

---

Duplicate comments:
In @.changeset/perky-sails-brush.md:
- Around line 2-5: The changeset incorrectly marks a breaking rename
(CustomEvent.data → .value) as 'patch' — update the entries for '@tanstack/ai'
and '@tanstack/ai-client' in the changeset so they are bumped to 'minor' (or
'major' if your release policy requires strict SemVer) instead of 'patch'; edit
the change description line for those two packages in the .changeset file to
reflect the higher bump and keep the note about the breaking change so release
tooling and consumers are properly signaled.

---

Nitpick comments:
In `@packages/typescript/ai/src/types.ts`:
- Around line 351-373: The emitCustomEvent signature and JSDoc are inconsistent
with the actual emitted payload field; update the
ToolExecutionContext.emitCustomEvent parameter name from "data" to "value" and
change the JSDoc `@param` description accordingly so it documents the event
payload as "value" (matching the emitted CustomEvent payload field), e.g.,
update the function declaration in ToolExecutionContext and the corresponding
JSDoc param line to use "value" and describe it as the event payload.

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