From 03d2c294531577e18951451370fa4572ce82cdd2 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Tue, 15 Jul 2025 21:49:05 +0100 Subject: [PATCH 1/2] Added experimental_devProcessCwdInBuildDir config option Added experimental_devProcessCwdInBuildDir config option to opt-in to new process.cwd behavior when executing tasks in the dev CLI. Currently process.cwd maps to the "root" of your trigger.dev project (the directory that contains your trigger.config.ts file). Setting experimental_devProcessCwdInBuildDir to true changes process.cwd to instead be the temporary build directory inside of the .trigger directory. This makes it so the files added via the additionalFiles extension can be read using the same path in dev and deployed tasks. --- .changeset/beige-horses-juggle.md | 5 + packages/cli-v3/src/dev/devSupervisor.ts | 11 ++ packages/cli-v3/src/dev/taskRunProcessPool.ts | 6 +- .../src/entryPoints/dev-run-controller.ts | 11 +- packages/core/src/v3/config.ts | 8 + pnpm-lock.yaml | 105 ++++++++++++ references/claude-code/.claude-settings.json | 3 + references/claude-code/package.json | 19 +++ references/claude-code/src/trigger/code.ts | 158 ++++++++++++++++++ references/claude-code/trigger.config.ts | 28 ++++ references/claude-code/tsconfig.json | 15 ++ 11 files changed, 365 insertions(+), 4 deletions(-) create mode 100644 .changeset/beige-horses-juggle.md create mode 100644 references/claude-code/.claude-settings.json create mode 100644 references/claude-code/package.json create mode 100644 references/claude-code/src/trigger/code.ts create mode 100644 references/claude-code/trigger.config.ts create mode 100644 references/claude-code/tsconfig.json diff --git a/.changeset/beige-horses-juggle.md b/.changeset/beige-horses-juggle.md new file mode 100644 index 0000000000..9c2f5c40e2 --- /dev/null +++ b/.changeset/beige-horses-juggle.md @@ -0,0 +1,5 @@ +--- +"trigger.dev": patch +--- + +Added experimental_devProcessCwdInBuildDir config option to opt-in to new process.cwd behavior when executing tasks in the dev CLI. Currently process.cwd maps to the "root" of your trigger.dev project (the directory that contains your trigger.config.ts file). Setting experimental_devProcessCwdInBuildDir to true changes process.cwd to instead be the temporary build directory inside of the .trigger directory. diff --git a/packages/cli-v3/src/dev/devSupervisor.ts b/packages/cli-v3/src/dev/devSupervisor.ts index c55b906cc3..e86ea4eb45 100644 --- a/packages/cli-v3/src/dev/devSupervisor.ts +++ b/packages/cli-v3/src/dev/devSupervisor.ts @@ -353,6 +353,16 @@ class DevSupervisor implements WorkerRuntime { continue; } + logger.debug("[DevSupervisor] dequeueRuns. Creating run controller", { + run: message.run.friendlyId, + worker, + config: this.options.config, + }); + + const cwd = this.options.config.experimental_devProcessCwdInBuildDir + ? worker.build.outputPath + : undefined; + //new run runController = new DevRunController({ runFriendlyId: message.run.friendlyId, @@ -360,6 +370,7 @@ class DevSupervisor implements WorkerRuntime { httpClient: this.options.client, logLevel: this.options.args.logLevel, taskRunProcessPool: this.taskRunProcessPool, + cwd, onFinished: () => { logger.debug("[DevSupervisor] Run finished", { runId: message.run.friendlyId }); diff --git a/packages/cli-v3/src/dev/taskRunProcessPool.ts b/packages/cli-v3/src/dev/taskRunProcessPool.ts index d7491bf17d..1d0640e52d 100644 --- a/packages/cli-v3/src/dev/taskRunProcessPool.ts +++ b/packages/cli-v3/src/dev/taskRunProcessPool.ts @@ -47,7 +47,8 @@ export class TaskRunProcessPool { workerManifest: WorkerManifest, serverWorker: ServerBackgroundWorker, machineResources: MachinePresetResources, - env?: Record + env?: Record, + cwd?: string ): Promise<{ taskRunProcess: TaskRunProcess; isReused: boolean }> { const version = serverWorker.version || "unknown"; @@ -97,6 +98,7 @@ export class TaskRunProcessPool { version, availableCount, busyCount, + workerManifest, }); const newProcess = new TaskRunProcess({ @@ -107,7 +109,7 @@ export class TaskRunProcessPool { }, serverWorker, machineResources, - cwd: this.options.cwd, + cwd: cwd ?? this.options.cwd, }).initialize(); // Add to busy processes for this version diff --git a/packages/cli-v3/src/entryPoints/dev-run-controller.ts b/packages/cli-v3/src/entryPoints/dev-run-controller.ts index c52192783e..50d9a61719 100644 --- a/packages/cli-v3/src/entryPoints/dev-run-controller.ts +++ b/packages/cli-v3/src/entryPoints/dev-run-controller.ts @@ -31,6 +31,7 @@ type DevRunControllerOptions = { onSubscribeToRunNotifications: (run: Run, snapshot: Snapshot) => void; onUnsubscribeFromRunNotifications: (run: Run, snapshot: Snapshot) => void; onFinished: () => void; + cwd?: string; }; type Run = { @@ -50,6 +51,7 @@ export class DevRunController { private readonly heartbeatIntervalSeconds: number; private readonly snapshotPoller: IntervalService; private readonly snapshotPollIntervalSeconds: number; + private readonly cwd?: string; private state: | { @@ -77,7 +79,7 @@ export class DevRunController { this.worker = opts.worker; this.heartbeatIntervalSeconds = opts.heartbeatIntervalSeconds || 20; this.snapshotPollIntervalSeconds = 5; - + this.cwd = opts.cwd; this.httpClient = opts.httpClient; this.snapshotPoller = new IntervalService({ @@ -607,6 +609,10 @@ export class DevRunController { this.snapshotPoller.start(); + logger.debug("getProcess", { + build: this.opts.worker.build, + }); + // Get process from pool instead of creating new one const { taskRunProcess, isReused } = await this.opts.taskRunProcessPool.getProcess( this.opts.worker.manifest, @@ -621,7 +627,8 @@ export class DevRunController { TRIGGER_WORKER_MANIFEST_PATH: join(this.opts.worker.build.outputPath, "index.json"), RUN_WORKER_SHOW_LOGS: this.opts.logLevel === "debug" ? "true" : "false", TRIGGER_WORKER_VERSION: this.opts.worker.serverWorker?.version, - } + }, + this.cwd ); this.taskRunProcess = taskRunProcess; diff --git a/packages/core/src/v3/config.ts b/packages/core/src/v3/config.ts index 061b40fc40..838a464dcf 100644 --- a/packages/core/src/v3/config.ts +++ b/packages/core/src/v3/config.ts @@ -259,6 +259,14 @@ export type TriggerConfig = { devMaxPoolSize?: number; }; + /** + * @default false + * @description When running the dev CLI, set the current working directory to the build directory. + * + * Currently, the process.cwd() is set to the root of the project. + */ + experimental_devProcessCwdInBuildDir?: boolean; + /** * @deprecated Use `dirs` instead */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9389ad43ea..bc474f1eb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1863,6 +1863,28 @@ importers: specifier: workspace:* version: link:../../packages/cli-v3 + references/claude-code: + dependencies: + '@anthropic-ai/claude-code': + specifier: ^1.0.31 + version: 1.0.31 + '@trigger.dev/build': + specifier: workspace:* + version: link:../../packages/build + '@trigger.dev/sdk': + specifier: workspace:* + version: link:../../packages/trigger-sdk + ai: + specifier: 4.3.16 + version: 4.3.16(react@18.3.1)(zod@3.23.8) + zod: + specifier: 3.23.8 + version: 3.23.8 + devDependencies: + trigger.dev: + specifier: workspace:* + version: link:../../packages/cli-v3 + references/d3-chat: dependencies: '@ai-sdk/anthropic': @@ -2581,6 +2603,18 @@ packages: zod: 3.23.8 dev: false + /@ai-sdk/provider-utils@2.2.8(zod@3.23.8): + resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.23.8 + dependencies: + '@ai-sdk/provider': 1.1.3 + nanoid: 3.3.8 + secure-json-parse: 2.7.0 + zod: 3.23.8 + dev: false + /@ai-sdk/provider@0.0.22: resolution: {integrity: sha512-smZ1/2jL/JSKnbhC6ama/PxI2D/psj+YAe0c0qpd5ComQCNFltg72VFf0rpUSFMmFuj1pCCNoBOCrvyl8HTZHQ==} engines: {node: '>=18'} @@ -2608,6 +2642,13 @@ packages: dependencies: json-schema: 0.4.0 + /@ai-sdk/provider@1.1.3: + resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} + engines: {node: '>=18'} + dependencies: + json-schema: 0.4.0 + dev: false + /@ai-sdk/react@0.0.53(react@19.0.0-rc.0)(zod@3.23.8): resolution: {integrity: sha512-sIsmTFoR/QHvUUkltmHwP4bPjwy2vko6j/Nj8ayxLhEHs04Ug+dwXQyfA7MwgimEE3BcDQpWL8ikVj0m3ZILWQ==} engines: {node: '>=18'} @@ -2667,6 +2708,24 @@ packages: zod: 3.23.8 dev: false + /@ai-sdk/react@1.2.12(react@18.3.1)(zod@3.23.8): + resolution: {integrity: sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.23.8 + peerDependenciesMeta: + zod: + optional: true + dependencies: + '@ai-sdk/provider-utils': 2.2.8(zod@3.23.8) + '@ai-sdk/ui-utils': 1.2.11(zod@3.23.8) + react: 18.3.1 + swr: 2.2.5(react@18.3.1) + throttleit: 2.1.0 + zod: 3.23.8 + dev: false + /@ai-sdk/react@1.2.2(react@18.3.1)(zod@3.23.8): resolution: {integrity: sha512-rxyNTFjUd3IilVOJFuUJV5ytZBYAIyRi50kFS2gNmSEiG4NHMBBm31ddrxI/i86VpY8gzZVp1/igtljnWBihUA==} engines: {node: '>=18'} @@ -2827,6 +2886,18 @@ packages: zod: 3.23.8 zod-to-json-schema: 3.24.5(zod@3.23.8) + /@ai-sdk/ui-utils@1.2.11(zod@3.23.8): + resolution: {integrity: sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.23.8 + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.23.8) + zod: 3.23.8 + zod-to-json-schema: 3.24.5(zod@3.23.8) + dev: false + /@ai-sdk/vue@0.0.45(vue@3.5.16)(zod@3.23.8): resolution: {integrity: sha512-bqeoWZqk88TQmfoPgnFUKkrvhOIcOcSH5LMPgzZ8XwDqz5tHHrMHzpPfHCj7XyYn4ROTFK/2kKdC/ta6Ko0fMw==} engines: {node: '>=18'} @@ -2881,6 +2952,20 @@ packages: hasBin: true dev: true + /@anthropic-ai/claude-code@1.0.31: + resolution: {integrity: sha512-prn3DEIBm5ALgCjp0sCcXwNbfBR5w98bEOXQbWViow/3BwkTgW784V8i0S/kfIWDVorz0o4cqR5D0fB4hbjNIg==} + engines: {node: '>=18.0.0'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + dev: false + /@arethetypeswrong/cli@0.15.4: resolution: {integrity: sha512-YDbImAi1MGkouT7f2yAECpUMFhhA1J0EaXzIqoC5GGtK0xDgauLtcsZezm8tNq7d3wOFXH7OnY+IORYcG212rw==} engines: {node: '>=18'} @@ -20576,6 +20661,26 @@ packages: zod: 3.23.8 dev: false + /ai@4.3.16(react@18.3.1)(zod@3.23.8): + resolution: {integrity: sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==} + engines: {node: '>=18'} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + zod: ^3.23.8 + peerDependenciesMeta: + react: + optional: true + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@3.23.8) + '@ai-sdk/react': 1.2.12(react@18.3.1)(zod@3.23.8) + '@ai-sdk/ui-utils': 1.2.11(zod@3.23.8) + '@opentelemetry/api': 1.9.0 + jsondiffpatch: 0.6.0 + react: 18.3.1 + zod: 3.23.8 + dev: false + /ajv-formats@2.1.1(ajv@8.17.1): resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: diff --git a/references/claude-code/.claude-settings.json b/references/claude-code/.claude-settings.json new file mode 100644 index 0000000000..67afbd468a --- /dev/null +++ b/references/claude-code/.claude-settings.json @@ -0,0 +1,3 @@ +{ + "model": "claude-3-5-sonnet-20240620" +} \ No newline at end of file diff --git a/references/claude-code/package.json b/references/claude-code/package.json new file mode 100644 index 0000000000..755b4dd48b --- /dev/null +++ b/references/claude-code/package.json @@ -0,0 +1,19 @@ +{ + "name": "references-claude-code", + "private": true, + "type": "module", + "devDependencies": { + "trigger.dev": "workspace:*" + }, + "dependencies": { + "@trigger.dev/build": "workspace:*", + "@trigger.dev/sdk": "workspace:*", + "@anthropic-ai/claude-code": "^1.0.31", + "zod": "3.23.8", + "ai": "4.3.16" + }, + "scripts": { + "dev": "trigger dev", + "deploy": "trigger deploy" + } +} \ No newline at end of file diff --git a/references/claude-code/src/trigger/code.ts b/references/claude-code/src/trigger/code.ts new file mode 100644 index 0000000000..240dd70261 --- /dev/null +++ b/references/claude-code/src/trigger/code.ts @@ -0,0 +1,158 @@ +import { query, type SDKMessage } from "@anthropic-ai/claude-code"; +import { Context, logger, metadata, schemaTask, wait } from "@trigger.dev/sdk"; +import { readFile } from "fs/promises"; +import { tmpdir } from "node:os"; +import { join, resolve } from "path"; +import { z } from "zod"; + +type CHUNK = { iteration: number; message: SDKMessage }; + +export type STREAMS = { + claude: CHUNK; +}; + +export const codeTask = schemaTask({ + id: "claude-code", + schema: z.object({ + prompt: z.string(), + maxTurns: z.number().default(3), + maxIterations: z.number().default(10), + }), + run: async ({ prompt, maxTurns, maxIterations }, { signal, ctx }) => { + const abortController = new AbortController(); + + signal.addEventListener("abort", () => { + abortController.abort(); + }); + + const pathToClaudeCodeExecutable = getPathToClaudeCodeExecutable(ctx); + + const settings = await readFile(join(process.cwd(), ".claude-settings.json")); + + const settingsJson = JSON.parse(settings.toString()); + + logger.log("settings", { settingsJson }); + + // Create a temporary directory for claude-code to work in + const tempDir = tmpdir(); + + logger.log("Starting claude code loop", { pathToClaudeCodeExecutable, cwd: tempDir }); + + let $currentPrompt = prompt; + + let sessionId: string | undefined; + + const { stream, write } = createStream(); + + await metadata.stream("claude", stream); + + for (let i = 0; i < maxIterations; i++) { + logger.info("Starting iteration", { iteration: i, prompt: $currentPrompt, sessionId }); + + const messages: SDKMessage[] = []; + + const result = query({ + prompt: $currentPrompt, + abortController, + options: { + resume: sessionId, + cwd: tempDir, + maxTurns, + pathToClaudeCodeExecutable, + permissionMode: "bypassPermissions", + allowedTools: [ + "Task", + "Bash", + "Glob", + "Grep", + "LS", + "exit_plan_mode", + "Read", + "Edit", + "MultiEdit", + "Write", + "NotebookRead", + "NotebookEdit", + "WebFetch", + "TodoRead", + "TodoWrite", + "WebSearch", + ], + }, + }); + + for await (const message of result) { + if (message.type === "system" && message.subtype === "init") { + sessionId = message.session_id; + } + + messages.push(message); + + write({ iteration: i, message }); + + logger.log("message", { message, iteration: i }); + } + + await saveMessages(messages); + + const continueToken = await wait.createToken({ timeout: "7d" }); + + const nextPrompt = await wait.forToken<{ prompt: string }>(continueToken); + + if (nextPrompt.ok) { + logger.info("Continuing with prompt", { prompt: nextPrompt.output.prompt }); + + $currentPrompt = nextPrompt.output.prompt; + } else { + logger.info("No more prompts", { iteration: i }); + + break; // break out of the loop + } + } + }, +}); + +export function createStream(): { stream: ReadableStream; write: (data: T) => void } { + let controller!: ReadableStreamDefaultController; + + const stream = new ReadableStream({ + start(controllerArg) { + controller = controllerArg; + }, + }); + + function safeEnqueue(data: T) { + try { + controller.enqueue(data); + } catch (error) { + // suppress errors when the stream has been closed + } + } + + return { + stream, + write: safeEnqueue, + }; +} + +async function saveMessages(messages: SDKMessage[]) { + logger.log("Saving messages", { messages }); + // TODO: save messages to a database +} + +function getPathToClaudeCodeExecutable(ctx: Context) { + return ctx.environment.type === "DEVELOPMENT" + ? resolve( + join( + process.cwd(), + "..", + "..", + "..", + "node_modules", + "@anthropic-ai", + "claude-code", + "cli.js" + ) + ) + : join(process.cwd(), "node_modules", "@anthropic-ai", "claude-code", "cli.js"); +} diff --git a/references/claude-code/trigger.config.ts b/references/claude-code/trigger.config.ts new file mode 100644 index 0000000000..b609102344 --- /dev/null +++ b/references/claude-code/trigger.config.ts @@ -0,0 +1,28 @@ +import { defineConfig } from "@trigger.dev/sdk/v3"; +import { additionalFiles } from "@trigger.dev/build/extensions/core"; + +export default defineConfig({ + project: process.env.TRIGGER_PROJECT_REF!, + experimental_processKeepAlive: { + enabled: true, + maxExecutionsPerProcess: 20, + }, + experimental_devProcessCwdInBuildDir: true, + logLevel: "log", + maxDuration: 3600, + retries: { + enabledInDev: true, + default: { + maxAttempts: 3, + minTimeoutInMs: 1000, + maxTimeoutInMs: 10000, + factor: 2, + randomize: true, + }, + }, + machine: "medium-2x", + build: { + external: ["@anthropic-ai/claude-code"], + extensions: [additionalFiles({ files: [".claude-settings.json"] })], + }, +}); diff --git a/references/claude-code/tsconfig.json b/references/claude-code/tsconfig.json new file mode 100644 index 0000000000..9a5ee0b9d6 --- /dev/null +++ b/references/claude-code/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2023", + "module": "Node16", + "moduleResolution": "Node16", + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "customConditions": ["@triggerdotdev/source"], + "jsx": "preserve", + "lib": ["DOM", "DOM.Iterable"], + "noEmit": true + }, + "include": ["./src/**/*.ts", "trigger.config.ts"] +} From 63ab751f70db70c06475e2a5ec4290f698f199ab Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Mon, 21 Jul 2025 14:38:26 +0100 Subject: [PATCH 2/2] =?UTF-8?q?Remove=20claude=20code=20reference=20becaus?= =?UTF-8?q?e=20it=20breaks=20windows=20tests=20=F0=9F=98=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pnpm-lock.yaml | 105 ------------ references/claude-code/.claude-settings.json | 3 - references/claude-code/package.json | 19 --- references/claude-code/src/trigger/code.ts | 158 ------------------- references/claude-code/trigger.config.ts | 28 ---- references/claude-code/tsconfig.json | 15 -- 6 files changed, 328 deletions(-) delete mode 100644 references/claude-code/.claude-settings.json delete mode 100644 references/claude-code/package.json delete mode 100644 references/claude-code/src/trigger/code.ts delete mode 100644 references/claude-code/trigger.config.ts delete mode 100644 references/claude-code/tsconfig.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc474f1eb1..9389ad43ea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1863,28 +1863,6 @@ importers: specifier: workspace:* version: link:../../packages/cli-v3 - references/claude-code: - dependencies: - '@anthropic-ai/claude-code': - specifier: ^1.0.31 - version: 1.0.31 - '@trigger.dev/build': - specifier: workspace:* - version: link:../../packages/build - '@trigger.dev/sdk': - specifier: workspace:* - version: link:../../packages/trigger-sdk - ai: - specifier: 4.3.16 - version: 4.3.16(react@18.3.1)(zod@3.23.8) - zod: - specifier: 3.23.8 - version: 3.23.8 - devDependencies: - trigger.dev: - specifier: workspace:* - version: link:../../packages/cli-v3 - references/d3-chat: dependencies: '@ai-sdk/anthropic': @@ -2603,18 +2581,6 @@ packages: zod: 3.23.8 dev: false - /@ai-sdk/provider-utils@2.2.8(zod@3.23.8): - resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.23.8 - dependencies: - '@ai-sdk/provider': 1.1.3 - nanoid: 3.3.8 - secure-json-parse: 2.7.0 - zod: 3.23.8 - dev: false - /@ai-sdk/provider@0.0.22: resolution: {integrity: sha512-smZ1/2jL/JSKnbhC6ama/PxI2D/psj+YAe0c0qpd5ComQCNFltg72VFf0rpUSFMmFuj1pCCNoBOCrvyl8HTZHQ==} engines: {node: '>=18'} @@ -2642,13 +2608,6 @@ packages: dependencies: json-schema: 0.4.0 - /@ai-sdk/provider@1.1.3: - resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==} - engines: {node: '>=18'} - dependencies: - json-schema: 0.4.0 - dev: false - /@ai-sdk/react@0.0.53(react@19.0.0-rc.0)(zod@3.23.8): resolution: {integrity: sha512-sIsmTFoR/QHvUUkltmHwP4bPjwy2vko6j/Nj8ayxLhEHs04Ug+dwXQyfA7MwgimEE3BcDQpWL8ikVj0m3ZILWQ==} engines: {node: '>=18'} @@ -2708,24 +2667,6 @@ packages: zod: 3.23.8 dev: false - /@ai-sdk/react@1.2.12(react@18.3.1)(zod@3.23.8): - resolution: {integrity: sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g==} - engines: {node: '>=18'} - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - zod: ^3.23.8 - peerDependenciesMeta: - zod: - optional: true - dependencies: - '@ai-sdk/provider-utils': 2.2.8(zod@3.23.8) - '@ai-sdk/ui-utils': 1.2.11(zod@3.23.8) - react: 18.3.1 - swr: 2.2.5(react@18.3.1) - throttleit: 2.1.0 - zod: 3.23.8 - dev: false - /@ai-sdk/react@1.2.2(react@18.3.1)(zod@3.23.8): resolution: {integrity: sha512-rxyNTFjUd3IilVOJFuUJV5ytZBYAIyRi50kFS2gNmSEiG4NHMBBm31ddrxI/i86VpY8gzZVp1/igtljnWBihUA==} engines: {node: '>=18'} @@ -2886,18 +2827,6 @@ packages: zod: 3.23.8 zod-to-json-schema: 3.24.5(zod@3.23.8) - /@ai-sdk/ui-utils@1.2.11(zod@3.23.8): - resolution: {integrity: sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.23.8 - dependencies: - '@ai-sdk/provider': 1.1.3 - '@ai-sdk/provider-utils': 2.2.8(zod@3.23.8) - zod: 3.23.8 - zod-to-json-schema: 3.24.5(zod@3.23.8) - dev: false - /@ai-sdk/vue@0.0.45(vue@3.5.16)(zod@3.23.8): resolution: {integrity: sha512-bqeoWZqk88TQmfoPgnFUKkrvhOIcOcSH5LMPgzZ8XwDqz5tHHrMHzpPfHCj7XyYn4ROTFK/2kKdC/ta6Ko0fMw==} engines: {node: '>=18'} @@ -2952,20 +2881,6 @@ packages: hasBin: true dev: true - /@anthropic-ai/claude-code@1.0.31: - resolution: {integrity: sha512-prn3DEIBm5ALgCjp0sCcXwNbfBR5w98bEOXQbWViow/3BwkTgW784V8i0S/kfIWDVorz0o4cqR5D0fB4hbjNIg==} - engines: {node: '>=18.0.0'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.5 - '@img/sharp-darwin-x64': 0.33.5 - '@img/sharp-linux-arm': 0.33.5 - '@img/sharp-linux-arm64': 0.33.5 - '@img/sharp-linux-x64': 0.33.5 - '@img/sharp-win32-x64': 0.33.5 - dev: false - /@arethetypeswrong/cli@0.15.4: resolution: {integrity: sha512-YDbImAi1MGkouT7f2yAECpUMFhhA1J0EaXzIqoC5GGtK0xDgauLtcsZezm8tNq7d3wOFXH7OnY+IORYcG212rw==} engines: {node: '>=18'} @@ -20661,26 +20576,6 @@ packages: zod: 3.23.8 dev: false - /ai@4.3.16(react@18.3.1)(zod@3.23.8): - resolution: {integrity: sha512-KUDwlThJ5tr2Vw0A1ZkbDKNME3wzWhuVfAOwIvFUzl1TPVDFAXDFTXio3p+jaKneB+dKNCvFFlolYmmgHttG1g==} - engines: {node: '>=18'} - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - zod: ^3.23.8 - peerDependenciesMeta: - react: - optional: true - dependencies: - '@ai-sdk/provider': 1.1.3 - '@ai-sdk/provider-utils': 2.2.8(zod@3.23.8) - '@ai-sdk/react': 1.2.12(react@18.3.1)(zod@3.23.8) - '@ai-sdk/ui-utils': 1.2.11(zod@3.23.8) - '@opentelemetry/api': 1.9.0 - jsondiffpatch: 0.6.0 - react: 18.3.1 - zod: 3.23.8 - dev: false - /ajv-formats@2.1.1(ajv@8.17.1): resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: diff --git a/references/claude-code/.claude-settings.json b/references/claude-code/.claude-settings.json deleted file mode 100644 index 67afbd468a..0000000000 --- a/references/claude-code/.claude-settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "model": "claude-3-5-sonnet-20240620" -} \ No newline at end of file diff --git a/references/claude-code/package.json b/references/claude-code/package.json deleted file mode 100644 index 755b4dd48b..0000000000 --- a/references/claude-code/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "references-claude-code", - "private": true, - "type": "module", - "devDependencies": { - "trigger.dev": "workspace:*" - }, - "dependencies": { - "@trigger.dev/build": "workspace:*", - "@trigger.dev/sdk": "workspace:*", - "@anthropic-ai/claude-code": "^1.0.31", - "zod": "3.23.8", - "ai": "4.3.16" - }, - "scripts": { - "dev": "trigger dev", - "deploy": "trigger deploy" - } -} \ No newline at end of file diff --git a/references/claude-code/src/trigger/code.ts b/references/claude-code/src/trigger/code.ts deleted file mode 100644 index 240dd70261..0000000000 --- a/references/claude-code/src/trigger/code.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { query, type SDKMessage } from "@anthropic-ai/claude-code"; -import { Context, logger, metadata, schemaTask, wait } from "@trigger.dev/sdk"; -import { readFile } from "fs/promises"; -import { tmpdir } from "node:os"; -import { join, resolve } from "path"; -import { z } from "zod"; - -type CHUNK = { iteration: number; message: SDKMessage }; - -export type STREAMS = { - claude: CHUNK; -}; - -export const codeTask = schemaTask({ - id: "claude-code", - schema: z.object({ - prompt: z.string(), - maxTurns: z.number().default(3), - maxIterations: z.number().default(10), - }), - run: async ({ prompt, maxTurns, maxIterations }, { signal, ctx }) => { - const abortController = new AbortController(); - - signal.addEventListener("abort", () => { - abortController.abort(); - }); - - const pathToClaudeCodeExecutable = getPathToClaudeCodeExecutable(ctx); - - const settings = await readFile(join(process.cwd(), ".claude-settings.json")); - - const settingsJson = JSON.parse(settings.toString()); - - logger.log("settings", { settingsJson }); - - // Create a temporary directory for claude-code to work in - const tempDir = tmpdir(); - - logger.log("Starting claude code loop", { pathToClaudeCodeExecutable, cwd: tempDir }); - - let $currentPrompt = prompt; - - let sessionId: string | undefined; - - const { stream, write } = createStream(); - - await metadata.stream("claude", stream); - - for (let i = 0; i < maxIterations; i++) { - logger.info("Starting iteration", { iteration: i, prompt: $currentPrompt, sessionId }); - - const messages: SDKMessage[] = []; - - const result = query({ - prompt: $currentPrompt, - abortController, - options: { - resume: sessionId, - cwd: tempDir, - maxTurns, - pathToClaudeCodeExecutable, - permissionMode: "bypassPermissions", - allowedTools: [ - "Task", - "Bash", - "Glob", - "Grep", - "LS", - "exit_plan_mode", - "Read", - "Edit", - "MultiEdit", - "Write", - "NotebookRead", - "NotebookEdit", - "WebFetch", - "TodoRead", - "TodoWrite", - "WebSearch", - ], - }, - }); - - for await (const message of result) { - if (message.type === "system" && message.subtype === "init") { - sessionId = message.session_id; - } - - messages.push(message); - - write({ iteration: i, message }); - - logger.log("message", { message, iteration: i }); - } - - await saveMessages(messages); - - const continueToken = await wait.createToken({ timeout: "7d" }); - - const nextPrompt = await wait.forToken<{ prompt: string }>(continueToken); - - if (nextPrompt.ok) { - logger.info("Continuing with prompt", { prompt: nextPrompt.output.prompt }); - - $currentPrompt = nextPrompt.output.prompt; - } else { - logger.info("No more prompts", { iteration: i }); - - break; // break out of the loop - } - } - }, -}); - -export function createStream(): { stream: ReadableStream; write: (data: T) => void } { - let controller!: ReadableStreamDefaultController; - - const stream = new ReadableStream({ - start(controllerArg) { - controller = controllerArg; - }, - }); - - function safeEnqueue(data: T) { - try { - controller.enqueue(data); - } catch (error) { - // suppress errors when the stream has been closed - } - } - - return { - stream, - write: safeEnqueue, - }; -} - -async function saveMessages(messages: SDKMessage[]) { - logger.log("Saving messages", { messages }); - // TODO: save messages to a database -} - -function getPathToClaudeCodeExecutable(ctx: Context) { - return ctx.environment.type === "DEVELOPMENT" - ? resolve( - join( - process.cwd(), - "..", - "..", - "..", - "node_modules", - "@anthropic-ai", - "claude-code", - "cli.js" - ) - ) - : join(process.cwd(), "node_modules", "@anthropic-ai", "claude-code", "cli.js"); -} diff --git a/references/claude-code/trigger.config.ts b/references/claude-code/trigger.config.ts deleted file mode 100644 index b609102344..0000000000 --- a/references/claude-code/trigger.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { defineConfig } from "@trigger.dev/sdk/v3"; -import { additionalFiles } from "@trigger.dev/build/extensions/core"; - -export default defineConfig({ - project: process.env.TRIGGER_PROJECT_REF!, - experimental_processKeepAlive: { - enabled: true, - maxExecutionsPerProcess: 20, - }, - experimental_devProcessCwdInBuildDir: true, - logLevel: "log", - maxDuration: 3600, - retries: { - enabledInDev: true, - default: { - maxAttempts: 3, - minTimeoutInMs: 1000, - maxTimeoutInMs: 10000, - factor: 2, - randomize: true, - }, - }, - machine: "medium-2x", - build: { - external: ["@anthropic-ai/claude-code"], - extensions: [additionalFiles({ files: [".claude-settings.json"] })], - }, -}); diff --git a/references/claude-code/tsconfig.json b/references/claude-code/tsconfig.json deleted file mode 100644 index 9a5ee0b9d6..0000000000 --- a/references/claude-code/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2023", - "module": "Node16", - "moduleResolution": "Node16", - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "customConditions": ["@triggerdotdev/source"], - "jsx": "preserve", - "lib": ["DOM", "DOM.Iterable"], - "noEmit": true - }, - "include": ["./src/**/*.ts", "trigger.config.ts"] -}