diff --git a/apps/docs/src/content/docs/ecosystem/channels/stripe.md b/apps/docs/src/content/docs/ecosystem/channels/stripe.md index 23b9d3167..72a1fe5bf 100644 --- a/apps/docs/src/content/docs/ecosystem/channels/stripe.md +++ b/apps/docs/src/content/docs/ecosystem/channels/stripe.md @@ -165,9 +165,10 @@ export function retrieveCustomer(customerId: string) { async run() { const customer = await client.customers.retrieve(customerId); return { - output: 'deleted' in customer - ? { id: customer.id, deleted: true } - : { id: customer.id, name: customer.name, email: customer.email }, + output: + 'deleted' in customer + ? { id: customer.id, deleted: true } + : { id: customer.id, name: customer.name, email: customer.email }, }; }, }); diff --git a/apps/docs/src/content/docs/ecosystem/sandboxes/cloudflare-computer.md b/apps/docs/src/content/docs/ecosystem/sandboxes/cloudflare-computer.md index 2d14c6c6d..b30a2dd94 100644 --- a/apps/docs/src/content/docs/ecosystem/sandboxes/cloudflare-computer.md +++ b/apps/docs/src/content/docs/ecosystem/sandboxes/cloudflare-computer.md @@ -22,8 +22,8 @@ The blueprint creates the adapter at `/sandboxes/cloudflare-compute ```jsonc title="wrangler.jsonc" { - "compatibility_flags": ["nodejs_compat", "experimental"], - "worker_loaders": [{ "binding": "LOADER" }] + "compatibility_flags": ["nodejs_compat", "experimental"], + "worker_loaders": [{ "binding": "LOADER" }], } ``` @@ -39,27 +39,27 @@ import { extend, getDurableObjectIdentity } from '@flue/runtime/cloudflare'; /** Re-export from each agent module: `export { workspaceHost as cloudflare } ...` */ export const workspaceHost = extend({ - base: (Base) => - class extends Base { - /* ... captures the Durable Object state; exposes the workspace stub ... */ - }, + base: (Base) => + class extends Base { + /* ... captures the Durable Object state; exposes the workspace stub ... */ + }, }); /** One durable Workspace per agent instance, shared with the sandbox. */ export function getComputerWorkspace(options: GetComputerWorkspaceOptions): Workspace { - /* ... memoized construction: DO storage + git client + WorkerShellBackend ... */ + /* ... memoized construction: DO storage + git client + WorkerShellBackend ... */ } export function getComputerSandbox(options: GetComputerWorkspaceOptions): SandboxFactory { - return { - async createSandbox(): Promise { - const workspace = getComputerWorkspace(options); - await workspace.fs.mkdir('/workspace', { recursive: true }); - return { ...createWorkspaceSandbox(workspace, '/workspace'), workspace }; - }, - // No `tools` override: exec() works here, so the framework's standard - // set (bash/grep/glob/read/write/edit) applies as-is. - }; + return { + async createSandbox(): Promise { + const workspace = getComputerWorkspace(options); + await workspace.fs.mkdir('/workspace', { recursive: true }); + return { ...createWorkspaceSandbox(workspace, '/workspace'), workspace }; + }, + // No `tools` override: exec() works here, so the framework's standard + // set (bash/grep/glob/read/write/edit) applies as-is. + }; } ``` @@ -74,9 +74,9 @@ import { getComputerSandbox } from '../sandboxes/cloudflare-computer'; export { workspaceHost as cloudflare } from '../sandboxes/cloudflare-computer'; export function Assistant() { - useModel('cloudflare/@cf/moonshotai/kimi-k2.6'); - useSandbox(getComputerSandbox({ loader: env.LOADER })); - return 'You explore and edit your durable workspace with the standard file and shell tools.'; + useModel('cloudflare/@cf/moonshotai/kimi-k2.6'); + useSandbox(getComputerSandbox({ loader: env.LOADER })); + return 'You explore and edit your durable workspace with the standard file and shell tools.'; } ``` diff --git a/apps/docs/src/content/docs/reference/sandbox-api.md b/apps/docs/src/content/docs/reference/sandbox-api.md index 88c993752..d90881259 100644 --- a/apps/docs/src/content/docs/reference/sandbox-api.md +++ b/apps/docs/src/content/docs/reference/sandbox-api.md @@ -277,7 +277,10 @@ interface BashLike { ## `SandboxToolFactory` ```ts -type SandboxToolFactory = (sandbox: Sandbox, options: SandboxToolFactoryOptions) => AgentTool[]; +type SandboxToolFactory = ( + sandbox: Sandbox, + options: SandboxToolFactoryOptions, +) => AgentTool[]; interface SandboxToolFactoryOptions { subagents: Record; diff --git a/apps/docs/src/styles/global.css b/apps/docs/src/styles/global.css index cecc5c41e..3b111e4dc 100644 --- a/apps/docs/src/styles/global.css +++ b/apps/docs/src/styles/global.css @@ -259,6 +259,7 @@ overflow-x: auto; border: 1px solid #e2e5eb; border-radius: 0.3rem; + /* biome-ignore lint/complexity/noImportantStyles: Shiki sets the theme background inline. */ background: #f6f8fa !important; box-shadow: 0 1px 1px rgb(0 0 0 / 0.04); font-family: var(--font-mono); diff --git a/apps/www/src/pages/blog/flue-2.mdx b/apps/www/src/pages/blog/flue-2.mdx index 5ffcc2bb2..dc53a56e2 100644 --- a/apps/www/src/pages/blog/flue-2.mdx +++ b/apps/www/src/pages/blog/flue-2.mdx @@ -13,16 +13,16 @@ import CopyPrompt from '../../components/CopyPrompt.astro'; Flue 2.0 is available today. We rebuilt our agent framework around a new hooks-based API, unlocking a new kind of dynamic agent that can evolve its capabilities over time. -**Agent Hooks** are the new foundation in Flue 2.0. Hooks let you build dynamic agents that can manage their own state, listen to agent lifecycle events, and even attach different resources and capabilities dynamically to enhance themselves at runtime. +**Agent Hooks** are the new foundation in Flue 2.0. Hooks let you build dynamic agents that can manage their own state, listen to agent lifecycle events, and even attach different resources and capabilities dynamically to enhance themselves at runtime. Hooks are authored in TypeScript and presented in a familiar API: ```ts export function Assistant() { - const [count, setCount] = usePersistentState('count', 0); - useAgentStart(() => setCount((n) => n + 1)); - useModel('moonshot/kimi-k2'); - return `You are a helpful assistant. This conversation has ${count} messages.`; + const [count, setCount] = usePersistentState('count', 0); + useAgentStart(() => setCount((n) => n + 1)); + useModel('moonshot/kimi-k2'); + return `You are a helpful assistant. This conversation has ${count} messages.`; } ``` @@ -50,29 +50,29 @@ In the original Flue 1.0 API I took the same static approach to agent architectu ```ts // Flue 1.0 API export default defineAgent(() => ({ - model: 'moonshot/kimi-k2', - tools: [replyToIssue], - skills: [triage, verify], - sandbox: local(), - instructions, + model: 'moonshot/kimi-k2', + tools: [replyToIssue], + skills: [triage, verify], + sandbox: local(), + instructions, })); ``` We dogfooded this API with real developers during the Flue 1.0 Beta. What we found was surprising: The static agent approach worked well for simple use-cases, but started to break down for more complex, non-trivial agents and multi-step workflows. -We began to wonder: if Flue 1.0 had this problem, then how many other popular agent frameworks and SDKs had this problem as well? +We began to wonder: if Flue 1.0 had this problem, then how many other popular agent frameworks and SDKs had this problem as well? We decided that this was a problem worth solving, and that the timing was right to make the breaking change to Flue now, while we were still early. We experimented with a bunch of different approaches, but eventually a familiar design pattern started to come into focus: ```ts // Flue 2.0 API export function IssueTriageAgent() { - useModel('moonshot/kimi-k2'); - useTool(replyToIssue); - useSkill(triage); - useSkill(verify); - useSandbox(local()); - return instructions; + useModel('moonshot/kimi-k2'); + useTool(replyToIssue); + useSkill(triage); + useSkill(verify); + useSandbox(local()); + return instructions; } ``` @@ -84,22 +84,22 @@ Let's say you want your agent to be able to upgrade its initial model or sandbox ```ts export function CompanySlackAgent() { - // Attach persistent data to each agent, stored in your DB. - const [isEnhanced, setEnhanced] = usePersistentState("isEnhanced", false); - // Give your agent the ability to upgrade itself. - useTool({ name: "enhance", description: "...", run: () => setEnhanced(true) }); - // Attach new capabilities, on-demand. - if (isEnhanced) { - useModel('anthropic/fable-5-0'); - useSandbox(daytona()); - useTool(/* ... */); - useSkill(/* ... */); - useSubagent(/* ... */); - } else { - useModel('moonshot/kimi-k2'); - } - // Return your agent instructions. Flue handles the rest. - return `You are a helpful assistant.`; + // Attach persistent data to each agent, stored in your DB. + const [isEnhanced, setEnhanced] = usePersistentState('isEnhanced', false); + // Give your agent the ability to upgrade itself. + useTool({ name: 'enhance', description: '...', run: () => setEnhanced(true) }); + // Attach new capabilities, on-demand. + if (isEnhanced) { + useModel('anthropic/fable-5-0'); + useSandbox(daytona()); + useTool(/* ... */); + useSkill(/* ... */); + useSubagent(/* ... */); + } else { + useModel('moonshot/kimi-k2'); + } + // Return your agent instructions. Flue handles the rest. + return `You are a helpful assistant.`; } ``` @@ -109,25 +109,25 @@ In Flue 2.0, a workflow is persistent state plus conditional tools. Give each st ```ts export function IssueTriageAgent({ id }) { - useSandbox(local()); - // Persist which step of the workflow the agent is on. - const [step, setStep] = usePersistentState('step', 'reproduce'); - // Each step attaches its own tools and skills. - if (step === 'reproduce') { - useModel('anthropic/sonnet-5-0'); - useSkill(reproChecklist); - useTool({ name: 'submit_repro', description: '...', run: () => setStep('diagnose') }); - } - if (step === 'diagnose') { - useModel('anthropic/fable-5-0'); - useSkill(debuggingGuide); - useTool({ name: 'submit_diagnosis', description: '...', run: () => setStep('report') }); - } - if (step === 'report') { - useModel('anthropic/sonnet-5-0'); - useTool(postGitHubComment); - } - return `Follow the workflow to triage GitHub issue ${id}: reproduce -> diagnose -> report.`; + useSandbox(local()); + // Persist which step of the workflow the agent is on. + const [step, setStep] = usePersistentState('step', 'reproduce'); + // Each step attaches its own tools and skills. + if (step === 'reproduce') { + useModel('anthropic/sonnet-5-0'); + useSkill(reproChecklist); + useTool({ name: 'submit_repro', description: '...', run: () => setStep('diagnose') }); + } + if (step === 'diagnose') { + useModel('anthropic/fable-5-0'); + useSkill(debuggingGuide); + useTool({ name: 'submit_diagnosis', description: '...', run: () => setStep('report') }); + } + if (step === 'report') { + useModel('anthropic/sonnet-5-0'); + useTool(postGitHubComment); + } + return `Follow the workflow to triage GitHub issue ${id}: reproduce -> diagnose -> report.`; } ``` @@ -137,18 +137,18 @@ And just like React hooks, they compose together nicely. You can build your own ```ts export function useLinear(apiKey) { - useMcpConnection({ - name: 'linear', - url: 'https://mcp.linear.app/mcp', - auth: apiKey, - }); + useMcpConnection({ + name: 'linear', + url: 'https://mcp.linear.app/mcp', + auth: apiKey, + }); } export function ProjectAssistant() { - useLinear(process.env.LINEAR_API_KEY); - useGitHub(process.env.GITHUB_API_KEY); - useBrowser(); - return 'Help your team manage their work.'; + useLinear(process.env.LINEAR_API_KEY); + useGitHub(process.env.GITHUB_API_KEY); + useBrowser(); + return 'Help your team manage their work.'; } ``` diff --git a/biome.jsonc b/biome.jsonc index acc54b5ec..8042af97f 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.5.4/schema.json", + "$schema": "https://biomejs.dev/schemas/2.5.6/schema.json", "assist": { "actions": { "source": { "organizeImports": "on" } } }, "css": { "parser": { diff --git a/examples/cloudflare/README.md b/examples/cloudflare/README.md index 458afb731..10cd2262b 100644 --- a/examples/cloudflare/README.md +++ b/examples/cloudflare/README.md @@ -13,11 +13,11 @@ mounts each agent's routes explicitly. ## Agents -| Agent | Demonstrates | -| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| `with-cloudflare-binding.ts` | Routing model traffic through the Workers AI binding (no API keys). | +| Agent | Demonstrates | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `with-cloudflare-binding.ts` | Routing model traffic through the Workers AI binding (no API keys). | | `skills-from-r2.ts` | Hydrating a cloudflare-computer `Workspace` from an R2 bucket and using a discovered skill (via a model-callable `check_spam` action). | -| `skills-from-git.ts` | Hydrating a cloudflare-computer `Workspace` from a git repo via the built-in `workspace.git` client. | +| `skills-from-git.ts` | Hydrating a cloudflare-computer `Workspace` from a git repo via the built-in `workspace.git` client. | ## Setup diff --git a/examples/discord-channel/package.json b/examples/discord-channel/package.json index fa7f92e60..603e91273 100644 --- a/examples/discord-channel/package.json +++ b/examples/discord-channel/package.json @@ -17,7 +17,6 @@ "valibot": "^1.0.0" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "typescript": "^7.0.2", diff --git a/examples/github-channel/package.json b/examples/github-channel/package.json index bd69fbebf..b1c80ba0f 100644 --- a/examples/github-channel/package.json +++ b/examples/github-channel/package.json @@ -15,7 +15,6 @@ "valibot": "^1.0.0" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "typescript": "^7.0.2", diff --git a/examples/google-chat-channel/package.json b/examples/google-chat-channel/package.json index 1f3a2e24f..bd538957c 100644 --- a/examples/google-chat-channel/package.json +++ b/examples/google-chat-channel/package.json @@ -17,7 +17,6 @@ "valibot": "^1.0.0" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "typescript": "^7.0.2", diff --git a/examples/hello-world/src/sandboxes/daytona.ts b/examples/hello-world/src/sandboxes/daytona.ts index 0743040d8..3b2e48ea5 100644 --- a/examples/hello-world/src/sandboxes/daytona.ts +++ b/examples/hello-world/src/sandboxes/daytona.ts @@ -29,8 +29,8 @@ */ import type { Sandbox as DaytonaSandbox } from '@daytona/sdk'; -import type { FileStat, SandboxDriver, SandboxFactory, Sandbox } from '@flue/runtime'; -import { sandboxFromDriver, SandboxOperationUnsupportedError } from '@flue/runtime'; +import type { FileStat, Sandbox, SandboxDriver, SandboxFactory } from '@flue/runtime'; +import { SandboxOperationUnsupportedError, sandboxFromDriver } from '@flue/runtime'; // ─── DaytonaSandboxDriver ────────────────────────────────────────────────────── diff --git a/examples/intercom-channel/package.json b/examples/intercom-channel/package.json index dc4dab9f1..9f0959d28 100644 --- a/examples/intercom-channel/package.json +++ b/examples/intercom-channel/package.json @@ -17,7 +17,6 @@ }, "devDependencies": { "@cloudflare/vite-plugin": "^1.39.2", - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "@types/node": "^26.1.1", diff --git a/examples/linear-channel/package.json b/examples/linear-channel/package.json index 0d8f0ffd3..90d1d6577 100644 --- a/examples/linear-channel/package.json +++ b/examples/linear-channel/package.json @@ -15,7 +15,6 @@ "valibot": "^1.0.0" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "typescript": "^7.0.2", diff --git a/examples/messenger-channel/package.json b/examples/messenger-channel/package.json index e52dfab9c..702fd1ea2 100644 --- a/examples/messenger-channel/package.json +++ b/examples/messenger-channel/package.json @@ -16,7 +16,6 @@ "valibot": "^1.0.0" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "typescript": "^7.0.2", diff --git a/examples/notion-channel/package.json b/examples/notion-channel/package.json index a5b565c3d..eeda6ceb2 100644 --- a/examples/notion-channel/package.json +++ b/examples/notion-channel/package.json @@ -17,7 +17,6 @@ }, "devDependencies": { "@cloudflare/vite-plugin": "^1.39.2", - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "@types/node": "^26.1.1", diff --git a/examples/resend-channel/package.json b/examples/resend-channel/package.json index 5581ca85f..2ff5015fb 100644 --- a/examples/resend-channel/package.json +++ b/examples/resend-channel/package.json @@ -16,7 +16,6 @@ }, "devDependencies": { "@cloudflare/vite-plugin": "^1.39.2", - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "@types/node": "^26.1.1", diff --git a/examples/salesforce-marketing-cloud-channel/package.json b/examples/salesforce-marketing-cloud-channel/package.json index 75b7045c4..0e97d1ade 100644 --- a/examples/salesforce-marketing-cloud-channel/package.json +++ b/examples/salesforce-marketing-cloud-channel/package.json @@ -15,7 +15,6 @@ }, "devDependencies": { "@cloudflare/vite-plugin": "^1.39.2", - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/cli": "workspace:*", "@flue/vite": "workspace:*", "@types/node": "^26.1.1", diff --git a/examples/salesforce-marketing-cloud-channel/src/salesforce-marketing-cloud-client.ts b/examples/salesforce-marketing-cloud-channel/src/salesforce-marketing-cloud-client.ts index c4141146e..72c417da0 100644 --- a/examples/salesforce-marketing-cloud-channel/src/salesforce-marketing-cloud-client.ts +++ b/examples/salesforce-marketing-cloud-channel/src/salesforce-marketing-cloud-client.ts @@ -64,7 +64,7 @@ export function createSalesforceMarketingCloudClient({ }; } -export function salesforceMarketingCloudRestOrigin(restBaseUrl: string): string { +function salesforceMarketingCloudRestOrigin(restBaseUrl: string): string { let url: URL; try { url = new URL(restBaseUrl); diff --git a/examples/sentry/src/sentry.ts b/examples/sentry/src/sentry.ts index aa393ab5a..c86101635 100644 --- a/examples/sentry/src/sentry.ts +++ b/examples/sentry/src/sentry.ts @@ -149,7 +149,9 @@ instrument({ // terminal outcome, 'terminated', always co-occurs with a `submission_settled` // outcome:'failed' event that the branch above already captures; recording it // here too would duplicate that issue. -function recordRecoveryBreadcrumb(event: Extract): void { +function recordRecoveryBreadcrumb( + event: Extract, +): void { Sentry.addBreadcrumb({ category: 'flue.submission_recovery', level: event.outcome === 'terminated' ? 'error' : 'warning', @@ -158,8 +160,12 @@ function recordRecoveryBreadcrumb(event: Extract; forceCloseSync(): void; exitCode: number; @@ -15,7 +15,7 @@ export interface BoundedShutdownOptions { terminate?: (code: number) => unknown; } -export async function boundedShutdown(options: BoundedShutdownOptions): Promise { +async function boundedShutdown(options: BoundedShutdownOptions): Promise { process.exitCode = options.exitCode; let timer: NodeJS.Timeout | undefined; let timedOut = false; diff --git a/packages/discord/package.json b/packages/discord/package.json index d7ea02fb3..b64cd8f24 100644 --- a/packages/discord/package.json +++ b/packages/discord/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/github/package.json b/packages/github/package.json index 990ac951d..7730515b3 100644 --- a/packages/github/package.json +++ b/packages/github/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/google-chat/package.json b/packages/google-chat/package.json index b1e660e93..8b8b69947 100644 --- a/packages/google-chat/package.json +++ b/packages/google-chat/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/intercom/package.json b/packages/intercom/package.json index e10719305..a01ce0204 100644 --- a/packages/intercom/package.json +++ b/packages/intercom/package.json @@ -36,7 +36,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/linear/package.json b/packages/linear/package.json index 8e0c2284b..237065b40 100644 --- a/packages/linear/package.json +++ b/packages/linear/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/messenger/package.json b/packages/messenger/package.json index 42bc5a313..e997999cb 100644 --- a/packages/messenger/package.json +++ b/packages/messenger/package.json @@ -36,7 +36,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/mongodb/src/mongodb-adapter.ts b/packages/mongodb/src/mongodb-adapter.ts index e8b894092..de26f3d5b 100644 --- a/packages/mongodb/src/mongodb-adapter.ts +++ b/packages/mongodb/src/mongodb-adapter.ts @@ -69,7 +69,7 @@ export function mongodb(runner: MongoRunner, options: MongoOptions = {}): Persis { $set: { leaseExpiresAt: Date.now() + MIGRATION_LEASE_MS } }, ) .catch(() => null); - if (!result || result.matchedCount !== 1) lockLost = true; + if (result?.matchedCount !== 1) lockLost = true; }); }, MIGRATION_LEASE_MS / 3); try { diff --git a/packages/notion/package.json b/packages/notion/package.json index 14e0872e6..c177255e0 100644 --- a/packages/notion/package.json +++ b/packages/notion/package.json @@ -38,7 +38,6 @@ "@types/node": ">=18" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "@notionhq/client": "5.23.3", "@types/node": "^26.1.1", diff --git a/packages/redis/src/redis-adapter.ts b/packages/redis/src/redis-adapter.ts index 5ea1bba6f..989ac6f4a 100644 --- a/packages/redis/src/redis-adapter.ts +++ b/packages/redis/src/redis-adapter.ts @@ -20,8 +20,8 @@ import { isSubmissionPayload, LEASE_DURATION_MS, matchesPersistedSubmissionAttachments, - parseAcceptedAt, PersistedFormatVersionError, + parseAcceptedAt, prepareSubmissionAttachments, SUBMISSION_HARNESS_NAME, SUBMISSION_SESSION_NAME, diff --git a/packages/resend/package.json b/packages/resend/package.json index f40e0059f..7ecf4782f 100644 --- a/packages/resend/package.json +++ b/packages/resend/package.json @@ -39,7 +39,6 @@ "resend": "^6.17.2" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "@types/node": "^26.1.1", "resend": "6.18.1", diff --git a/packages/runtime/src/abort.ts b/packages/runtime/src/abort.ts index f06ead3dd..ee340fc14 100644 --- a/packages/runtime/src/abort.ts +++ b/packages/runtime/src/abort.ts @@ -42,7 +42,7 @@ export function composeTimeoutSignal( } /** Appended to the abort error when the abandoned work may still be running. */ -export const ABANDONED_TOOL_SUFFIX = +const ABANDONED_TOOL_SUFFIX = ' The tool execution could not be confirmed cancelled and may still be running.'; /** diff --git a/packages/runtime/src/client.ts b/packages/runtime/src/client.ts index 973ed2c00..cb3a6fa55 100644 --- a/packages/runtime/src/client.ts +++ b/packages/runtime/src/client.ts @@ -592,7 +592,7 @@ async function resolveSandbox( '[flue] SandboxFactory.createSessionEnv is deprecated; rename the method to createSandbox.', ); } - const env = await create!.call(sandbox, { id }); + const env = await (create as SandboxFactory['createSandbox']).call(sandbox, { id }); return { env, toolFactory: sandbox.tools }; } throw new Error('[flue] Invalid sandbox option composed by the agent function.'); diff --git a/packages/runtime/src/cloudflare/agent-coordinator.ts b/packages/runtime/src/cloudflare/agent-coordinator.ts index cbb7e60e1..82acba452 100644 --- a/packages/runtime/src/cloudflare/agent-coordinator.ts +++ b/packages/runtime/src/cloudflare/agent-coordinator.ts @@ -869,9 +869,7 @@ class CloudflareAgentCoordinator { // Abort intent wins over timeout, mirroring the settle-order in // reconcileInterruptedSubmission. AbortController.abort is idempotent, // so re-signaling on every pass is safe. - controller.abort( - abortRequested ? new SubmissionAbortedError() : new SubmissionTimeoutError(), - ); + controller.abort(abortRequested ? new SubmissionAbortedError() : new SubmissionTimeoutError()); // The grace is anchored to when the fiber was first SIGNALED, not to // the deadline itself: a delayed first pass (late alarms) must not // abort and force-settle in the same breath. Abort intents were @@ -894,9 +892,7 @@ class CloudflareAgentCoordinator { attemptCount: submission.attemptCount, maxAttempts: submission.maxAttempts, error: serializeSubmissionError( - abortRequested - ? new SubmissionAbortedError() - : new SubmissionTimeoutError(), + abortRequested ? new SubmissionAbortedError() : new SubmissionTimeoutError(), ), }); return false; diff --git a/packages/runtime/src/cloudflare/worker-config.ts b/packages/runtime/src/cloudflare/worker-config.ts index efc08a76b..11a4f55a8 100644 --- a/packages/runtime/src/cloudflare/worker-config.ts +++ b/packages/runtime/src/cloudflare/worker-config.ts @@ -121,7 +121,7 @@ export function createCloudflareWorkerConfig( ); } const info = (await response.json()) as { exists?: unknown; uid?: unknown } | null; - if (!info || info.exists !== true) return null; + if (info?.exists !== true) return null; return { id: instanceId, ...(typeof info.uid === 'string' ? { uid: info.uid } : {}) }; }; @@ -161,7 +161,8 @@ function dispatchAdmissionError(input: DispatchInput, status: number, rejection: // The wire body's submissionId names the existing keyed submission; // the dispatch input derived the same id, so it is the fallback. return new SubmissionConflictError({ - submissionId: typeof body.submissionId === 'string' ? body.submissionId : input.submissionId, + submissionId: + typeof body.submissionId === 'string' ? body.submissionId : input.submissionId, }); case 'invalid_request': return new InvalidRequestError({ diff --git a/packages/runtime/src/cloudflare/workers-ai-provider.ts b/packages/runtime/src/cloudflare/workers-ai-provider.ts index 54ed50b12..4291261d0 100644 --- a/packages/runtime/src/cloudflare/workers-ai-provider.ts +++ b/packages/runtime/src/cloudflare/workers-ai-provider.ts @@ -869,9 +869,7 @@ function streamCloudflareResponsesAi( observeResponsesEvents( iterateSseChunks(withStreamIdleDeadline(response.body, binding.streamIdleTimeoutMs)), observed, - ) as Parameters< - typeof processResponsesStream - >[0], + ) as Parameters[0], output, stream, responsesModel, diff --git a/packages/runtime/src/conversation-fold-checkpoint.ts b/packages/runtime/src/conversation-fold-checkpoint.ts index 4aa2ce628..13f9250db 100644 --- a/packages/runtime/src/conversation-fold-checkpoint.ts +++ b/packages/runtime/src/conversation-fold-checkpoint.ts @@ -46,7 +46,7 @@ export const FOLD_CHECKPOINT_INTERVAL = 64; type EncodedEntries = Array<[string, unknown]>; /** Serialize a reduced state to the checkpoint's canonical JSON `data`. */ -export function encodeReducedInstanceState(state: ReducedInstanceState): string { +function encodeReducedInstanceState(state: ReducedInstanceState): string { return JSON.stringify({ ...state, conversationScopes: [...state.conversationScopes], @@ -85,7 +85,7 @@ export function encodeReducedInstanceState(state: ReducedInstanceState): string * Rebuild a reduced state from checkpoint `data`. Throws on any structural * mismatch — callers treat every throw as "no checkpoint". */ -export function decodeReducedInstanceState(data: string): ReducedInstanceState { +function decodeReducedInstanceState(data: string): ReducedInstanceState { const parsed = JSON.parse(data) as Record; const state = { ...parsed, diff --git a/packages/runtime/src/conversation-public.ts b/packages/runtime/src/conversation-public.ts index e4c7e40cb..3230cd359 100644 --- a/packages/runtime/src/conversation-public.ts +++ b/packages/runtime/src/conversation-public.ts @@ -164,7 +164,8 @@ export interface ConversationStreamCheckpointChunk { } /** Everything the `updates` wire can carry: projected chunks plus wire-only markers. */ -export type ConversationStreamWireChunk = ConversationStreamChunk | ConversationStreamCheckpointChunk; +export type ConversationStreamWireChunk = + ConversationStreamChunk | ConversationStreamCheckpointChunk; // The public conversation API addresses exactly one conversation per agent // instance: the default harness/session root. An instance can hold other root diff --git a/packages/runtime/src/conversation-records.ts b/packages/runtime/src/conversation-records.ts index 21ff7a518..d49c89ab3 100644 --- a/packages/runtime/src/conversation-records.ts +++ b/packages/runtime/src/conversation-records.ts @@ -336,7 +336,7 @@ export interface SubmissionSettledRecord extends ConversationRecordEnvelope { * append batch as their batch's `tool_results_committed` record, so a state * write shares the durability of the tool batch that made it. */ -export interface StateWriteRecord extends ConversationRecordEnvelope { +interface StateWriteRecord extends ConversationRecordEnvelope { type: 'state_write'; name: string; value: unknown; diff --git a/packages/runtime/src/conversation-reducer.ts b/packages/runtime/src/conversation-reducer.ts index 53822714a..fe6644952 100644 --- a/packages/runtime/src/conversation-reducer.ts +++ b/packages/runtime/src/conversation-reducer.ts @@ -439,7 +439,7 @@ function cloneReducedInstanceState(state: ReducedInstanceState): ReducedInstance }; } -export function applyConversationRecord( +function applyConversationRecord( state: ReducedInstanceState, record: ConversationRecord, ): void { @@ -1151,7 +1151,7 @@ function pathToContextEntries( let index = 0; while (index < path.length) { const entry = path[index]; - if (!entry || entry.type !== 'message') { + if (entry?.type !== 'message') { index += 1; continue; } diff --git a/packages/runtime/src/harness.ts b/packages/runtime/src/harness.ts index c4631e0ba..9d9a94426 100644 --- a/packages/runtime/src/harness.ts +++ b/packages/runtime/src/harness.ts @@ -14,9 +14,9 @@ import { createCwdSandbox } from './sandbox.ts'; import { type CreateTaskSessionOptions, createPublicSession, - Session, type SandboxRuntime, type SandboxSlot, + Session, type SessionRerender, type SessionResourceRuntime, } from './session.ts'; diff --git a/packages/runtime/src/hooks/render.ts b/packages/runtime/src/hooks/render.ts index 32353f277..3e0606f02 100644 --- a/packages/runtime/src/hooks/render.ts +++ b/packages/runtime/src/hooks/render.ts @@ -32,21 +32,6 @@ function agentPropsFor(state: RenderStateContext | undefined): AgentProps { return props as AgentProps; } -/** - * Run one render of an agent function: invoke it inside a fresh frame, - * validate the returned instruction, and map the hook attachments onto the - * internal runtime-config shape the initialization path consumes. The whole - * config is hook-composed — `useModel` declares the model and its tuning, - * `useSandbox` the environment; hooks validated each value when it was - * declared. - */ -export function renderAgentFunction( - agent: AgentFunction, - state?: RenderStateContext, -): AgentRuntimeConfig { - return renderAgentFunctionWithStructure(agent, state).config; -} - /** * The structural fingerprint of one render. Message data (by name) feeds the * invariance guard — it must be identical across renders, because the parts @@ -77,7 +62,7 @@ export interface AgentRenderStructure { resources: ResourceSnapshot; } -/** `renderAgentFunction` plus the render's structural fingerprint. */ +/** Run one agent render and return its config plus structural fingerprint. */ export function renderAgentFunctionWithStructure( agent: AgentFunction, state?: RenderStateContext, diff --git a/packages/runtime/src/mcp.ts b/packages/runtime/src/mcp.ts index 1c8c768d1..5e7b86f0a 100644 --- a/packages/runtime/src/mcp.ts +++ b/packages/runtime/src/mcp.ts @@ -117,7 +117,7 @@ export async function createMcpConnection( ); } -export async function createMcpConnectionWithClient( +async function createMcpConnectionWithClient( name: string, client: McpClient, transport: Transport, diff --git a/packages/runtime/src/node/agent-coordinator.ts b/packages/runtime/src/node/agent-coordinator.ts index 93dcb439e..2b905111c 100644 --- a/packages/runtime/src/node/agent-coordinator.ts +++ b/packages/runtime/src/node/agent-coordinator.ts @@ -33,10 +33,7 @@ import { import type { AttachmentStore } from '../runtime/attachment-store.ts'; import type { ConversationStreamStore } from '../runtime/conversation-stream-store.ts'; import type { DispatchInput, DispatchQueue } from '../runtime/dispatch-queue.ts'; -import { - type CoordinatorEventEmitter, - createCoordinatorEventEmitter, -} from '../runtime/events.ts'; +import { type CoordinatorEventEmitter, createCoordinatorEventEmitter } from '../runtime/events.ts'; import type { CreateAgentContextFn } from '../runtime/handle-agent.ts'; import { generateAttemptId, generateOwnerId, isKeyDerivedSubmissionId } from '../runtime/ids.ts'; import type { RuntimeActivityGate } from '../runtime/runtime-activity-gate.ts'; @@ -54,9 +51,7 @@ export interface NodeAgentCoordinator { * when a keyed admission converged on the submission its key already * names instead of admitting a new one. */ - admitDispatch( - input: DispatchInput, - ): Promise< + admitDispatch(input: DispatchInput): Promise< | { readonly kind: 'submission'; readonly submission: AgentSubmission; @@ -162,10 +157,7 @@ export function createNodeAgentCoordinator(options: { // and infallible by contract. const passEventEmitter = createCoordinatorEventEmitter({ env: coordinatorEnv }); const instanceEventEmitters = new Map(); - function coordinatorEventEmitter(input?: { - agent: string; - id: string; - }): CoordinatorEventEmitter { + function coordinatorEventEmitter(input?: { agent: string; id: string }): CoordinatorEventEmitter { if (!input) return passEventEmitter; const key = agentStreamPath(input.agent, input.id); let emitter = instanceEventEmitters.get(key); diff --git a/packages/runtime/src/persisted-images.ts b/packages/runtime/src/persisted-images.ts index 70b1ffb71..99be2592e 100644 --- a/packages/runtime/src/persisted-images.ts +++ b/packages/runtime/src/persisted-images.ts @@ -2,8 +2,7 @@ import type { AgentSubmissionInput } from './runtime/agent-submissions.ts'; import { MAX_IMAGE_DATA_LENGTH } from './runtime/schemas.ts'; import type { PromptImage } from './types.ts'; -export { MAX_IMAGE_DATA_LENGTH }; -export const IMAGE_DATA_CHUNK_LENGTH = 256 * 1024; +const IMAGE_DATA_CHUNK_LENGTH = 256 * 1024; const markerPrefix = '__flue_submission_chunks__:'; diff --git a/packages/runtime/src/provider-diagnostics.ts b/packages/runtime/src/provider-diagnostics.ts index 6532fcb90..03738671b 100644 --- a/packages/runtime/src/provider-diagnostics.ts +++ b/packages/runtime/src/provider-diagnostics.ts @@ -31,7 +31,7 @@ import type { AssistantMessage, AssistantMessageDiagnostic } from '@earendil-works/pi-ai'; /** Diagnostic `type` under which providers attach response metadata. */ -export const PROVIDER_RESPONSE_DIAGNOSTIC = 'flue:provider_response'; +const PROVIDER_RESPONSE_DIAGNOSTIC = 'flue:provider_response'; /** * Allowlisted provider-response metadata projected onto `turn` observations. diff --git a/packages/runtime/src/runtime/agent-submissions.ts b/packages/runtime/src/runtime/agent-submissions.ts index 80d1b8e50..af84a1733 100644 --- a/packages/runtime/src/runtime/agent-submissions.ts +++ b/packages/runtime/src/runtime/agent-submissions.ts @@ -718,11 +718,7 @@ export async function settleUnclaimableSubmission( error: unknown, emitCoordinatorEvent: CoordinatorEventEmitter, ): Promise { - const settled = await submissions.settleQueuedSubmission( - submission.submissionId, - outcome, - error, - ); + const settled = await submissions.settleQueuedSubmission(submission.submissionId, outcome, error); if (!settled) return false; const errorInfo = { errorInfo: classifyError(error) }; emitCoordinatorEvent( diff --git a/packages/runtime/src/runtime/conversation-observer.ts b/packages/runtime/src/runtime/conversation-observer.ts index 3b98c38ef..8833c6821 100644 --- a/packages/runtime/src/runtime/conversation-observer.ts +++ b/packages/runtime/src/runtime/conversation-observer.ts @@ -14,13 +14,13 @@ * CLI's `flue run` and the programmatic agent client. */ +import { getConversationFoldHost } from '../conversation-fold-host.ts'; import { type AgentConversationSnapshot, type ConversationStreamChunk, projectAgentConversationBatch, projectAgentConversationSnapshot, } from '../conversation-public.ts'; -import { getConversationFoldHost } from '../conversation-fold-host.ts'; import { loadReducedConversationPrefix } from '../conversation-reader.ts'; import { reduceConversationRecords } from '../conversation-reducer.ts'; import type { diff --git a/packages/runtime/src/runtime/conversation-stream-store.ts b/packages/runtime/src/runtime/conversation-stream-store.ts index e78146357..b269fb2a9 100644 --- a/packages/runtime/src/runtime/conversation-stream-store.ts +++ b/packages/runtime/src/runtime/conversation-stream-store.ts @@ -154,7 +154,7 @@ CREATE TABLE IF NOT EXISTS flue_conversation_stream_batch_chunks ( * `flue_conversation_stream_batch_chunks` instead of the batch row's `data` * column: Cloudflare Durable Object SQLite caps an individual value at ~2MB. */ -export const CONVERSATION_BATCH_SPILL_THRESHOLD = 1024 * 1024; +const CONVERSATION_BATCH_SPILL_THRESHOLD = 1024 * 1024; /** Code units per spilled chunk row; every cell stays far under the value cap. */ const BATCH_CHUNK_LENGTH = 512 * 1024; diff --git a/packages/runtime/src/runtime/events.ts b/packages/runtime/src/runtime/events.ts index cfaebaf88..365c2ca4d 100644 --- a/packages/runtime/src/runtime/events.ts +++ b/packages/runtime/src/runtime/events.ts @@ -73,9 +73,7 @@ export function dispatchGlobalEvent( const observation = createObservation(event, detail); for (const subscriber of [...subscribers]) { try { - const delivery = Promise.resolve(subscriber(observation, ctx)).catch( - reportSubscriberFailure, - ); + const delivery = Promise.resolve(subscriber(observation, ctx)).catch(reportSubscriberFailure); inFlightDeliveries.add(delivery); void delivery.finally(() => inFlightDeliveries.delete(delivery)); } catch (error) { diff --git a/packages/runtime/src/runtime/flue-app.ts b/packages/runtime/src/runtime/flue-app.ts index 34c288f39..92a7e183a 100644 --- a/packages/runtime/src/runtime/flue-app.ts +++ b/packages/runtime/src/runtime/flue-app.ts @@ -149,7 +149,7 @@ export async function getAgentInstance( * the instance's stream, so existence and uid come from stream meta plus the * first batch. */ -export async function readInstanceInfoFromStream( +async function readInstanceInfoFromStream( store: ConversationStreamStore, agentName: string, instanceId: string, diff --git a/packages/runtime/src/runtime/handle-conversation-routes.ts b/packages/runtime/src/runtime/handle-conversation-routes.ts index a3c9f6a96..ff3361b20 100644 --- a/packages/runtime/src/runtime/handle-conversation-routes.ts +++ b/packages/runtime/src/runtime/handle-conversation-routes.ts @@ -1,8 +1,8 @@ +import { getConversationFoldHost } from '../conversation-fold-host.ts'; import { type ConversationStreamCheckpointChunk, projectAgentConversationSnapshot, } from '../conversation-public.ts'; -import { getConversationFoldHost } from '../conversation-fold-host.ts'; import { loadReducedConversationPrefix } from '../conversation-reader.ts'; import type { ReducedInstanceState } from '../conversation-reducer.ts'; import { diff --git a/packages/runtime/src/runtime/ids.ts b/packages/runtime/src/runtime/ids.ts index bd04aaad5..dde7406b4 100644 --- a/packages/runtime/src/runtime/ids.ts +++ b/packages/runtime/src/runtime/ids.ts @@ -1,6 +1,6 @@ import { ulid } from 'ulidx'; -export function generateSessionAffinityKey(): string { +function generateSessionAffinityKey(): string { return `aff_${ulid()}`; } diff --git a/packages/runtime/src/session.ts b/packages/runtime/src/session.ts index 8305c8568..171489c88 100644 --- a/packages/runtime/src/session.ts +++ b/packages/runtime/src/session.ts @@ -2308,7 +2308,7 @@ export class Session implements FlueSession, AgentSubmissionSession { ]); } else if (assistant && aEvent.type === 'text_delta') { const block = assistant.blocks.get(aEvent.contentIndex); - if (!block || block.type !== 'text') + if (block?.type !== 'text') throw new Error('[flue] Canonical text delta has no started block.'); this.enqueueCanonical( [ @@ -2325,7 +2325,7 @@ export class Session implements FlueSession, AgentSubmissionSession { ); } else if (assistant && aEvent.type === 'text_end') { const block = assistant.blocks.get(aEvent.contentIndex); - if (!block || block.type !== 'text') + if (block?.type !== 'text') throw new Error('[flue] Canonical text completion has no started block.'); const content = aEvent.partial.content[aEvent.contentIndex]; await this.flushCanonical(); @@ -2362,7 +2362,7 @@ export class Session implements FlueSession, AgentSubmissionSession { this.emit({ type: 'thinking_start', contentIndex: aEvent.contentIndex }); } else if (assistant && aEvent.type === 'thinking_delta') { const block = assistant.blocks.get(aEvent.contentIndex); - if (!block || block.type !== 'reasoning') + if (block?.type !== 'reasoning') throw new Error('[flue] Canonical reasoning delta has no started block.'); this.enqueueCanonical( [ @@ -2384,7 +2384,7 @@ export class Session implements FlueSession, AgentSubmissionSession { ); } else if (assistant && aEvent.type === 'thinking_end') { const block = assistant.blocks.get(aEvent.contentIndex); - if (!block || block.type !== 'reasoning') + if (block?.type !== 'reasoning') throw new Error('[flue] Canonical reasoning completion has no started block.'); const content = aEvent.partial.content[aEvent.contentIndex]; await this.flushCanonical(); @@ -4922,7 +4922,7 @@ export class Session implements FlueSession, AgentSubmissionSession { return false; } const firstKeptEntry = contextEntries[preparation.firstKeptIndex]?.sourceEntry; - if (!firstKeptEntry || firstKeptEntry.type !== 'message') { + if (firstKeptEntry?.type !== 'message') { this.internalLog( 'info', '[flue:compaction] Nothing to compact (first kept message has no entry)', diff --git a/packages/runtime/src/sql-agent-execution-store.ts b/packages/runtime/src/sql-agent-execution-store.ts index f4869f1cb..1eac71d14 100644 --- a/packages/runtime/src/sql-agent-execution-store.ts +++ b/packages/runtime/src/sql-agent-execution-store.ts @@ -37,13 +37,13 @@ import type { SqlStorage } from './sql-storage.ts'; type SqlRow = Record; +import { migrateFlueSqlSchema } from './format-version.ts'; import { hydratePersistedSubmissionAttachments } from './persisted-image-placement.ts'; import { type AgentSubmissionInput, createDispatchAgentSubmissionInput, } from './runtime/agent-submissions.ts'; import type { DispatchInput } from './runtime/dispatch-queue.ts'; -import { migrateFlueSqlSchema } from './format-version.ts'; import { createSqlSubmissionChunkStore, ensureSqlSubmissionChunkTable, diff --git a/packages/runtime/src/sql-attachment-store.ts b/packages/runtime/src/sql-attachment-store.ts index aedfc3282..c92d70faa 100644 --- a/packages/runtime/src/sql-attachment-store.ts +++ b/packages/runtime/src/sql-attachment-store.ts @@ -1,4 +1,5 @@ import { AttachmentConflictError, AttachmentIntegrityError } from './errors.ts'; +import { migrateFlueSqlSchema } from './format-version.ts'; import { type AttachmentStore, attachmentBytesEqual, @@ -9,7 +10,6 @@ import { sameAttachmentRef, verifyAttachmentBytes, } from './runtime/attachment-store.ts'; -import { migrateFlueSqlSchema } from './format-version.ts'; import type { SqlStorage } from './sql-storage.ts'; export const ATTACHMENT_CHUNK_BYTE_LENGTH = 512 * 1024; diff --git a/packages/runtime/src/telemetry/projection.ts b/packages/runtime/src/telemetry/projection.ts index ab191e08d..5085c8022 100644 --- a/packages/runtime/src/telemetry/projection.ts +++ b/packages/runtime/src/telemetry/projection.ts @@ -57,7 +57,7 @@ export function agentOutputMessage( | { type: 'data'; data: unknown } | undefined, ): GenAIContent | undefined { - if (!output || output.type !== 'text') return undefined; + if (output?.type !== 'text') return undefined; return [ { role: 'assistant', diff --git a/packages/runtime/src/telemetry/truncate.ts b/packages/runtime/src/telemetry/truncate.ts index 4396b74b9..879da5719 100644 --- a/packages/runtime/src/telemetry/truncate.ts +++ b/packages/runtime/src/telemetry/truncate.ts @@ -27,7 +27,7 @@ export function truncateContent(content: unknown, options: { maxBytes: number }) if (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < MIN_BUDGET_BYTES) { throw new TypeError(`maxBytes must be a safe integer of at least ${MIN_BUDGET_BYTES}.`); } - return fit(content, options.maxBytes); + return fitContent(content, options.maxBytes); } /** Serialized UTF-8 byte length, or undefined when JSON can't represent it. */ @@ -42,7 +42,7 @@ function measure(value: unknown): number | undefined { return ENCODER.encode(serialized).byteLength; } -function fit(value: unknown, budget: number): unknown { +function fitContent(value: unknown, budget: number): unknown { const size = measure(value); if (size === undefined) return CONTENT_UNSERIALIZABLE; if (size <= budget) return value; @@ -109,11 +109,11 @@ function truncateArray(value: unknown[], budget: number): unknown { droppedCount > 0 ? sentinelItem(messageShaped, droppedCount, droppedBytes) : undefined; const overhead = (sentinel ? (measure(sentinel) ?? 0) + 1 : 0) + 4; // Shrink the last element only when a workable slice of the budget is left - // beside the sentinel, and re-measure the result: nested fit() calls bottom + // beside the sentinel, and re-measure the result: nested fitContent() calls bottom // out in fixed-size markers that can overshoot a tight budget. const innerBudget = budget - overhead; if (innerBudget >= MIN_LEAF_BYTES) { - const shrunk = fit(items[0], innerBudget); + const shrunk = fitContent(items[0], innerBudget); const candidate = sentinel ? [sentinel, shrunk] : [shrunk]; const size = measure(candidate); if (size !== undefined && size <= budget) return candidate; diff --git a/packages/runtime/src/tool.ts b/packages/runtime/src/tool.ts index c122299c2..4d7418c14 100644 --- a/packages/runtime/src/tool.ts +++ b/packages/runtime/src/tool.ts @@ -276,22 +276,6 @@ function validateToolOutput( } } -export async function validateAndRunTool( - tool: TTool, - data?: unknown, - signal?: AbortSignal, -): Promise> { - if (tool.harness) { - throw new Error( - `[flue] Tool "${tool.name}" declares \`harness: true\` and can only run inside an agent session — a standalone run has no harness.`, - ); - } - const parsed = parseToolInput(tool, data, signal); - // `terminate` is a turn-loop concern; a standalone run has no turn to end, - // so only the resolved output survives here. - return resolveToolRun(tool, await tool.run(parsed.context)).output; -} - function assertNonEmptyString(value: unknown, label: string): asserts value is string { if (typeof value !== 'string' || value.trim().length === 0) { throw new Error(`[flue] ${label} must be a non-empty string.`); diff --git a/packages/salesforce-marketing-cloud/package.json b/packages/salesforce-marketing-cloud/package.json index ab42c470f..134f4315b 100644 --- a/packages/salesforce-marketing-cloud/package.json +++ b/packages/salesforce-marketing-cloud/package.json @@ -36,7 +36,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/sdk/src/public/conversation-stream.ts b/packages/sdk/src/public/conversation-stream.ts index e62b39dfe..44744b99d 100644 --- a/packages/sdk/src/public/conversation-stream.ts +++ b/packages/sdk/src/public/conversation-stream.ts @@ -152,7 +152,7 @@ export type ConversationStreamChunk = * current state (an unknown chunk shape). `observe()` recovers by rehydrating a * fresh snapshot. */ -export class ConversationStreamError extends Error { +class ConversationStreamError extends Error { constructor(message: string) { super(message); this.name = 'ConversationStreamError'; diff --git a/packages/sdk/src/public/send.ts b/packages/sdk/src/public/send.ts index a11b5139e..2c6d52d0b 100644 --- a/packages/sdk/src/public/send.ts +++ b/packages/sdk/src/public/send.ts @@ -101,9 +101,7 @@ export async function sendConversationMessage( const siblings = { ...(options.initialData !== undefined ? { initialData: options.initialData } : {}), ...(options.uid !== undefined ? { uid: options.uid } : {}), - ...(options.idempotencyKey !== undefined - ? { idempotencyKey: options.idempotencyKey } - : {}), + ...(options.idempotencyKey !== undefined ? { idempotencyKey: options.idempotencyKey } : {}), }; return http.json({ method: 'POST', diff --git a/packages/shopify/package.json b/packages/shopify/package.json index dec4fbab7..5c3350ff5 100644 --- a/packages/shopify/package.json +++ b/packages/shopify/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/slack/package.json b/packages/slack/package.json index e7efaa294..d1bd4b927 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/stripe/package.json b/packages/stripe/package.json index c898a6aa1..ac1d9fafe 100644 --- a/packages/stripe/package.json +++ b/packages/stripe/package.json @@ -38,7 +38,6 @@ "stripe": "^22.3.2" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "@types/node": "^26.1.1", "stripe": "22.4.0", diff --git a/packages/teams/package.json b/packages/teams/package.json index f0718197f..ef05b2a03 100644 --- a/packages/teams/package.json +++ b/packages/teams/package.json @@ -38,7 +38,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/telegram/package.json b/packages/telegram/package.json index 9f6d9883d..b9aa34c65 100644 --- a/packages/telegram/package.json +++ b/packages/telegram/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/twilio/package.json b/packages/twilio/package.json index ad39f3b18..e0d157441 100644 --- a/packages/twilio/package.json +++ b/packages/twilio/package.json @@ -36,7 +36,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "twilio": "6.0.2", diff --git a/packages/vite/package.json b/packages/vite/package.json index f63d328a3..1cc9d38ef 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -46,7 +46,6 @@ "vite": "^8.0.0" }, "devDependencies": { - "@cloudflare/vite-plugin": "^1.39.2", "@earendil-works/pi-ai": "^0.83.0", "hono": "4.12.32", "tsdown": "^0.22.7", diff --git a/packages/vite/src/agent-scan.ts b/packages/vite/src/agent-scan.ts index 0253521ba..43a28672a 100644 --- a/packages/vite/src/agent-scan.ts +++ b/packages/vite/src/agent-scan.ts @@ -98,7 +98,7 @@ class AgentScanError extends Error { } /** Two or more scanned agents resolve to the same identity. */ -export class DuplicateAgentIdentityError extends AgentScanError { +class DuplicateAgentIdentityError extends AgentScanError { readonly duplicates: ReadonlyArray<{ readonly identity: string; readonly filePaths: readonly string[]; @@ -121,7 +121,7 @@ export class DuplicateAgentIdentityError extends AgentScanError { } /** Two distinct agent identities fold to the same generated durable identifier. */ -export class AgentIdentifierCollisionError extends AgentScanError { +class AgentIdentifierCollisionError extends AgentScanError { readonly collisions: ReadonlyArray<{ /** The colliding generated name (a DO class or binding name). */ readonly identifier: string; @@ -153,7 +153,7 @@ export class AgentIdentifierCollisionError extends AgentScanError { } /** The same local function is exported under two different agent names. */ -export class DuplicateAgentExportError extends AgentScanError { +class DuplicateAgentExportError extends AgentScanError { readonly filePath: string; readonly functionName: string; readonly exportNames: readonly string[]; @@ -172,7 +172,7 @@ export class DuplicateAgentExportError extends AgentScanError { } /** A scanned agent's identity (function name or `agentName` override) is invalid. */ -export class InvalidAgentIdentityError extends AgentScanError { +class InvalidAgentIdentityError extends AgentScanError { readonly invalidAgents: ReadonlyArray<{ readonly identity: string; readonly filePath: string; @@ -193,7 +193,7 @@ export class InvalidAgentIdentityError extends AgentScanError { } /** An agent's `agentName` static is assigned in a form the build cannot read statically. */ -export class InvalidAgentNameStaticError extends AgentScanError { +class InvalidAgentNameStaticError extends AgentScanError { readonly filePath: string; constructor(filePath: string, agentName: string, position: { line: number; column: number }) { @@ -208,7 +208,7 @@ export class InvalidAgentNameStaticError extends AgentScanError { } /** A `'use agent'` module default-exports an anonymous function. */ -export class AnonymousAgentExportError extends AgentScanError { +class AnonymousAgentExportError extends AgentScanError { readonly filePath: string; constructor(filePath: string, position: { line: number; column: number }) { @@ -222,7 +222,7 @@ export class AnonymousAgentExportError extends AgentScanError { } /** A `'use agent'` module exports no agents (no capitalized exported functions). */ -export class NoAgentExportsError extends AgentScanError { +class NoAgentExportsError extends AgentScanError { readonly filePath: string; constructor(filePath: string) { @@ -236,7 +236,7 @@ export class NoAgentExportsError extends AgentScanError { } /** A `'use agent'` candidate module could not be parsed. */ -export class AgentModuleParseError extends AgentScanError { +class AgentModuleParseError extends AgentScanError { readonly filePath: string; constructor(filePath: string, cause: unknown) { @@ -308,12 +308,12 @@ export function isAgentModulePath(filePath: string): boolean { } /** `FlueAgent` — matches the Cloudflare codegen exactly. */ -export function agentClassName(identity: string): string { +function agentClassName(identity: string): string { return `Flue${pascalCaseName(identity)}Agent`; } /** `FLUE__AGENT` — camel boundaries split, so `IssueTriage` → `FLUE_ISSUE_TRIAGE_AGENT`. */ -export function agentBindingName(identity: string): string { +function agentBindingName(identity: string): string { return `FLUE_${snakeUpperName(identity)}_AGENT`; } diff --git a/packages/vite/src/index.ts b/packages/vite/src/index.ts index 606c37aff..f869f8a98 100644 --- a/packages/vite/src/index.ts +++ b/packages/vite/src/index.ts @@ -17,6 +17,10 @@ * package's own tests. A tooling-facing scan API can ship on purpose later. */ export type { AgentScanResult } from './agent-scan.ts'; +export type { FlueWorkerConfigCustomizer } from './cloudflare-worker-config.ts'; +export { flueWorkerConfig } from './cloudflare-worker-config.ts'; +export type { FlueResolvedProjectInfo, FlueVitePluginApi } from './flue-plugin.ts'; +export { flue } from './flue-plugin.ts'; export type { FlueNodeActivityLease, FlueNodeServer, @@ -24,7 +28,3 @@ export type { LoadFlueNodeApplicationOptions, StartFlueNodeServerOptions, } from './types.ts'; -export type { FlueWorkerConfigCustomizer } from './cloudflare-worker-config.ts'; -export { flueWorkerConfig } from './cloudflare-worker-config.ts'; -export type { FlueResolvedProjectInfo, FlueVitePluginApi } from './flue-plugin.ts'; -export { flue } from './flue-plugin.ts'; diff --git a/packages/whatsapp/package.json b/packages/whatsapp/package.json index af784d9f7..71dcc5f10 100644 --- a/packages/whatsapp/package.json +++ b/packages/whatsapp/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/packages/zendesk/package.json b/packages/zendesk/package.json index f32dd9dff..047fe8eb6 100644 --- a/packages/zendesk/package.json +++ b/packages/zendesk/package.json @@ -37,7 +37,6 @@ "@flue/runtime": "workspace:^" }, "devDependencies": { - "@cloudflare/vitest-pool-workers": "0.19.1", "@flue/runtime": "workspace:*", "tsdown": "^0.22.7", "typescript": "^7.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b1961d87..c6e6675b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -329,9 +329,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -366,9 +363,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -403,9 +397,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -499,9 +490,6 @@ importers: '@cloudflare/vite-plugin': specifier: ^1.39.2 version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -539,9 +527,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -573,9 +558,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -635,9 +617,6 @@ importers: '@cloudflare/vite-plugin': specifier: ^1.39.2 version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -727,9 +706,6 @@ importers: '@cloudflare/vite-plugin': specifier: ^1.39.2 version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -767,9 +743,6 @@ importers: '@cloudflare/vite-plugin': specifier: ^1.39.2 version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -838,9 +811,6 @@ importers: '@cloudflare/vite-plugin': specifier: ^1.39.2 version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -878,9 +848,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -912,9 +879,6 @@ importers: specifier: '*' version: 22.4.0(@types/node@26.1.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -971,9 +935,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -1008,9 +969,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -1042,9 +1000,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -1113,9 +1068,6 @@ importers: specifier: ^1.0.0 version: 1.4.2(typescript@7.0.2) devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -1153,9 +1105,6 @@ importers: '@cloudflare/vite-plugin': specifier: ^1.39.2 version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/cli': specifier: workspace:* version: link:../../packages/cli @@ -1233,9 +1182,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1258,9 +1204,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1283,9 +1226,6 @@ importers: specifier: 6.2.5 version: 6.2.5 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1305,9 +1245,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1349,9 +1286,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1371,9 +1305,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1434,9 +1365,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1566,9 +1494,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1643,9 +1568,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1687,9 +1609,6 @@ importers: specifier: 4.3.0 version: 4.3.0 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1712,9 +1631,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1734,9 +1650,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1768,9 +1681,6 @@ importers: specifier: 6.2.5 version: 6.2.5 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1793,9 +1703,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1815,9 +1722,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1855,9 +1759,6 @@ importers: specifier: ^2.4.1 version: 2.4.1 devDependencies: - '@cloudflare/vite-plugin': - specifier: ^1.39.2 - version: 1.49.0(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))(wrangler@4.116.0(@cloudflare/workers-types@5.20260731.1)) '@earendil-works/pi-ai': specifier: ^0.83.0 version: 0.83.0(@modelcontextprotocol/sdk@1.30.0(@cfworker/json-schema@4.1.1)(zod@4.4.3))(ws@8.21.1)(zod@4.4.3) @@ -1886,9 +1787,6 @@ importers: specifier: 4.12.32 version: 4.12.32 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -1911,9 +1809,6 @@ importers: specifier: 4.3.0 version: 4.3.0 devDependencies: - '@cloudflare/vitest-pool-workers': - specifier: 0.19.1 - version: 0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0))) '@flue/runtime': specifier: workspace:* version: link:../runtime @@ -2522,15 +2417,8 @@ packages: vite: ^6.1.0 || ^7.0.0 || ^8.0.0 wrangler: ^4.116.0 - '@cloudflare/vitest-pool-workers@0.19.1': - resolution: {integrity: sha512-YzAJGOZNap12xefPgc7y74v2C1VcabPqn254wPjfgsleizy9Jj2nrvDjFnUAxoNzyiBi8p4ya8qDjA/fLOpqlQ==} - peerDependencies: - '@vitest/runner': ^4.1.0 - '@vitest/snapshot': ^4.1.0 - vitest: ^4.1.0 - '@cloudflare/workerd-darwin-64@1.20260730.1': - resolution: {integrity: sha512-+MBHmPaiTe2KajryW0T24rZvWFxb41hD3d8anNzQqHzft6vSEb18+sp0znSwxgij7ApPhSM1+vhkNg4f3YMguA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260730.1.tgz} + resolution: {integrity: sha512-+MBHmPaiTe2KajryW0T24rZvWFxb41hD3d8anNzQqHzft6vSEb18+sp0znSwxgij7ApPhSM1+vhkNg4f3YMguA==} engines: {node: '>=16'} cpu: [x64] os: [darwin] @@ -2542,19 +2430,19 @@ packages: os: [darwin] '@cloudflare/workerd-linux-64@1.20260730.1': - resolution: {integrity: sha512-ouyPOSMbiKPeSwUJUvxtMcxGAXs2J4aPE4T5ABIYX5ClcQx5j5bbHTmnqOQEY8sAuLTPjH7dY+iB6UI5ISlwwA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260730.1.tgz} + resolution: {integrity: sha512-ouyPOSMbiKPeSwUJUvxtMcxGAXs2J4aPE4T5ABIYX5ClcQx5j5bbHTmnqOQEY8sAuLTPjH7dY+iB6UI5ISlwwA==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20260730.1': - resolution: {integrity: sha512-YQ+Mi78U3TPdgBPtwq+Sm6rJU+Ihl2y0pjYtuuKkdmUbYzL7oLR6Xqq9wljhasnuCFICssDJaqhMep5WizYoEQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260730.1.tgz} + resolution: {integrity: sha512-YQ+Mi78U3TPdgBPtwq+Sm6rJU+Ihl2y0pjYtuuKkdmUbYzL7oLR6Xqq9wljhasnuCFICssDJaqhMep5WizYoEQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-windows-64@1.20260730.1': - resolution: {integrity: sha512-27fAN+vUECW1oYVc1KOcHYpkL8COM2Uxtxql7TL595kxbjoqS5yckw7NLz7bTf2pALFCZWjqXDjZGJ/xbG4ZKQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260730.1.tgz} + resolution: {integrity: sha512-27fAN+vUECW1oYVc1KOcHYpkL8COM2Uxtxql7TL595kxbjoqS5yckw7NLz7bTf2pALFCZWjqXDjZGJ/xbG4ZKQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -6226,9 +6114,6 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} - cjs-module-lexer@1.2.3: - resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} - cjs-module-lexer@2.2.0: resolution: {integrity: sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==} @@ -10144,21 +10029,6 @@ snapshots: - bufferutil - utf-8-validate - '@cloudflare/vitest-pool-workers@0.19.1(@cloudflare/workers-types@5.20260731.1)(@vitest/runner@4.1.10)(@vitest/snapshot@4.1.10)(vitest@4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)))': - dependencies: - '@vitest/runner': 4.1.10 - '@vitest/snapshot': 4.1.10 - cjs-module-lexer: 1.2.3 - esbuild: 0.28.1 - miniflare: 4.20260730.0 - vitest: 4.1.10(@opentelemetry/api@1.9.1)(@types/node@26.1.2)(happy-dom@20.11.1)(vite@8.1.5(@types/node@26.1.2)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1)(yaml@2.9.0)) - wrangler: 4.116.0(@cloudflare/workers-types@5.20260731.1) - zod: 3.25.76 - transitivePeerDependencies: - - '@cloudflare/workers-types' - - bufferutil - - utf-8-validate - '@cloudflare/workerd-darwin-64@1.20260730.1': optional: true @@ -13652,8 +13522,6 @@ snapshots: dependencies: consola: 3.4.2 - cjs-module-lexer@1.2.3: {} - cjs-module-lexer@2.2.0: {} class-variance-authority@0.7.1: diff --git a/turbo.jsonc b/turbo.jsonc index 942b8513e..67534301d 100644 --- a/turbo.jsonc +++ b/turbo.jsonc @@ -2,6 +2,8 @@ "$schema": "https://turbo.build/schema.json", "globalEnv": [ "ANTHROPIC_API_KEY", + "FREDKBOT_GITHUB_TOKEN", + "GITHUB_REPOSITORY", "GITHUB_TOKEN", "GITHUB_WEBHOOK_SECRET", "ASTRO_REPO",