Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
906d5fa
feat(mollifier): trigger burst smoothing — Phase 1 (monitoring) (#3614)
d-cs May 18, 2026
8b98e21
fix(sdk,core): cache realtime-stream credentials per slot with refres…
ericallam May 18, 2026
427d9e0
feat(sdk): functional baseURL and fetch override on chat transports (…
ericallam May 18, 2026
02d61af
fix(webapp): sanitize OTel attributes on ClickHouse JSON parse reject…
0ski May 18, 2026
5dacab0
fix: validate email format on magic link login (#3660)
nicktrn May 18, 2026
2f261e5
fix(webapp): catch loader/action throws before Remix serializes them …
d-cs May 19, 2026
e825409
ci(release): exit changeset pre mode before snapshot prerelease (#3665)
ericallam May 19, 2026
2fbac48
feat(webapp): prompt to clear TRIGGER_VERSION on disabling Vercel ato…
0ski May 19, 2026
436b7a9
fix(webapp): fold S2 token scope into access-token cache key (#3668)
ericallam May 19, 2026
204a766
feat(webapp): expose is_warm_start in TRQL runs schema (#3667)
isshaddad May 19, 2026
12d2125
fix(sdk,core,build): SDK hardening pass (#3670)
ericallam May 19, 2026
f91b96e
feat(sdk,core): preserve chat.agent context after cancel / OOM / cras…
ericallam May 20, 2026
6b46a34
fix(webapp): return 404 instead of 500 for missing env/project/schedu…
d-cs May 20, 2026
aec7e0a
perf(webapp): index EnvironmentVariableValue.environmentId (#3675)
ericallam May 20, 2026
d343727
fix(webapp,sdk): keep chat.agent snapshots on one object store (#3679)
ericallam May 20, 2026
9ff410b
feat(sdk): type chat.createStartSessionAction against your chat agent…
ericallam May 21, 2026
89d085a
fix(references): repair ai-chat typecheck against current wire shape …
ericallam May 21, 2026
422f9f0
ci: unblock changesets release PRs (#3687)
ericallam May 21, 2026
acfba02
chore: release v4.5.0-rc.0 (#3563)
github-actions[bot] May 21, 2026
dbf9b4e
fix(core,cli): register tasks loaded via dynamic import during run (#…
nicktrn May 21, 2026
5ddb81a
fix(cli): stop chat.agent skills silently disappearing from trigger d…
ericallam May 21, 2026
0b5b817
chore: release v4.5.0-rc.1 (#3691)
github-actions[bot] May 21, 2026
80bb600
docs(ai-chat): AI Agents documentation for v4.5 (#3226)
ericallam May 21, 2026
c80b85e
docs(ai-chat): atomic onTurnComplete writes + Anthropic prose (#3693)
ericallam May 21, 2026
f27aa53
fix: null-safe getTime() calls in replication services (#3519)
May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bundle-skills-single-pass.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---

Fix `chat.agent` skills silently missing in `trigger dev` for projects whose task files read `process.env` at module top level (e.g. a third-party SDK client initialized at import). Skill folders now bundle into `.trigger/skills/` reliably regardless of which env vars are set when the CLI launches.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Changeset description does not match the PR changes. The PR fixes null-safe getTime() calls in the ClickHouse replication service, but the changeset describes an unrelated fix about chat.agent skills in trigger dev. This will generate an incorrect changelog entry and mislead users about what was fixed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .changeset/bundle-skills-single-pass.md, line 5:

<comment>Changeset description does not match the PR changes. The PR fixes null-safe `getTime()` calls in the ClickHouse replication service, but the changeset describes an unrelated fix about `chat.agent` skills in `trigger dev`. This will generate an incorrect changelog entry and mislead users about what was fixed.</comment>

<file context>
@@ -0,0 +1,5 @@
+"trigger.dev": patch
+---
+
+Fix `chat.agent` skills silently missing in `trigger dev` for projects whose task files read `process.env` at module top level (e.g. a third-party SDK client initialized at import). Skill folders now bundle into `.trigger/skills/` reliably regardless of which env vars are set when the CLI launches.
</file context>
Suggested change
Fix `chat.agent` skills silently missing in `trigger dev` for projects whose task files read `process.env` at module top level (e.g. a third-party SDK client initialized at import). Skill folders now bundle into `.trigger/skills/` reliably regardless of which env vars are set when the CLI launches.
Fix null-safe `getTime()` calls in the ClickHouse replication service for `createdAt` and `updatedAt` in `toTaskRunInsertArray` and `toSessionInsertArray`, preventing `TypeError: Cannot read properties of undefined (reading 'getTime')` when task runs or sessions are synced before their timestamps are fully populated.

22 changes: 22 additions & 0 deletions .changeset/chat-start-session-action-typed-client-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"@trigger.dev/sdk": patch
---

Type `chat.createStartSessionAction` against your chat agent so `clientData` is typed end-to-end on the first turn:

```ts
import { chat } from "@trigger.dev/sdk/ai";
import type { myChat } from "@/trigger/chat";

export const startChatSession = chat.createStartSessionAction<typeof myChat>("my-chat");

// In the browser, threaded from the transport's typed startSession callback:
const transport = useTriggerChatTransport<typeof myChat>({
task: "my-chat",
startSession: ({ chatId, clientData }) =>
startChatSession({ chatId, clientData }),
// ...
});
```

`ChatStartSessionParams` gains a typed `clientData` field — folded into the first run's `payload.metadata` so `onPreload` / `onChatStart` see the same shape per-turn `metadata` carries via the transport. The opaque session-level `metadata` field is unchanged.
9 changes: 9 additions & 0 deletions .changeset/mollifier-redis-worker-primitives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@trigger.dev/redis-worker": patch
---

Add MollifierBuffer and MollifierDrainer primitives for trigger burst smoothing.

MollifierBuffer (`accept`, `pop`, `ack`, `requeue`, `fail`, `evaluateTrip`) is a per-env FIFO over Redis with atomic Lua transitions for status tracking. `evaluateTrip` is a sliding-window trip evaluator the webapp gate uses to detect per-env trigger bursts.

MollifierDrainer pops entries through a polling loop with a user-supplied handler. The loop survives transient Redis errors via capped exponential backoff (up to 5s), and per-env pop failures don't poison the rest of the batch — one env's blip is logged and counted as failed for that tick. Rotation is two-level: orgs at the top, envs within each org. The buffer maintains `mollifier:orgs` and `mollifier:org-envs:${orgId}` atomically with per-env queues, so the drainer walks orgs → envs directly without an in-memory cache. The `maxOrgsPerTick` option (default 500) caps how many orgs are scheduled per tick; for each picked org, one env is popped (rotating round-robin within the org). An org with N envs gets the same per-tick scheduling slot as an org with 1 env, so tenant-level drainage throughput is determined by org count rather than env count.
24 changes: 23 additions & 1 deletion .changeset/pre.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,27 @@
"@trigger.dev/schema-to-json": "4.4.6",
"@trigger.dev/sdk": "4.4.6"
},
"changesets": []
"changesets": [
"agent-skills",
"ai-prompts",
"ai-tool-helpers",
"bundle-skills-single-pass",
"cap-idempotency-key-length",
"chat-agent-on-boot-hook",
"chat-agent",
"chat-history-read-primitives",
"chat-session-attributes",
"chat-start-session-action-typed-client-data",
"cli-deploy-skip-rewrite-timestamp",
"locals-key-dual-package-fix",
"mcp-agent-chat-sessions",
"mcp-list-runs-region",
"mock-chat-agent-test-harness",
"mollifier-redis-worker-primitives",
"plugin-auth-path",
"resource-catalog-runtime-registration",
"retry-sigsegv",
"runs-list-region-filter",
"sessions-primitive"
]
}
6 changes: 6 additions & 0 deletions .changeset/resource-catalog-runtime-registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@trigger.dev/core": patch
"trigger.dev": patch
---

Fix `COULD_NOT_FIND_EXECUTOR` when a task's definition is loaded via `await import(...)` from inside another task's `run()`. The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: The changeset describes a fix for COULD_NOT_FIND_EXECUTOR in runtime workers, but the PR title states this is about null-safe getTime() calls in the ClickHouse replication service. These are unrelated issues. When published, this changeset will generate a misleading changelog entry that doesn't match the PR's actual changes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .changeset/resource-catalog-runtime-registration.md, line 6:

<comment>The changeset describes a fix for `COULD_NOT_FIND_EXECUTOR` in runtime workers, but the PR title states this is about null-safe `getTime()` calls in the ClickHouse replication service. These are unrelated issues. When published, this changeset will generate a misleading changelog entry that doesn't match the PR's actual changes.</comment>

<file context>
@@ -0,0 +1,6 @@
+"trigger.dev": patch
+---
+
+Fix `COULD_NOT_FIND_EXECUTOR` when a task's definition is loaded via `await import(...)` from inside another task's `run()`. The runtime workers now register such tasks with a sentinel file context, and the catalog logs a one-time warning per task id.
</file context>

25 changes: 25 additions & 0 deletions .github/workflows/changesets-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
permissions:
contents: write
pull-requests: write
checks: write
if: github.repository == 'triggerdotdev/trigger.dev'
steps:
- name: Checkout
Expand Down Expand Up @@ -72,3 +73,27 @@ jobs:
-f body="$ENHANCED_BODY"
fi
fi

# The changesets bot authors release PRs with GITHUB_TOKEN, which by GitHub
# design cannot trigger downstream workflows. That leaves the required
# "All PR Checks" status permanently Expected and the PR unmergeable.
# The release PR only bumps package.json + lockfile + CHANGELOGs from
# changesets already on main, so we self-report the required check as
# success. If a human ever pushes to changeset-release/main, the real
# pr_checks.yml fires and its result overwrites this one (last write wins
# for the same context on the same SHA).
- name: Self-report "All PR Checks" success on release PR
if: steps.changesets.outputs.published != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER=$(gh pr list --head changeset-release/main --json number --jq '.[0].number')
if [ -z "$PR_NUMBER" ]; then exit 0; fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The no-PR guard misses the null case from gh --jq, so the step can continue with an invalid PR number and fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/changesets-pr.yml, line 91:

<comment>The no-PR guard misses the `null` case from `gh --jq`, so the step can continue with an invalid PR number and fail.</comment>

<file context>
@@ -72,3 +73,27 @@ jobs:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          PR_NUMBER=$(gh pr list --head changeset-release/main --json number --jq '.[0].number')
+          if [ -z "$PR_NUMBER" ]; then exit 0; fi
+          HEAD_SHA=$(gh pr view "$PR_NUMBER" --json headRefOid --jq '.headRefOid')
+          gh api -X POST repos/${{ github.repository }}/check-runs \
</file context>
Suggested change
if [ -z "$PR_NUMBER" ]; then exit 0; fi
if [ -z "$PR_NUMBER" ] || [ "$PR_NUMBER" = "null" ]; then exit 0; fi

HEAD_SHA=$(gh pr view "$PR_NUMBER" --json headRefOid --jq '.headRefOid')
gh api -X POST repos/${{ github.repository }}/check-runs \
-f name="All PR Checks" \
-f head_sha="$HEAD_SHA" \
-f status=completed \
-f conclusion=success \
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: This auto-pass check is reported as success without validating the PR contents, so required checks can be bypassed if the release branch contains unexpected code changes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/changesets-pr.yml, line 97:

<comment>This auto-pass check is reported as success without validating the PR contents, so required checks can be bypassed if the release branch contains unexpected code changes.</comment>

<file context>
@@ -72,3 +73,27 @@ jobs:
+            -f name="All PR Checks" \
+            -f head_sha="$HEAD_SHA" \
+            -f status=completed \
+            -f conclusion=success \
+            -f 'output[title]=Auto-pass for changeset release PR' \
+            -f 'output[summary]=Required check auto-satisfied for changeset-release/main PRs. Full CI ran on the underlying commits before they landed on main.'
</file context>

-f 'output[title]=Auto-pass for changeset release PR' \
-f 'output[summary]=Required check auto-satisfied for changeset-release/main PRs. Full CI ran on the underlying commits before they landed on main.'
7 changes: 7 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ jobs:
- name: Generate Prisma Client
run: pnpm run generate

- name: Exit changeset pre mode (if active)
run: |
if [ -f .changeset/pre.json ]; then
echo "Repo is in changeset pre mode; exiting so snapshot release can run"
pnpm exec changeset pre exit
fi

- name: Snapshot version
run: pnpm exec changeset version --snapshot "${GITHUB_EVENT_INPUTS_PRERELEASE_TAG}"
env:
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/vouch-check-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ jobs:
github.event.pull_request.author_association != 'OWNER' &&
github.event.pull_request.author_association != 'COLLABORATOR' &&
github.event.pull_request.user.login != 'devin-ai-integration[bot]' &&
github.event.pull_request.user.login != 'dependabot[bot]'
github.event.pull_request.user.login != 'dependabot[bot]' &&
github.event.pull_request.user.login != 'github-actions[bot]'
runs-on: ubuntu-latest
steps:
- name: Close non-draft PR
Expand Down
6 changes: 0 additions & 6 deletions .server-changes/admin-tabs-preserve-search.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/agent-playground.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/agents-dashboard.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/ai-span-inspector.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/fix-ck-queue-length-cap-and-dashboard.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/fix-worker-deployment-version-race.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/google-auth-conflict-warn.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/models-registry.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/plugin-auth-path.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/prompts-dashboard.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/realtimestreams-dedupe.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/run-agent-view.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/runs-task-source-filter.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/sessions-dashboard.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/streamdown-v2-upgrade.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/task-metadata-cache.md

This file was deleted.

6 changes: 0 additions & 6 deletions .server-changes/webapp-sentry-fingerprint-p1001.md

This file was deleted.

22 changes: 22 additions & 0 deletions apps/webapp/app/components/integrations/VercelBuildSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ type BuildSettingsFieldsProps = {
disabledEnvSlugs?: Partial<Record<EnvSlug, string>>;
autoPromote?: boolean;
onAutoPromoteChange?: (value: boolean) => void;
/** The currently pinned TRIGGER_VERSION on Vercel production, if any. Shown under the
* Atomic deployments toggle so the user knows what version is set on Vercel right now. */
currentTriggerVersion?: string | null;
/** True when the Vercel lookup for TRIGGER_VERSION failed. We show this so the user knows
* the pin status is unknown — distinct from "not set". */
currentTriggerVersionFetchFailed?: boolean;
/** Hide the section-level master toggles for "Pull env vars" and "Discover new env vars". */
hideSectionToggles?: boolean;
};
Expand All @@ -39,6 +45,8 @@ export function BuildSettingsFields({
disabledEnvSlugs,
autoPromote,
onAutoPromoteChange,
currentTriggerVersion,
currentTriggerVersionFetchFailed,
hideSectionToggles,
}: BuildSettingsFieldsProps) {
const isSlugDisabled = (slug: EnvSlug) => !!disabledEnvSlugs?.[slug];
Expand Down Expand Up @@ -208,6 +216,20 @@ export function BuildSettingsFields({
</TextLink>
.
</Hint>
{currentTriggerVersion && (
<Hint className="pr-6">
Currently pinned to{" "}
<span className="font-mono text-text-bright">{currentTriggerVersion}</span> in Vercel
production.
</Hint>
)}
{!currentTriggerVersion && currentTriggerVersionFetchFailed && (
<Hint className="pr-6 text-warning">
Couldn't read{" "}
<span className="font-mono text-text-bright">TRIGGER_VERSION</span> from Vercel —
check the Vercel dashboard to confirm the production pin.
</Hint>
)}
</div>

{/* Auto promotion — only visible when atomic deployments are on */}
Expand Down
3 changes: 3 additions & 0 deletions apps/webapp/app/entry.server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import isbot from "isbot";
import { renderToPipeableStream } from "react-dom/server";
import { PassThrough } from "stream";
import * as Worker from "~/services/worker.server";
import { initMollifierDrainerWorker } from "~/v3/mollifierDrainerWorker.server";
import { bootstrap } from "./bootstrap";
import { LocaleContextProvider } from "./components/primitives/LocaleProvider";
import {
Expand Down Expand Up @@ -247,6 +248,8 @@ Worker.init().catch((error) => {
logError(error);
});

initMollifierDrainerWorker();

bootstrap().catch((error) => {
logError(error);
});
Expand Down
41 changes: 41 additions & 0 deletions apps/webapp/app/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,47 @@ const EnvironmentSchema = z
COMMON_WORKER_REDIS_TLS_DISABLED: z.string().default(process.env.REDIS_TLS_DISABLED ?? "false"),
COMMON_WORKER_REDIS_CLUSTER_MODE_ENABLED: z.string().default("0"),

TRIGGER_MOLLIFIER_ENABLED: z.string().default("0"),
// Separate switch for the drainer (consumer side) so it can be split
// off onto a dedicated worker service. Unset → inherits
// TRIGGER_MOLLIFIER_ENABLED, so single-container self-hosters don't have to
// flip two switches. In multi-replica deployments, set this to "0"
// explicitly on every replica except the one dedicated drainer
// service — otherwise every replica's polling loop races for the
// same buffer entries. `TRIGGER_MOLLIFIER_ENABLED` is still the master kill
// switch; setting this to "1" while `TRIGGER_MOLLIFIER_ENABLED` is "0" is a
// no-op because the gate-side singleton refuses to construct a
// buffer when the system is off.
TRIGGER_MOLLIFIER_DRAINER_ENABLED: z.string().default(process.env.TRIGGER_MOLLIFIER_ENABLED ?? "0"),
TRIGGER_MOLLIFIER_SHADOW_MODE: z.string().default("0"),
TRIGGER_MOLLIFIER_REDIS_HOST: z
.string()
.optional()
.transform((v) => v ?? process.env.REDIS_HOST),
TRIGGER_MOLLIFIER_REDIS_PORT: z.coerce
.number()
.optional()
.transform(
(v) => v ?? (process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : undefined),
),
TRIGGER_MOLLIFIER_REDIS_USERNAME: z
.string()
.optional()
.transform((v) => v ?? process.env.REDIS_USERNAME),
TRIGGER_MOLLIFIER_REDIS_PASSWORD: z
.string()
.optional()
.transform((v) => v ?? process.env.REDIS_PASSWORD),
TRIGGER_MOLLIFIER_REDIS_TLS_DISABLED: z.string().default(process.env.REDIS_TLS_DISABLED ?? "false"),
TRIGGER_MOLLIFIER_TRIP_WINDOW_MS: z.coerce.number().int().positive().default(200),
TRIGGER_MOLLIFIER_TRIP_THRESHOLD: z.coerce.number().int().positive().default(100),
TRIGGER_MOLLIFIER_HOLD_MS: z.coerce.number().int().positive().default(500),
TRIGGER_MOLLIFIER_DRAIN_CONCURRENCY: z.coerce.number().int().positive().default(50),
TRIGGER_MOLLIFIER_ENTRY_TTL_S: z.coerce.number().int().positive().default(600),
TRIGGER_MOLLIFIER_DRAIN_MAX_ATTEMPTS: z.coerce.number().int().positive().default(3),
TRIGGER_MOLLIFIER_DRAIN_SHUTDOWN_TIMEOUT_MS: z.coerce.number().int().positive().default(30_000),
TRIGGER_MOLLIFIER_DRAIN_MAX_ORGS_PER_TICK: z.coerce.number().int().positive().default(500),

BATCH_TRIGGER_PROCESS_JOB_VISIBILITY_TIMEOUT_MS: z.coerce
.number()
.int()
Expand Down
Loading
Loading