Skip to content

Commit c6ebc5a

Browse files
Merge branch 'main' into fix/task-run-refresh-lag-2798
2 parents 92fd9f9 + d893b26 commit c6ebc5a

File tree

102 files changed

+9854
-3066
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+9854
-3066
lines changed

.changeset/ai-sdk-v6-support.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
"@trigger.dev/core": patch
4+
---
5+
6+
Add support for AI SDK v6 (Vercel AI SDK)
7+
8+
- Updated peer dependency to allow `ai@^6.0.0` alongside v4 and v5
9+
- Updated internal code to handle async validation from AI SDK v6's Schema type

.changeset/bright-keys-shine.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@trigger.dev/sdk": patch
3+
"@trigger.dev/core": patch
4+
---
5+
6+
Expose user-provided idempotency key and scope in task context. `ctx.run.idempotencyKey` now returns the original key passed to `idempotencyKeys.create()` instead of the hash, and `ctx.run.idempotencyKeyScope` shows the scope ("run", "attempt", or "global").

.changeset/gentle-streams-flow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/core": patch
3+
---
4+
5+
Fix batch trigger failing with "ReadableStream is locked" error when network failures occur mid-stream. Added safe stream cancellation that gracefully handles locked streams during retry attempts.

apps/supervisor/src/env.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,25 @@ const Env = z.object({
8989
KUBERNETES_CPU_REQUEST_RATIO: z.coerce.number().min(0).max(1).default(0.75), // Ratio of CPU limit, so 0.75 = 75% of CPU limit
9090
KUBERNETES_MEMORY_REQUEST_MIN_GB: z.coerce.number().min(0).default(0),
9191
KUBERNETES_MEMORY_REQUEST_RATIO: z.coerce.number().min(0).max(1).default(1), // Ratio of memory limit, so 1 = 100% of memory limit
92+
93+
// Per-preset overrides of the global KUBERNETES_CPU_REQUEST_RATIO
94+
KUBERNETES_CPU_REQUEST_RATIO_MICRO: z.coerce.number().min(0).max(1).optional(),
95+
KUBERNETES_CPU_REQUEST_RATIO_SMALL_1X: z.coerce.number().min(0).max(1).optional(),
96+
KUBERNETES_CPU_REQUEST_RATIO_SMALL_2X: z.coerce.number().min(0).max(1).optional(),
97+
KUBERNETES_CPU_REQUEST_RATIO_MEDIUM_1X: z.coerce.number().min(0).max(1).optional(),
98+
KUBERNETES_CPU_REQUEST_RATIO_MEDIUM_2X: z.coerce.number().min(0).max(1).optional(),
99+
KUBERNETES_CPU_REQUEST_RATIO_LARGE_1X: z.coerce.number().min(0).max(1).optional(),
100+
KUBERNETES_CPU_REQUEST_RATIO_LARGE_2X: z.coerce.number().min(0).max(1).optional(),
101+
102+
// Per-preset overrides of the global KUBERNETES_MEMORY_REQUEST_RATIO
103+
KUBERNETES_MEMORY_REQUEST_RATIO_MICRO: z.coerce.number().min(0).max(1).optional(),
104+
KUBERNETES_MEMORY_REQUEST_RATIO_SMALL_1X: z.coerce.number().min(0).max(1).optional(),
105+
KUBERNETES_MEMORY_REQUEST_RATIO_SMALL_2X: z.coerce.number().min(0).max(1).optional(),
106+
KUBERNETES_MEMORY_REQUEST_RATIO_MEDIUM_1X: z.coerce.number().min(0).max(1).optional(),
107+
KUBERNETES_MEMORY_REQUEST_RATIO_MEDIUM_2X: z.coerce.number().min(0).max(1).optional(),
108+
KUBERNETES_MEMORY_REQUEST_RATIO_LARGE_1X: z.coerce.number().min(0).max(1).optional(),
109+
KUBERNETES_MEMORY_REQUEST_RATIO_LARGE_2X: z.coerce.number().min(0).max(1).optional(),
110+
92111
KUBERNETES_MEMORY_OVERHEAD_GB: z.coerce.number().min(0).optional(), // Optional memory overhead to add to the limit in GB
93112
KUBERNETES_SCHEDULER_NAME: z.string().optional(), // Custom scheduler name for pods
94113
KUBERNETES_LARGE_MACHINE_POOL_LABEL: z.string().optional(), // if set, large-* presets affinity for machinepool=<value>

apps/supervisor/src/workloadManager/kubernetes.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ import {
44
type WorkloadManagerCreateOptions,
55
type WorkloadManagerOptions,
66
} from "./types.js";
7-
import type { EnvironmentType, MachinePreset, PlacementTag } from "@trigger.dev/core/v3";
7+
import type {
8+
EnvironmentType,
9+
MachinePreset,
10+
MachinePresetName,
11+
PlacementTag,
12+
} from "@trigger.dev/core/v3";
813
import { PlacementTagProcessor } from "@trigger.dev/core/v3/serverOnly";
914
import { env } from "../env.js";
1015
import { type K8sApi, createK8sApi, type k8s } from "../clients/kubernetes.js";
@@ -14,6 +19,26 @@ type ResourceQuantities = {
1419
[K in "cpu" | "memory" | "ephemeral-storage"]?: string;
1520
};
1621

22+
const cpuRequestRatioByMachinePreset: Record<MachinePresetName, number | undefined> = {
23+
micro: env.KUBERNETES_CPU_REQUEST_RATIO_MICRO,
24+
"small-1x": env.KUBERNETES_CPU_REQUEST_RATIO_SMALL_1X,
25+
"small-2x": env.KUBERNETES_CPU_REQUEST_RATIO_SMALL_2X,
26+
"medium-1x": env.KUBERNETES_CPU_REQUEST_RATIO_MEDIUM_1X,
27+
"medium-2x": env.KUBERNETES_CPU_REQUEST_RATIO_MEDIUM_2X,
28+
"large-1x": env.KUBERNETES_CPU_REQUEST_RATIO_LARGE_1X,
29+
"large-2x": env.KUBERNETES_CPU_REQUEST_RATIO_LARGE_2X,
30+
};
31+
32+
const memoryRequestRatioByMachinePreset: Record<MachinePresetName, number | undefined> = {
33+
micro: env.KUBERNETES_MEMORY_REQUEST_RATIO_MICRO,
34+
"small-1x": env.KUBERNETES_MEMORY_REQUEST_RATIO_SMALL_1X,
35+
"small-2x": env.KUBERNETES_MEMORY_REQUEST_RATIO_SMALL_2X,
36+
"medium-1x": env.KUBERNETES_MEMORY_REQUEST_RATIO_MEDIUM_1X,
37+
"medium-2x": env.KUBERNETES_MEMORY_REQUEST_RATIO_MEDIUM_2X,
38+
"large-1x": env.KUBERNETES_MEMORY_REQUEST_RATIO_LARGE_1X,
39+
"large-2x": env.KUBERNETES_MEMORY_REQUEST_RATIO_LARGE_2X,
40+
};
41+
1742
export class KubernetesWorkloadManager implements WorkloadManager {
1843
private readonly logger = new SimpleStructuredLogger("kubernetes-workload-provider");
1944
private k8s: K8sApi;
@@ -321,8 +346,11 @@ export class KubernetesWorkloadManager implements WorkloadManager {
321346
}
322347

323348
#getResourceRequestsForMachine(preset: MachinePreset): ResourceQuantities {
324-
const cpuRequest = preset.cpu * this.cpuRequestRatio;
325-
const memoryRequest = preset.memory * this.memoryRequestRatio;
349+
const cpuRatio = cpuRequestRatioByMachinePreset[preset.name] ?? this.cpuRequestRatio;
350+
const memoryRatio = memoryRequestRatioByMachinePreset[preset.name] ?? this.memoryRequestRatio;
351+
352+
const cpuRequest = preset.cpu * cpuRatio;
353+
const memoryRequest = preset.memory * memoryRatio;
326354

327355
// Clamp between min and max
328356
const clampedCpu = this.clamp(cpuRequest, this.cpuRequestMinCores, preset.cpu);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
export function AbacusIcon({ className }: { className?: string }) {
2+
return (
3+
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
4+
<g clipPath="url(#clip0_16909_120578)">
5+
<path
6+
d="M4 3V21"
7+
stroke="currentColor"
8+
strokeWidth="2"
9+
strokeLinecap="round"
10+
strokeLinejoin="round"
11+
/>
12+
<path
13+
d="M20 21V3"
14+
stroke="currentColor"
15+
strokeWidth="2"
16+
strokeLinecap="round"
17+
strokeLinejoin="round"
18+
/>
19+
<path
20+
d="M8 5L8 6"
21+
stroke="currentColor"
22+
strokeWidth="2"
23+
strokeLinecap="round"
24+
strokeLinejoin="round"
25+
/>
26+
<path
27+
d="M14 5L14 6"
28+
stroke="currentColor"
29+
strokeWidth="2"
30+
strokeLinecap="round"
31+
strokeLinejoin="round"
32+
/>
33+
<path
34+
d="M15 10L15 11"
35+
stroke="currentColor"
36+
strokeWidth="2"
37+
strokeLinecap="round"
38+
strokeLinejoin="round"
39+
/>
40+
<path
41+
d="M9 10L9 11"
42+
stroke="currentColor"
43+
strokeWidth="2"
44+
strokeLinecap="round"
45+
strokeLinejoin="round"
46+
/>
47+
<path
48+
d="M12 15L12 16"
49+
stroke="currentColor"
50+
strokeWidth="2"
51+
strokeLinecap="round"
52+
strokeLinejoin="round"
53+
/>
54+
<path
55+
d="M8 15L8 16"
56+
stroke="currentColor"
57+
strokeWidth="2"
58+
strokeLinecap="round"
59+
strokeLinejoin="round"
60+
/>
61+
<path
62+
d="M3 21H21"
63+
stroke="currentColor"
64+
strokeWidth="2"
65+
strokeLinecap="round"
66+
strokeLinejoin="round"
67+
/>
68+
</g>
69+
</svg>
70+
);
71+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export function ArrowTopRightBottomLeftIcon({ className }: { className?: string }) {
2+
return (
3+
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
4+
<path
5+
d="M14.8258 10.5L20.125 5.20083V8.5625C20.125 9.08027 20.5447 9.5 21.0625 9.5C21.5803 9.5 22 9.08027 22 8.5625V2.9375C22 2.41973 21.5803 2 21.0625 2H15.4375C14.9197 2 14.5 2.41973 14.5 2.9375C14.5 3.45527 14.9197 3.875 15.4375 3.875H18.7992L13.5 9.17417C13.1339 9.54029 13.1339 10.1339 13.5 10.5C13.8661 10.8661 14.4597 10.8661 14.8258 10.5Z"
6+
fill="currentColor"
7+
/>
8+
<path
9+
d="M2 21.0625V15.4375C2 14.9197 2.41973 14.5 2.9375 14.5C3.45527 14.5 3.875 14.9197 3.875 15.4375V18.7992L9.17417 13.5C9.54029 13.1339 10.1339 13.1339 10.5 13.5C10.8661 13.8661 10.8661 14.4597 10.5 14.8258L5.20083 20.125H8.5625C9.08027 20.125 9.5 20.5447 9.5 21.0625C9.5 21.5803 9.08027 22 8.5625 22H2.9375C2.69757 22 2.45765 21.9085 2.27459 21.7254C2.1847 21.6355 2.11689 21.5319 2.07114 21.4214C2.0253 21.3108 2 21.1896 2 21.0625Z"
10+
fill="currentColor"
11+
/>
12+
<path
13+
d="M14.8258 10.5L20.125 5.20083V10C20.125 10.5178 20.5447 10.9375 21.0625 10.9375C21.5803 10.9375 22 10.5178 22 10V2.9375C22 2.41973 21.5803 2 21.0625 2H14C13.4822 2 13.0625 2.41973 13.0625 2.9375C13.0625 3.45527 13.4822 3.875 14 3.875H18.7992L13.5 9.17417C13.1339 9.54029 13.1339 10.1339 13.5 10.5C13.8661 10.8661 14.4597 10.8661 14.8258 10.5Z"
14+
fill="currentColor"
15+
/>
16+
<path
17+
d="M2 21.0625V13.9375C2 13.4197 2.41973 13 2.9375 13C3.45527 13 3.875 13.4197 3.875 13.9375V18.7992L9.17417 13.5C9.54029 13.1339 10.1339 13.1339 10.5 13.5C10.8661 13.8661 10.8661 14.4597 10.5 14.8258L5.20083 20.125H10.0625C10.5803 20.125 11 20.5447 11 21.0625C11 21.5803 10.5803 22 10.0625 22H2.9375C2.69757 22 2.45765 21.9085 2.27459 21.7254C2.1847 21.6355 2.11689 21.5319 2.07114 21.4214C2.0253 21.3108 2 21.1896 2 21.0625Z"
18+
fill="currentColor"
19+
/>
20+
</svg>
21+
);
22+
}

apps/webapp/app/components/code/AIQueryInput.tsx

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,22 @@ import { Spinner } from "~/components/primitives/Spinner";
1818
import { useEnvironment } from "~/hooks/useEnvironment";
1919
import { useOrganization } from "~/hooks/useOrganizations";
2020
import { useProject } from "~/hooks/useProject";
21+
import type { AITimeFilter } from "~/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.query/types";
2122
import { cn } from "~/utils/cn";
2223

2324
type StreamEventType =
2425
| { type: "thinking"; content: string }
2526
| { type: "tool_call"; tool: string; args: unknown }
26-
| { type: "result"; success: true; query: string }
27+
| { type: "time_filter"; filter: AITimeFilter }
28+
| { type: "result"; success: true; query: string; timeFilter?: AITimeFilter }
2729
| { type: "result"; success: false; error: string };
2830

2931
export type AIQueryMode = "new" | "edit";
3032

3133
interface AIQueryInputProps {
3234
onQueryGenerated: (query: string) => void;
35+
/** Called when the AI sets a time filter - updates URL search params */
36+
onTimeFilterChange?: (filter: AITimeFilter) => void;
3337
/** Set this to a prompt to auto-populate and immediately submit */
3438
autoSubmitPrompt?: string;
3539
/** Change this to force re-submission even if prompt is the same */
@@ -40,6 +44,7 @@ interface AIQueryInputProps {
4044

4145
export function AIQueryInput({
4246
onQueryGenerated,
47+
onTimeFilterChange,
4348
autoSubmitPrompt,
4449
autoSubmitKey,
4550
getCurrentQuery,
@@ -174,10 +179,32 @@ export function AIQueryInput({
174179
setThinking((prev) => prev + event.content);
175180
break;
176181
case "tool_call":
177-
setThinking((prev) => prev + `\nValidating query...\n`);
182+
if (event.tool === "setTimeFilter") {
183+
setThinking((prev) => {
184+
if (prev.trimEnd().endsWith("Setting time filter...")) {
185+
return prev;
186+
}
187+
return prev + `\nSetting time filter...\n`;
188+
});
189+
} else {
190+
setThinking((prev) => {
191+
if (prev.trimEnd().endsWith("Validating query...")) {
192+
return prev;
193+
}
194+
return prev + `\nValidating query...\n`;
195+
});
196+
}
197+
break;
198+
case "time_filter":
199+
// Apply time filter immediately when the AI sets it
200+
onTimeFilterChange?.(event.filter);
178201
break;
179202
case "result":
180203
if (event.success) {
204+
// Apply time filter if included in result (backup in case time_filter event was missed)
205+
if (event.timeFilter) {
206+
onTimeFilterChange?.(event.timeFilter);
207+
}
181208
onQueryGenerated(event.query);
182209
setPrompt("");
183210
setLastResult("success");
@@ -189,7 +216,7 @@ export function AIQueryInput({
189216
break;
190217
}
191218
},
192-
[onQueryGenerated]
219+
[onQueryGenerated, onTimeFilterChange]
193220
);
194221

195222
const handleSubmit = useCallback(
@@ -359,10 +386,10 @@ export function AIQueryInput({
359386
{isLoading
360387
? "AI is thinking..."
361388
: lastResult === "success"
362-
? "Query generated"
363-
: lastResult === "error"
364-
? "Generation failed"
365-
: "AI response"}
389+
? "Query generated"
390+
: lastResult === "error"
391+
? "Generation failed"
392+
: "AI response"}
366393
</span>
367394
</div>
368395
{isLoading ? (

0 commit comments

Comments
 (0)