Conversation
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
|
Cursor Agent can help with this pull request. Just |
🦋 Changeset detectedLatest commit: 65d96e7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 29 packages
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 |
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@packages/ai/package.json`:
- Around line 45-53: The peerDependencies incorrectly include "ai": "^4.2.0"
while the code unconditionally imports/uses ChatTransport (symbol:
ChatTransport) which only exists in ai >=5; fix by either updating the
package.json peerDependencies to "ai": "^5.0.0 || ^6.0.0" or add runtime/version
guards around ChatTransport usage (e.g., check the installed ai package version
or confirm ChatTransport exists before importing/instantiating and provide a
fallback/error), and ensure the change is applied where ChatTransport is
imported/used and reflected in package.json peerDependencies.
In `@packages/ai/src/ai.ts`:
- Around line 63-67: The validation in the conversion check erroneously throws
when either "schema" or "jsonSchema" is present but falsy; change the logic in
the block around the task check so it only throws when both schema sources are
absent/unusable (e.g., require that ("schema" in task && !task.schema) AND
("jsonSchema" in task && !task.jsonSchema") before throwing), and fix the error
message text from "to to a tool" to "to a tool"; update references in this
change for the Task/TaskWithSchema handling where task, schema, and jsonSchema
are inspected.
In `@packages/ai/src/chatTransport.ts`:
- Around line 239-264: The catch-all in consumeTrackingStream currently treats
any exception as a terminal cancellation and sets runState.isActive = false,
which prevents reconnectToStream from attempting reconnection; change
consumeTrackingStream to distinguish abort/cancellation errors from
transient/retriable errors (e.g., check for an AbortError or a specific error
type), only set runState.isActive = false for non-retriable/aborted errors, and
for transient errors leave isActive true (or call a provided error-classifier
callback) while still updating lastEventId via incrementLastEventId and
persisting via this.runStore.set(runState); ensure runStore.get/runStore.set
calls remain and update logic references the runState variable in both paths so
reconnectToStream can retry when appropriate.
- Around line 429-440: incrementLastEventId currently parses the whole Redis
stream ID as an integer and drops the "-sequence" suffix; update the function so
it preserves the timestamp prefix and only increments the sequence part: when
lastEventId contains a hyphen split on the first '-' into timestamp and seq,
validate both parts as numbers and return `${timestamp}-${seq+1}`; if it has no
hyphen fall back to parsing as an integer and return the incremented value as
before; keep the existing behavior of returning "0" for undefined or non-numeric
inputs and ensure function name incrementLastEventId is updated accordingly.
🧹 Nitpick comments (4)
packages/ai/src/types.ts (1)
77-81: Usetypeinstead ofinterfaceforTriggerChatRunStore.All other type definitions in this file correctly use
type, butTriggerChatRunStoreusesinterface. As per coding guidelines: "Use types over interfaces for TypeScript".Suggested fix
-export interface TriggerChatRunStore { - get(chatId: string): Promise<TriggerChatRunState | undefined> | TriggerChatRunState | undefined; - set(state: TriggerChatRunState): Promise<void> | void; - delete(chatId: string): Promise<void> | void; -} +export type TriggerChatRunStore = { + get(chatId: string): Promise<TriggerChatRunState | undefined> | TriggerChatRunState | undefined; + set(state: TriggerChatRunState): Promise<void> | void; + delete(chatId: string): Promise<void> | void; +};packages/ai/src/chatTransport.test.ts (3)
215-231: Unconsumed stream fromsendMessagesmay leave the first SSE connection dangling.The stream returned by
sendMessages(Line 216) is never read or cancelled. WhilefirstStreamResponse.end()in thefinallyblock closes the server side, the client-sideReadableStreamis abandoned. If the transport doesn't internally consume and cancel this stream, it may result in a resource leak or an unhandled error once the server ends the response.Consider capturing the stream and explicitly cancelling it in the
finallyblock:Proposed fix
- await transport.sendMessages({ + const initialStream = await transport.sendMessages({ trigger: "submit-message", chatId: "chat-2", messageId: undefined, messages: [], abortSignal: undefined, });Then in the
finally:} finally { + if (initialStream) { + await initialStream.cancel().catch(function () {}); + } if (firstStreamResponse) { firstStreamResponse.end(); } }
306-322:readChunksreturn type could be tightened.The function builds an array of
{ type: string; id?: string; chunk: UIMessageChunk }, but this type is declared inline twice (Line 307 and Line 309). Extract it to a local type alias for DRY:Proposed fix
+type ChunkPart = { type: string; id?: string; chunk: UIMessageChunk }; + async function readChunks(stream: ReadableStream<UIMessageChunk>) { - const parts: Array<{ type: string; id?: string; chunk: UIMessageChunk }> = []; + const parts: ChunkPart[] = []; for await (const chunk of stream) { - const part: { type: string; id?: string; chunk: UIMessageChunk } = { + const part: ChunkPart = { type: chunk.type, chunk, };
224-231: The test is correct; clarify thatlastEventIdis a separate counter from the SSE event ID.The test's expectation of
lastEventId === "0"is correct, but for a different reason than the comment assumes. ThelastEventIdis an independent counter initialized asundefined, andincrementLastEventId()transformsundefinedto"0"(then"1","2", etc.). The SSE event ID"1-0"is separate and not parsed intolastEventId. Add a brief comment clarifying this mechanism to prevent future confusion—e.g.,// lastEventId is an internal counter (undefined→"0"→"1"), separate from SSE event ids like "1-0".
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (6)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlreferences/realtime-streams/package.jsonis excluded by!references/**references/realtime-streams/src/app/actions.tsis excluded by!references/**references/realtime-streams/src/app/page.tsxis excluded by!references/**references/realtime-streams/src/components/ai-sdk-chat.tsxis excluded by!references/**references/realtime-streams/src/trigger/ai-chat.tsis excluded by!references/**
📒 Files selected for processing (11)
.changeset/curly-radios-visit.mddocs/tasks/schemaTask.mdxdocs/tasks/streams.mdxpackages/ai/package.jsonpackages/ai/src/ai.test.tspackages/ai/src/ai.tspackages/ai/src/chatTransport.test.tspackages/ai/src/chatTransport.tspackages/ai/src/index.tspackages/ai/src/types.tspackages/ai/tsconfig.json
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead
**/*.{ts,tsx}: Always import tasks from@trigger.dev/sdk, never use@trigger.dev/sdk/v3or deprecatedclient.defineJobpattern
Every Trigger.dev task must be exported and have a uniqueidproperty with no timeouts in the run function
Files:
packages/ai/src/types.tspackages/ai/src/index.tspackages/ai/src/ai.test.tspackages/ai/src/ai.tspackages/ai/src/chatTransport.tspackages/ai/src/chatTransport.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use function declarations instead of default exports
Import from
@trigger.dev/coreusing subpaths only, never import from root
Files:
packages/ai/src/types.tspackages/ai/src/index.tspackages/ai/src/ai.test.tspackages/ai/src/ai.tspackages/ai/src/chatTransport.tspackages/ai/src/chatTransport.test.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)
**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries
Files:
packages/ai/src/types.tspackages/ai/src/index.tspackages/ai/src/ai.test.tspackages/ai/src/ai.tspackages/ai/src/chatTransport.tspackages/ai/src/chatTransport.test.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}
📄 CodeRabbit inference engine (AGENTS.md)
Format code using Prettier before committing
Files:
packages/ai/src/types.tspackages/ai/src/index.tspackages/ai/tsconfig.jsonpackages/ai/src/ai.test.tspackages/ai/src/ai.tspackages/ai/package.jsonpackages/ai/src/chatTransport.tspackages/ai/src/chatTransport.test.ts
{packages,integrations}/**/*
📄 CodeRabbit inference engine (CLAUDE.md)
Add a changeset when modifying any public package in
packages/*orintegrations/*usingpnpm run changeset:add
Files:
packages/ai/src/types.tspackages/ai/src/index.tspackages/ai/tsconfig.jsonpackages/ai/src/ai.test.tspackages/ai/src/ai.tspackages/ai/package.jsonpackages/ai/src/chatTransport.tspackages/ai/src/chatTransport.test.ts
**/tsconfig.json
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use strict mode in TypeScript configuration
Files:
packages/ai/tsconfig.json
**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use vitest for all tests in the Trigger.dev repository
Files:
packages/ai/src/ai.test.tspackages/ai/src/chatTransport.test.ts
**/*.test.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx,js,jsx}: Test files should live beside the files under test and use descriptivedescribeanditblocks
Tests should avoid mocks or stubs and use the helpers from@internal/testcontainerswhen Redis or Postgres are needed
Use vitest for running unit tests
**/*.test.{ts,tsx,js,jsx}: Use vitest exclusively for testing and never mock anything - use testcontainers instead
Place test files next to source files with naming pattern: source file (e.g.,MyService.ts) →MyService.test.ts
Files:
packages/ai/src/ai.test.tspackages/ai/src/chatTransport.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use testcontainers helpers (
redisTest,postgresTest,containerTest) from@internal/testcontainersfor Redis/PostgreSQL testing instead of mocks
Files:
packages/ai/src/ai.test.tspackages/ai/src/chatTransport.test.ts
🧠 Learnings (37)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The SDK at packages/trigger-sdk is an isomorphic TypeScript SDK
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation
Applied to files:
packages/ai/src/types.tspackages/ai/src/index.tsdocs/tasks/schemaTask.mdxdocs/tasks/streams.mdx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The SDK at packages/trigger-sdk is an isomorphic TypeScript SDK
Applied to files:
packages/ai/src/types.tspackages/ai/src/index.tsdocs/tasks/schemaTask.mdxdocs/tasks/streams.mdxpackages/ai/package.json.changeset/curly-radios-visit.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation
Applied to files:
packages/ai/src/types.tspackages/ai/src/index.tsdocs/tasks/schemaTask.mdxpackages/ai/src/ai.test.tsdocs/tasks/streams.mdxpackages/ai/src/ai.tspackages/ai/package.json.changeset/curly-radios-visit.mdpackages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties
Applied to files:
packages/ai/src/types.tspackages/ai/src/index.tsdocs/tasks/schemaTask.mdxpackages/ai/src/ai.test.tsdocs/tasks/streams.mdxpackages/ai/src/ai.tspackages/ai/package.json.changeset/curly-radios-visit.mdpackages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `.withStreams()` to subscribe to realtime streams from task metadata in addition to run changes
Applied to files:
packages/ai/src/types.tsdocs/tasks/streams.mdx.changeset/curly-radios-visit.mdpackages/ai/src/chatTransport.tspackages/ai/src/chatTransport.test.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks
Applied to files:
packages/ai/src/types.tspackages/ai/src/index.tsdocs/tasks/schemaTask.mdxdocs/tasks/streams.mdxpackages/ai/package.json.changeset/curly-radios-visit.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `yourTask.trigger()` to trigger a task from inside another task with specified payload
Applied to files:
packages/ai/src/types.tsdocs/tasks/streams.mdx.changeset/curly-radios-visit.mdpackages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.batchTrigger()` to trigger multiple runs of a single task with different payloads
Applied to files:
packages/ai/src/types.tsdocs/tasks/streams.mdxpackages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `batch.trigger()` to trigger multiple different tasks at once from backend code
Applied to files:
packages/ai/src/types.tsdocs/tasks/streams.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Subscribe to run updates using `runs.subscribeToRun()` for realtime monitoring of task execution
Applied to files:
packages/ai/src/types.tspackages/ai/src/chatTransport.test.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : When importing from `trigger.dev/core` in the webapp, use subpath exports from the package.json instead of importing from the root path
Applied to files:
packages/ai/src/index.tsdocs/tasks/schemaTask.mdxpackages/ai/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export every task, including subtasks
Applied to files:
packages/ai/src/index.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure OpenTelemetry instrumentations and exporters in trigger.config.ts for enhanced logging
Applied to files:
packages/ai/src/index.tspackages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Applied to files:
packages/ai/src/index.tspackages/ai/package.json.changeset/curly-radios-visit.mdpackages/ai/src/chatTransport.test.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution
Applied to files:
packages/ai/src/index.tsdocs/tasks/schemaTask.mdxpackages/ai/src/chatTransport.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Always import tasks from `trigger.dev/sdk`, never use `trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern
Applied to files:
docs/tasks/schemaTask.mdxpackages/ai/src/ai.tspackages/ai/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Import from `trigger.dev/core` using subpaths only, never import from root
Applied to files:
docs/tasks/schemaTask.mdxpackages/ai/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Keep the `.claude/skills/trigger-dev-tasks/` skill in sync with the latest rules version when SDK features change
Applied to files:
docs/tasks/schemaTask.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions
Applied to files:
docs/tasks/schemaTask.mdxpackages/ai/src/ai.tspackages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to **/tsconfig.json : Use strict mode in TypeScript configuration
Applied to files:
packages/ai/tsconfig.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Use build extensions in trigger.config.ts (additionalFiles, additionalPackages, aptGet, prismaExtension, etc.) to customize the build
Applied to files:
packages/ai/tsconfig.jsonpackages/ai/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure build process in trigger.config.ts using `build` object with external packages, extensions, and JSX settings
Applied to files:
packages/ai/tsconfig.jsonpackages/ai/package.json
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use function declarations instead of default exports
Applied to files:
packages/ai/tsconfig.json
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to **/*.{test,spec}.{ts,tsx} : Use vitest for all tests in the Trigger.dev repository
Applied to files:
packages/ai/src/ai.test.tspackages/ai/src/chatTransport.test.ts
📚 Learning: 2026-01-15T10:48:02.687Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T10:48:02.687Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vitest for running unit tests
Applied to files:
packages/ai/src/ai.test.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use vitest exclusively for testing and never mock anything - use testcontainers instead
Applied to files:
packages/ai/src/ai.test.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Generate example payloads for tasks when possible
Applied to files:
docs/tasks/streams.mdx.changeset/curly-radios-visit.mdpackages/ai/src/chatTransport.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
Applied to files:
packages/ai/package.json
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Every Trigger.dev task must be exported and have a unique `id` property with no timeouts in the run function
Applied to files:
packages/ai/package.json
📚 Learning: 2025-11-26T14:40:07.146Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2710
File: packages/schema-to-json/package.json:0-0
Timestamp: 2025-11-26T14:40:07.146Z
Learning: Node.js 24+ has native TypeScript support and can execute .ts files directly without tsx or ts-node for scripts that use only erasable TypeScript syntax (type annotations, interfaces, etc.). The trigger.dev repository uses Node.js 24.11.1+ and scripts like updateVersion.ts can be run with `node` instead of `tsx`.
Applied to files:
packages/ai/package.json
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks
Applied to files:
.changeset/curly-radios-visit.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Run `npx trigger.devlatest init` to initialize a Trigger.dev project
Applied to files:
.changeset/curly-radios-visit.md
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions
Applied to files:
packages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run
Applied to files:
packages/ai/src/chatTransport.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/services/**/*.server.{ts,tsx} : Separate testable services from configuration files; follow the pattern of `realtimeClient.server.ts` (testable service) and `realtimeClientGlobal.server.ts` (configuration) in the webapp
Applied to files:
packages/ai/src/chatTransport.test.ts
📚 Learning: 2025-11-27T16:26:44.496Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/executing-commands.mdc:0-0
Timestamp: 2025-11-27T16:26:44.496Z
Learning: For running tests, navigate into the package directory and run `pnpm run test --run` to enable single-file test execution (e.g., `pnpm run test ./src/engine/tests/ttl.test.ts --run`)
Applied to files:
packages/ai/src/chatTransport.test.ts
🧬 Code graph analysis (1)
packages/ai/src/ai.test.ts (1)
packages/ai/src/ai.ts (1)
ai(128-131)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
- GitHub Check: sdk-compat / Cloudflare Workers
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
- GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: typecheck / typecheck
- GitHub Check: sdk-compat / Bun Runtime
- GitHub Check: sdk-compat / Deno Runtime
🔇 Additional comments (10)
docs/tasks/schemaTask.mdx (1)
84-84: Import path updates look correct.All three
aiimport paths are updated consistently to@trigger.dev/ai, matching the new package introduced in this PR.Also applies to: 121-121, 186-186
packages/ai/src/ai.ts (1)
128-131: LGTM — clean public API surface.The
aiobject provides a concise, well-named API (ai.tool,ai.currentToolOptions).packages/ai/src/chatTransport.ts (2)
96-110: LGTM —InMemoryTriggerChatRunStoreis clean and straightforward.Simple in-memory Map-based implementation with synchronous operations. Good default for client-side use.
352-377:normalizeHeadershandles bothHeadersand plain objects correctly.Good defensive check with
isHeadersInstancefor environments whereHeadersmay not exist..changeset/curly-radios-visit.md (1)
1-10: Changeset is present and properly scoped.Minor bump for the new
@trigger.dev/aipackage with a clear summary of the added features.packages/ai/tsconfig.json (1)
1-10: No action needed — strict mode is properly inherited from the base config.The base configuration (
.configs/tsconfig.base.json) has"strict": trueexplicitly enabled, and this tsconfig correctly extends it. The guideline requirement is satisfied.docs/tasks/streams.mdx (1)
588-598: Thechat.sendMessage({ text: "Hello!" })API usage is correct according to official AI SDK documentation. TheuseChat()hook from@ai-sdk/reactreturns asendMessagefunction with the signaturesendMessage(message?, options?) => Promise<void>, which accepts an object withtextand optional properties. The code example matches the documented API.packages/ai/src/ai.test.ts (1)
1-78: Well-structured unit tests for theaihelper.The three test cases cover the happy path (tool creation + execution), the error path (missing schema), and the edge case (no execution context). The use of lightweight in-memory fakes rather than mocks is appropriate here since no external services are involved.
packages/ai/src/chatTransport.test.ts (1)
256-291: Clean test infrastructure with proper cleanup.The
startServerhelper with random port binding,closeAllConnectionsguard, and theafterEachteardown viaactiveServersis well-structured. Good defensive pattern for avoiding port conflicts and leaked server handles.packages/ai/src/index.ts (1)
1-18: Clean barrel file with proper type-only re-exports and changeset documented.The public API surface is well-organized with clear separation between value exports and type-only exports across the three modules. A changeset has been added for this new public package (curly-radios-visit.md).
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| "ai": "^6.0.0", | ||
| "rimraf": "^3.0.2", | ||
| "tshy": "^3.0.2", | ||
| "tsx": "4.17.0", | ||
| "zod": "3.25.76" | ||
| }, | ||
| "peerDependencies": { | ||
| "ai": "^4.2.0 || ^5.0.0 || ^6.0.0", | ||
| "zod": "^3.0.0 || ^4.0.0" |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Vercel AI SDK ChatTransport interface when introduced version history
💡 Result:
When was ChatTransport introduced (Vercel AI SDK)?
ChatTransport was introduced as part of the AI SDK v5 chat redesign (the switch to a “transport-based architecture” for useChat). The v5 useChat docs explicitly call out that AI SDK 5.0 moved to transports and exposes a transport?: ChatTransport option. [1]
Timeline / version history (high-confidence points)
- AI SDK v5 alphas (at least by
5.0.0-alpha.13, June 16, 2025): v5 alpha issues reference the new chat architecture (Chat store/transport concepts were already in play during the alpha cycle). [2] - AI SDK 5 GA (announced July 31, 2025): Vercel’s AI SDK 5 announcement describes the rebuilt chat integration that v5 shipped with. [3]
- First stable package releases that explicitly include “introduce ChatStore and ChatTransport”:
@ai-sdk/react@2.0.0[4]@ai-sdk/vue@2.0.0[5]@ai-sdk/svelte@3.0.0[6]
Where the interface lives (current docs/code)
- The interface is documented/used via
useChat(..., transport?: ChatTransport)in the v5 UI docs. [1] - In the
aipackage source,ChatTransportis defined insrc/ui/chat-transport.ts. [7]
Sources: [1] [2] [3] [4] [5] [6] [7]
🌐 Web query:
Zod npm package version 3.25.76
💡 Result:
zod@3.25.76 is a published version of the Zod npm package (TypeScript-first schema validation). Install it with:
npm i zod@3.25.76It’s listed on npm as version 3.25.76. [1]
🏁 Script executed:
# Check if zod 3.25.76 is a valid published version
npm view zod versions --json | grep "3.25.76"Repository: triggerdotdev/trigger.dev
Length of output: 81
🏁 Script executed:
# Find chatTransport.ts in the repository
find . -name "chatTransport.ts" -o -name "chat-transport.ts" 2>/dev/nullRepository: triggerdotdev/trigger.dev
Length of output: 103
🏁 Script executed:
# Search for ChatTransport imports and usage in the packages/ai directory
rg "ChatTransport" packages/ai/ -A 3 -B 1Repository: triggerdotdev/trigger.dev
Length of output: 9267
🏁 Script executed:
# Check the actual package.json file content to see the full context
cat -n packages/ai/package.json | head -70Repository: triggerdotdev/trigger.dev
Length of output: 2271
Remove AI SDK v4.2.0 from peer dependencies or add version guards.
The code unconditionally imports and implements ChatTransport, which was introduced in AI SDK v5 (released July 31, 2025). The peer dependency "ai": "^4.2.0 || ^5.0.0 || ^6.0.0" incorrectly claims compatibility with v4.2.0, where ChatTransport does not exist. This will cause runtime errors for users with only AI SDK v4 installed. Either tighten the peer dependency to "ai": "^5.0.0 || ^6.0.0" or add version guards around ChatTransport usage. The zod: "3.25.76" devDependency is valid.
🤖 Prompt for AI Agents
In `@packages/ai/package.json` around lines 45 - 53, The peerDependencies
incorrectly include "ai": "^4.2.0" while the code unconditionally imports/uses
ChatTransport (symbol: ChatTransport) which only exists in ai >=5; fix by either
updating the package.json peerDependencies to "ai": "^5.0.0 || ^6.0.0" or add
runtime/version guards around ChatTransport usage (e.g., check the installed ai
package version or confirm ChatTransport exists before importing/instantiating
and provide a fallback/error), and ensure the change is applied where
ChatTransport is imported/used and reflected in package.json peerDependencies.
| if (("schema" in task && !task.schema) || ("jsonSchema" in task && !task.jsonSchema)) { | ||
| throw new Error( | ||
| "Cannot convert this task to to a tool because the task has no schema. Make sure to either use schemaTask or a task with an input jsonSchema." | ||
| ); | ||
| } |
There was a problem hiding this comment.
Validation logic may incorrectly reject tasks that have a valid schema but an undefined jsonSchema property.
The || means this throws if either property is present but falsy. A TaskWithSchema with a valid schema could still have jsonSchema in its prototype (from the union type on line 58) set to undefined, causing a false rejection. Consider using && to only throw when both are unusable, or restructuring the check:
Suggested fix
- if (("schema" in task && !task.schema) || ("jsonSchema" in task && !task.jsonSchema)) {
+ const hasSchema = "schema" in task && !!task.schema;
+ const hasJsonSchema = "jsonSchema" in task && !!task.jsonSchema;
+ if (!hasSchema && !hasJsonSchema) {
throw new Error(
"Cannot convert this task to to a tool because the task has no schema. Make sure to either use schemaTask or a task with an input jsonSchema."
);
}Also, minor: there's a typo "to to a tool" → "to a tool" in the error message.
#!/bin/bash
# Check what properties Task and TaskWithSchema types expose
ast-grep --pattern 'type Task<$$$> = {
$$$
}'
ast-grep --pattern 'type TaskWithSchema<$$$> = {
$$$
}'
# Also check AnyTask
rg -n "type AnyTask" --type=ts -A5
rg -n "type Task<" --type=ts -A10 -g '!node_modules' -g '!*.test.*' | head -60🤖 Prompt for AI Agents
In `@packages/ai/src/ai.ts` around lines 63 - 67, The validation in the conversion
check erroneously throws when either "schema" or "jsonSchema" is present but
falsy; change the logic in the block around the task check so it only throws
when both schema sources are absent/unusable (e.g., require that ("schema" in
task && !task.schema) AND ("jsonSchema" in task && !task.jsonSchema") before
throwing), and fix the error message text from "to to a tool" to "to a tool";
update references in this change for the Task/TaskWithSchema handling where
task, schema, and jsonSchema are inspected.
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Co-authored-by: Eric Allam <eric@trigger.dev>
Closes #
✅ Checklist
Testing
Unit and integration tests were added for the new
@trigger.dev/aipackage, covering the chat transport, task triggering, and stream handling. End-to-end validation was performed by updating thereferences/realtime-streamsexample to use the new transport, demonstrating a functional AI SDK chat frontend powered by a Trigger.dev task.Changelog
This PR introduces the new
@trigger.dev/aipackage, enabling a typesafe and ergonomic integration for AI SDK chat applications with Trigger.dev tasks and Realtime Streams v2.Key changes include:
@trigger.dev/aipackage: Provides a custom AI SDK chat transport.ai.tool: The existingai.toolandai.currentToolOptionsfunctionality has been moved to this new package.references/realtime-streamsexample now uses the new AI SDK chat transport.Screenshots
💯