diff --git a/src/modules/dashboard/__tests__/dashboard.stats.test.tsx b/src/modules/dashboard/__tests__/stats.test.tsx similarity index 97% rename from src/modules/dashboard/__tests__/dashboard.stats.test.tsx rename to src/modules/dashboard/__tests__/stats.test.tsx index db393e6..6342d4e 100644 --- a/src/modules/dashboard/__tests__/dashboard.stats.test.tsx +++ b/src/modules/dashboard/__tests__/stats.test.tsx @@ -1,7 +1,7 @@ import '@testing-library/jest-dom'; import { describe, it, expect } from 'vitest'; import { render, screen } from '@testing-library/react'; -import DashboardStatCard from '../components/dashboard.stats'; +import DashboardStatCard from '../components/stats'; describe('DashboardStatCard Component Tests', () => { diff --git a/src/modules/dashboard/components/dashbaord.barchart.tsx b/src/modules/dashboard/components/bar-chart.tsx similarity index 97% rename from src/modules/dashboard/components/dashbaord.barchart.tsx rename to src/modules/dashboard/components/bar-chart.tsx index 983ed29..5dfd42d 100644 --- a/src/modules/dashboard/components/dashbaord.barchart.tsx +++ b/src/modules/dashboard/components/bar-chart.tsx @@ -1,6 +1,3 @@ -"use client" - -import { TrendingUp } from "lucide-react" import { Bar, BarChart, CartesianGrid, XAxis } from "recharts" import { diff --git a/src/modules/dashboard/components/dashboard.date.picker.tsx b/src/modules/dashboard/components/date-picker.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.date.picker.tsx rename to src/modules/dashboard/components/date-picker.tsx diff --git a/src/modules/dashboard/components/dashbaord.device.tsx b/src/modules/dashboard/components/device-breakdown.tsx similarity index 100% rename from src/modules/dashboard/components/dashbaord.device.tsx rename to src/modules/dashboard/components/device-breakdown.tsx diff --git a/src/modules/dashboard/components/dashboard.header.tsx b/src/modules/dashboard/components/header.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.header.tsx rename to src/modules/dashboard/components/header.tsx diff --git a/src/modules/dashboard/components/dashboard.layout.tsx b/src/modules/dashboard/components/layout.tsx similarity index 90% rename from src/modules/dashboard/components/dashboard.layout.tsx rename to src/modules/dashboard/components/layout.tsx index 1941d53..26c028e 100644 --- a/src/modules/dashboard/components/dashboard.layout.tsx +++ b/src/modules/dashboard/components/layout.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { cn } from "@/lib/utils"; -import { DashboardHeader } from './dashboard.header'; -import DashboardSidebar from './dashboard.sidebar'; +import { DashboardHeader } from './header'; +import DashboardSidebar from './sidebar'; export function DashboardLayout({ children }: { children: React.ReactNode }) { const [isSidebarOpen, setIsSidebarOpen] = useState(false); diff --git a/src/modules/dashboard/components/dashboard.page.tsx b/src/modules/dashboard/components/page.tsx similarity index 87% rename from src/modules/dashboard/components/dashboard.page.tsx rename to src/modules/dashboard/components/page.tsx index 2315f6e..69b0fd3 100644 --- a/src/modules/dashboard/components/dashboard.page.tsx +++ b/src/modules/dashboard/components/page.tsx @@ -3,18 +3,18 @@ import { type DateRange } from "react-day-picker"; import { PageHeader } from "@/components/ui/page-header"; import ErrorAlert from "@/components/ui/error-alert"; -import DashboardSiteSelector from "./dashboard.site.selector"; -import { DashboardDateRangePicker } from "./dashboard.date.picker"; -import DashboardStatsGrid from "./dashboard.stats.grid"; -import { PageviewsCard } from "./dashboard.pageviews"; -import TrafficMap from "./dashboard.traffic.map"; +import DashboardSiteSelector from "./site-selector"; +import { DashboardDateRangePicker } from "./date-picker"; +import DashboardStatsGrid from "./stats-grid"; +import { PageviewsCard } from "./pageviews-chart"; +import TrafficMap from "./traffic-map"; -import type { DashboardPageProps } from "../dashboard.types"; import { useAction } from "@/hooks/use-action"; import { actions } from "astro:actions"; -import { DashboardReferrerList } from "./dashboard.referrer.list"; -import { DevicesCard } from "./dashbaord.device"; -import { TrafficTrendsChart } from "./dashbaord.barchart"; +import { DashboardReferrerList } from "./referrer-list"; +import { DevicesCard } from "./device-breakdown"; +import { TrafficTrendsChart } from "./bar-chart"; +import type { DashboardPageProps } from "../dashboard.types"; export function DashboardPage({ sites, diff --git a/src/modules/dashboard/components/dashboard.pageviews.tsx b/src/modules/dashboard/components/pageviews-chart.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.pageviews.tsx rename to src/modules/dashboard/components/pageviews-chart.tsx diff --git a/src/modules/dashboard/components/dashboard.referrer.list.tsx b/src/modules/dashboard/components/referrer-list.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.referrer.list.tsx rename to src/modules/dashboard/components/referrer-list.tsx diff --git a/src/modules/dashboard/components/dashboard.sidebar.tsx b/src/modules/dashboard/components/sidebar.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.sidebar.tsx rename to src/modules/dashboard/components/sidebar.tsx diff --git a/src/modules/dashboard/components/dashboard.site.selector.tsx b/src/modules/dashboard/components/site-selector.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.site.selector.tsx rename to src/modules/dashboard/components/site-selector.tsx diff --git a/src/modules/dashboard/components/dashboard.stats.grid.tsx b/src/modules/dashboard/components/stats-grid.tsx similarity index 92% rename from src/modules/dashboard/components/dashboard.stats.grid.tsx rename to src/modules/dashboard/components/stats-grid.tsx index d84f214..92dabc8 100644 --- a/src/modules/dashboard/components/dashboard.stats.grid.tsx +++ b/src/modules/dashboard/components/stats-grid.tsx @@ -1,5 +1,5 @@ import type { DashboardStatItem } from "../dashboard.types"; -import DashboardStatCard from "./dashboard.stats"; +import DashboardStatCard from "./stats"; export default function DashboardStatsGrid({ stats }: { stats: DashboardStatItem[] | undefined}) { return ( diff --git a/src/modules/dashboard/components/dashboard.stats.tsx b/src/modules/dashboard/components/stats.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.stats.tsx rename to src/modules/dashboard/components/stats.tsx diff --git a/src/modules/dashboard/components/dashboard.traffic.map.tsx b/src/modules/dashboard/components/traffic-map.tsx similarity index 100% rename from src/modules/dashboard/components/dashboard.traffic.map.tsx rename to src/modules/dashboard/components/traffic-map.tsx diff --git a/src/modules/dashboard/index.ts b/src/modules/dashboard/index.ts index d95b10f..4131432 100644 --- a/src/modules/dashboard/index.ts +++ b/src/modules/dashboard/index.ts @@ -1,4 +1,4 @@ -export * from "./components/dashboard.layout" -export * from "./components/dashboard.page" -export * from "./components/dashboard.date.picker" +export * from "./components/layout" +export * from "./components/page" +export * from "./components/date-picker" export * from "./dashboard.types" \ No newline at end of file diff --git a/src/modules/marketing/components/faq.footer.section.tsx b/src/modules/marketing/components/faq-footer-section.tsx similarity index 98% rename from src/modules/marketing/components/faq.footer.section.tsx rename to src/modules/marketing/components/faq-footer-section.tsx index 92f2fa2..3099319 100644 --- a/src/modules/marketing/components/faq.footer.section.tsx +++ b/src/modules/marketing/components/faq-footer-section.tsx @@ -6,7 +6,7 @@ import { } from "@/components/ui/accordion"; import { Footer } from "./footer"; import { faqs } from "@/data/faqs"; -import { GetStarted } from "./get.started.button"; +import { GetStarted } from "./get-started-button"; export function FAQAndFootersection() { diff --git a/src/modules/marketing/components/features.card.tsx b/src/modules/marketing/components/feature-card.tsx similarity index 100% rename from src/modules/marketing/components/features.card.tsx rename to src/modules/marketing/components/feature-card.tsx diff --git a/src/modules/marketing/components/feature.section.tsx b/src/modules/marketing/components/feature-section.tsx similarity index 96% rename from src/modules/marketing/components/feature.section.tsx rename to src/modules/marketing/components/feature-section.tsx index 44ecb51..b214a5a 100644 --- a/src/modules/marketing/components/feature.section.tsx +++ b/src/modules/marketing/components/feature-section.tsx @@ -1,8 +1,8 @@ import { Button } from '@/components/ui/button' import { features } from '@/data/features' import { cn } from '@/lib/utils' -import { FeaturesCard } from './features.card' -import { GetStarted } from './get.started.button' +import { FeaturesCard } from './feature-card' +import { GetStarted } from './get-started-button' export function FeaturesSection() { return ( diff --git a/src/modules/marketing/components/get.started.button.tsx b/src/modules/marketing/components/get-started-button.tsx similarity index 100% rename from src/modules/marketing/components/get.started.button.tsx rename to src/modules/marketing/components/get-started-button.tsx diff --git a/src/modules/marketing/components/hero.section.tsx b/src/modules/marketing/components/hero-section.tsx similarity index 98% rename from src/modules/marketing/components/hero.section.tsx rename to src/modules/marketing/components/hero-section.tsx index 36c0a81..f0161bd 100644 --- a/src/modules/marketing/components/hero.section.tsx +++ b/src/modules/marketing/components/hero-section.tsx @@ -1,6 +1,6 @@ import { GlobeIcon, ShieldCheckIcon, ZapIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { GetStarted } from "./get.started.button"; +import { GetStarted } from "./get-started-button"; type Stat = { label: string, diff --git a/src/modules/marketing/components/pricing.card.tsx b/src/modules/marketing/components/pricing-card.tsx similarity index 100% rename from src/modules/marketing/components/pricing.card.tsx rename to src/modules/marketing/components/pricing-card.tsx diff --git a/src/modules/marketing/components/pricing-section.tsx b/src/modules/marketing/components/pricing-section.tsx index 502cb66..1782c17 100644 --- a/src/modules/marketing/components/pricing-section.tsx +++ b/src/modules/marketing/components/pricing-section.tsx @@ -1,5 +1,5 @@ import { plans } from '@/config/pricing-plans' -import { PricingCard } from './pricing.card' +import { PricingCard } from './pricing-card' export default function PricingSection() { return ( diff --git a/src/modules/marketing/components/public.header.tsx b/src/modules/marketing/components/public-header.tsx similarity index 100% rename from src/modules/marketing/components/public.header.tsx rename to src/modules/marketing/components/public-header.tsx diff --git a/src/modules/marketing/index.ts b/src/modules/marketing/index.ts index 7564470..85ede22 100644 --- a/src/modules/marketing/index.ts +++ b/src/modules/marketing/index.ts @@ -1,8 +1,8 @@ -export * from "./components/features.card" +export * from "./components/feature-card" export * from "./components/footer" -export * from "./components/get.started.button" -export * from "./components/hero.section" -export * from "./components/pricing.card" -export * from "./components/public.header" -export * from "./components/feature.section" -export * from "./components/faq.footer.section" \ No newline at end of file +export * from "./components/get-started-button" +export * from "./components/hero-section" +export * from "./components/pricing-card" +export * from "./components/public-header" +export * from "./components/feature-section" +export * from "./components/faq-footer-section" \ No newline at end of file diff --git a/src/modules/website/components/website.card.tsx b/src/modules/website/components/card.tsx similarity index 99% rename from src/modules/website/components/website.card.tsx rename to src/modules/website/components/card.tsx index 6755a41..9b03317 100644 --- a/src/modules/website/components/website.card.tsx +++ b/src/modules/website/components/card.tsx @@ -28,7 +28,7 @@ import { AlertDialogTrigger, } from "@/components/ui/alert-dialog" import { useState } from 'react' -import { WebsiteStatusIcon } from './website.status.icon'; +import { WebsiteStatusIcon } from './status-icon'; import CopyToClipboard from '@/components/ui/copy-to-clipboard'; import { Card } from "@/components/ui/card"; diff --git a/src/modules/website/components/websites.empty.state.tsx b/src/modules/website/components/empty-state.tsx similarity index 100% rename from src/modules/website/components/websites.empty.state.tsx rename to src/modules/website/components/empty-state.tsx diff --git a/src/modules/website/components/website.form.tsx b/src/modules/website/components/form.tsx similarity index 100% rename from src/modules/website/components/website.form.tsx rename to src/modules/website/components/form.tsx diff --git a/src/modules/website/components/website.manager.tsx b/src/modules/website/components/manager.tsx similarity index 96% rename from src/modules/website/components/website.manager.tsx rename to src/modules/website/components/manager.tsx index f6da271..8b938b0 100644 --- a/src/modules/website/components/website.manager.tsx +++ b/src/modules/website/components/manager.tsx @@ -5,11 +5,11 @@ import { actions } from "astro:actions"; import type { Site } from "@/db/schema"; import { useAction } from "@/hooks/use-action"; import { Button } from "@/components/ui/button"; -import SiteForm from "./website.form"; +import SiteForm from "./form"; import ErrorAlert from "@/components/ui/error-alert"; import { PageHeader } from "@/components/ui/page-header"; -import SiteCard from "./website.card"; -import DomainEmptyState from "./websites.empty.state"; +import SiteCard from "./card"; +import DomainEmptyState from "./empty-state"; interface WebsitePageProps { initialWebsites: Site[]; diff --git a/src/modules/website/components/website.status.icon.tsx b/src/modules/website/components/status-icon.tsx similarity index 100% rename from src/modules/website/components/website.status.icon.tsx rename to src/modules/website/components/status-icon.tsx diff --git a/src/modules/website/index.ts b/src/modules/website/index.ts index 39889e9..32477f3 100644 --- a/src/modules/website/index.ts +++ b/src/modules/website/index.ts @@ -1,2 +1,2 @@ // src/modules/website/index.ts -export * from "./components/website.manager" \ No newline at end of file +export * from "./components/manager" \ No newline at end of file diff --git a/src/pages/script.js.ts b/src/pages/script.js.ts index 7c813e2..359fd0c 100644 --- a/src/pages/script.js.ts +++ b/src/pages/script.js.ts @@ -7,7 +7,7 @@ export const GET: APIRoute = async () => { return new Response(trackerCode, { headers: { 'Content-Type': 'application/javascript; charset=utf-8', - 'Cache-Control': 'public, max-age=31536000, immutable', // Cache aggressively on CDN + 'Cache-Control': 'public, max-age=31536000, immutable', }, }); }; \ No newline at end of file diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index 226999c..fea7e8a 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,18 +1,20 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: 452a347d3488314292a60bc11b20fb7e) -// Runtime types generated with workerd@1.20260401.1 2024-09-23 global_fetch_strictly_public,nodejs_compat_v2 +// Generated by Wrangler by running `wrangler types` (hash: c4102ce12fcf8cf5f658a0f66f7673c8) +// Runtime types generated with workerd@1.20260611.1 2024-09-23 global_fetch_strictly_public,nodejs_compat_v2 +interface __BaseEnv_Env { + DB: D1Database; + ASSETS: Fetcher; + ADMIN_EMAIL: string; + ADMIN_PASSWORD: string; + JWT_SECRET: string; +} declare namespace Cloudflare { - interface Env { - USER_LIMITS: KVNamespace; - DB: D1Database; - EVENTS_QUEUE: Queue; - ASSETS: Fetcher; - ADMIN_PASSWORD: string; - ADMIN_EMAIL: string; - JWT_SECRET: string; + interface GlobalProps { + mainModule: typeof import("./dist/_worker.js/index"); } + interface Env extends __BaseEnv_Env {} } -interface Env extends Cloudflare.Env {} +interface Env extends __BaseEnv_Env {} // Begin runtime types /*! ***************************************************************************** @@ -433,6 +435,8 @@ interface ExecutionContext { waitUntil(promise: Promise): void; passThroughOnException(): void; readonly props: Props; + cache?: CacheContext; + tracing?: Tracing; } type ExportedHandlerFetchHandler = (request: Request>, env: Env, ctx: ExecutionContext) => Response | Promise; type ExportedHandlerConnectHandler = (socket: Socket, env: Env, ctx: ExecutionContext) => void | Promise; @@ -460,6 +464,7 @@ declare abstract class Navigator { sendBeacon(url: string, body?: BodyInit): boolean; readonly userAgent: string; readonly hardwareConcurrency: number; + readonly platform: string; } interface AlarmInvocationInfo { readonly isRetry: boolean; @@ -469,6 +474,25 @@ interface AlarmInvocationInfo { interface Cloudflare { readonly compatibilityFlags: Record; } +interface CachePurgeError { + code: number; + message: string; +} +interface CachePurgeResult { + success: boolean; + errors: CachePurgeError[]; +} +interface CachePurgeOptions { + tags?: string[]; + pathPrefixes?: string[]; + purgeEverything?: boolean; +} +interface CacheContext { + purge(options: CachePurgeOptions): Promise; +} +declare abstract class ColoLocalActorNamespace { + get(actorId: string): Fetcher; +} interface DurableObject { fetch(request: Request): Response | Promise; connect?(socket: Socket): void | Promise; @@ -513,6 +537,7 @@ interface DurableObjectState { readonly id: DurableObjectId; readonly storage: DurableObjectStorage; container?: Container; + facets: DurableObjectFacets; blockConcurrencyWhile(callback: () => Promise): Promise; acceptWebSocket(ws: WebSocket, tags?: string[]): void; getWebSockets(tag?: string): WebSocket[]; @@ -589,6 +614,15 @@ declare class WebSocketRequestResponsePair { get request(): string; get response(): string; } +interface DurableObjectFacets { + get(name: string, getStartupOptions: () => FacetStartupOptions | Promise>): Fetcher; + abort(name: string, reason: any): void; + delete(name: string): void; +} +interface FacetStartupOptions { + id?: DurableObjectId | string; + class: DurableObjectClass; +} interface AnalyticsEngineDataset { writeDataPoint(event?: AnalyticsEngineDataPoint): void; } @@ -881,7 +915,7 @@ interface CustomEventCustomEventInit { * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob) */ declare class Blob { - constructor(type?: ((ArrayBuffer | ArrayBufferView) | string | Blob)[], options?: BlobOptions); + constructor(bits?: ((ArrayBuffer | ArrayBufferView) | string | Blob)[], options?: BlobOptions); /** * The **`size`** read-only property of the Blob interface returns the size of the Blob or File in bytes. * @@ -1869,8 +1903,31 @@ interface KVNamespaceGetWithMetadataResult { } type QueueContentType = "text" | "bytes" | "json" | "v8"; interface Queue { - send(message: Body, options?: QueueSendOptions): Promise; - sendBatch(messages: Iterable>, options?: QueueSendBatchOptions): Promise; + metrics(): Promise; + send(message: Body, options?: QueueSendOptions): Promise; + sendBatch(messages: Iterable>, options?: QueueSendBatchOptions): Promise; +} +interface QueueSendMetrics { + backlogCount: number; + backlogBytes: number; + oldestMessageTimestamp?: Date; +} +interface QueueSendMetadata { + metrics: QueueSendMetrics; +} +interface QueueSendResponse { + metadata: QueueSendMetadata; +} +interface QueueSendBatchMetrics { + backlogCount: number; + backlogBytes: number; + oldestMessageTimestamp?: Date; +} +interface QueueSendBatchMetadata { + metrics: QueueSendBatchMetrics; +} +interface QueueSendBatchResponse { + metadata: QueueSendBatchMetadata; } interface QueueSendOptions { contentType?: QueueContentType; @@ -1884,6 +1941,19 @@ interface MessageSendRequest { contentType?: QueueContentType; delaySeconds?: number; } +interface QueueMetrics { + backlogCount: number; + backlogBytes: number; + oldestMessageTimestamp?: Date; +} +interface MessageBatchMetrics { + backlogCount: number; + backlogBytes: number; + oldestMessageTimestamp?: Date; +} +interface MessageBatchMetadata { + metrics: MessageBatchMetrics; +} interface QueueRetryOptions { delaySeconds?: number; } @@ -1898,12 +1968,14 @@ interface Message { interface QueueEvent extends ExtendableEvent { readonly messages: readonly Message[]; readonly queue: string; + readonly metadata: MessageBatchMetadata; retryAll(options?: QueueRetryOptions): void; ackAll(): void; } interface MessageBatch { readonly messages: readonly Message[]; readonly queue: string; + readonly metadata: MessageBatchMetadata; retryAll(options?: QueueRetryOptions): void; ackAll(): void; } @@ -1922,7 +1994,7 @@ interface R2ListOptions { startAfter?: string; include?: ("httpMetadata" | "customMetadata")[]; } -declare abstract class R2Bucket { +interface R2Bucket { head(key: string): Promise; get(key: string, options: R2GetOptions & { onlyIf: R2Conditional | Headers; @@ -3224,6 +3296,7 @@ interface Container { interceptAllOutboundHttp(binding: Fetcher): Promise; snapshotDirectory(options: ContainerDirectorySnapshotOptions): Promise; snapshotContainer(options: ContainerSnapshotOptions): Promise; + interceptOutboundHttps(addr: string, binding: Fetcher): Promise; } interface ContainerDirectorySnapshot { id: string; @@ -3296,6 +3369,10 @@ type LoopbackDurableObjectClass DurableObjectClass : (opts: { props?: any; }) => DurableObjectClass); +interface LoopbackDurableObjectNamespace extends DurableObjectNamespace { +} +interface LoopbackColoLocalActorNamespace extends ColoLocalActorNamespace { +} interface SyncKvStorage { get(key: string): T | undefined; list(options?: SyncKvListOptions): Iterable<[ @@ -3315,9 +3392,11 @@ interface SyncKvListOptions { } interface WorkerStub { getEntrypoint(name?: string, options?: WorkerStubEntrypointOptions): Fetcher; + getDurableObjectClass(name?: string, options?: WorkerStubEntrypointOptions): DurableObjectClass; } interface WorkerStubEntrypointOptions { props?: any; + limits?: workerdResourceLimits; } interface WorkerLoader { get(name: string | null, getCode: () => WorkerLoaderWorkerCode | Promise): WorkerStub; @@ -3336,6 +3415,7 @@ interface WorkerLoaderWorkerCode { compatibilityDate: string; compatibilityFlags?: string[]; allowExperimental?: boolean; + limits?: workerdResourceLimits; mainModule: string; modules: Record; env?: any; @@ -3343,6 +3423,10 @@ interface WorkerLoaderWorkerCode { tails?: Fetcher[]; streamingTails?: Fetcher[]; } +interface workerdResourceLimits { + cpuMs?: number; + subRequests?: number; +} /** * The Workers runtime supports a subset of the Performance API, used to measure timing and performance, * as well as timing of subrequests and other operations. @@ -3361,78 +3445,367 @@ declare abstract class Performance { */ toJSON(): object; } +interface Tracing { + enterSpan(name: string, callback: (span: Span, ...args: A) => T, ...args: A): T; + Span: typeof Span; +} +declare abstract class Span { + get isTraced(): boolean; + setAttribute(key: string, value?: (boolean | number | string)): void; +} +// ============================================================================ +// Agent Memory +// +// Public type surface for user Workers binding to an Agent Memory namespace. +// ============================================================================ +/** Memory type — every memory is classified into exactly one. */ +type AgentMemoryMemoryType = "fact" | "event" | "instruction" | "task"; +/** Search intensity for recall. */ +type AgentMemoryThinkingLevel = "low" | "medium" | "high"; +/** Response verbosity for recall. */ +type AgentMemoryResponseLength = "short" | "medium" | "long"; +/** A conversation message passed to ingest(). */ +interface AgentMemoryMessage { + role: "system" | "user" | "assistant"; + content: string; + /** Optional message timestamp. */ + timestamp?: Date; +} +/** Raw memory content passed to remember(). */ +interface AgentMemoryIncomingMemory { + /** Raw memory content. The service classifies and summarizes automatically. */ + content: string; + /** Optional session identifier to associate with this memory. */ + sessionId?: string | null | undefined; +} +/** A stored memory returned from remember(), get(), and delete(). */ +interface AgentMemoryMemory { + /** Memory ID. */ + id: string; + /** Memory type. */ + type: AgentMemoryMemoryType; + /** Text summary. */ + summary: string; + /** Memory text. */ + content: string; + /** Session that created this memory. */ + sessionId: string | null; + /** Memory creation time. */ + createdAt: Date; + /** Memory last-update time. */ + updatedAt: Date; +} +/** Single entry in a list() response. Same shape as Memory minus full content. */ +type AgentMemoryMemoryListEntry = Omit; +/** A scored memory candidate in a recall result. */ +interface AgentMemoryScoredCandidate { + /** Candidate ID. */ + id: string; + /** Text summary. */ + summary: string; + /** Session that created this candidate, when known. */ + sessionId: string | null; + /** Relevance score (higher is better). Comparable only within a single query. */ + score: number; +} +/** Options for the ingest() method. */ +interface AgentMemoryIngestOptions { + /** Session identifier to associate with memories created during ingestion. */ + sessionId?: string | null | undefined; +} +/** Options for the getSummary() method. */ +interface AgentMemoryGetSummaryOptions { + /** Session identifier to retrieve session summary for. */ + sessionId?: string | null | undefined; +} +/** Response from the getSummary() method. */ +interface AgentMemoryGetSummaryResponse { + /** Markdown summary. */ + summary: string; +} +/** + * Options for the recall() method. + * + * `referenceDate` accepts a Date object, an ISO-8601 date string + * (YYYY-MM-DD), or a full ISO-8601 datetime string. When provided, this + * date is used as "today" for resolving relative time references + * ("how many days ago", "last week") instead of the server's wall-clock time. + */ +interface AgentMemoryRecallOptions { + /** Recall intensity: "low" (default), "medium", or "high". */ + thinkingLevel?: AgentMemoryThinkingLevel; + /** Response verbosity: "short", "medium" (default), or "long". */ + responseLength?: AgentMemoryResponseLength; + /** Temporal anchor for date arithmetic. */ + referenceDate?: Date | string; +} +/** Response from the recall() method. */ +interface AgentMemoryRecallResult { + /** Number of memories retrieved. */ + count: number; + /** LLM-generated answer synthesizing the matching memories. */ + answer: string; + /** Matching memories ranked by relevance. */ + candidates: AgentMemoryScoredCandidate[]; +} +/** + * Options for the list() method. + * + * `cursor` is the opaque continuation token returned by the previous page; + * pass it back unchanged to fetch the next page. `sessionId` and `type` + * are exact-match filters; combining them is allowed. + */ +interface AgentMemoryListMemoriesOptions { + /** Maximum number of memories to return. Default 20, max 500. */ + limit?: number; + /** Opaque cursor from a previous page. */ + cursor?: string; + /** Exact-match session filter. */ + sessionId?: string; + /** Exact-match memory-type filter. */ + type?: AgentMemoryMemoryType; +} +/** Response from the list() method. */ +interface AgentMemoryListMemoriesResult { + memories: AgentMemoryMemoryListEntry[]; + /** Continuation cursor; absent when this page exhausted the result set. */ + cursor?: string; +} +/** + * A single Agent Memory profile, scoped to a profile name. + * + * Returned by {@link AgentMemoryNamespace.getProfile}. + */ +declare abstract class AgentMemoryProfile { + /** + * Retrieve a memory by ID. + * + * @param memoryId - ULID of the memory to retrieve. + * @throws if the memory does not exist. + */ + get(memoryId: string): Promise; + /** + * Delete a memory by ID. + * + * Removes the memory and any source messages linked by the memory's + * source message IDs. + * + * @param memoryId - ULID of the memory to delete. + * @throws if the memory does not exist. + */ + delete(memoryId: string): Promise; + /** + * Store a memory in this profile. The content is automatically classified, + * summarized, and indexed. + * + * @param memory - Raw memory content to persist. + */ + remember(memory: AgentMemoryIncomingMemory): Promise; + /** + * Extract memories from a conversation. + * + * @param messages - Conversation messages to extract memories from. + * @param options - Optional ingest options. + */ + ingest(messages: Iterable, options?: AgentMemoryIngestOptions): Promise; + /** + * Get a profile summary. + * + * @param options - Optional getSummary options. + */ + getSummary(options?: AgentMemoryGetSummaryOptions): Promise; + /** + * Recall memories in this profile. + * + * @param query - Recall query matched against memory content and keywords. + * @param options - Optional recall parameters. + * @returns Matching memories with relevance scores and a synthesized answer. + */ + recall(query: string, options?: AgentMemoryRecallOptions): Promise; + /** + * List active memories in this profile. + * + * Returns a paginated, filterable view of stored memories. Superseded + * versions are excluded. Use the returned `cursor` (when present) to + * fetch the next page. + * + * @param options - Optional pagination and filter options. + */ + list(options?: AgentMemoryListMemoriesOptions): Promise; + /** + * Soft-delete every memory and message in this profile that is tagged + * with `sessionId`. + * + * Idempotent: deleting a sessionId that has no rows is a no-op. + * + * @param sessionId - Session to delete. + */ + deleteSession(sessionId: string): Promise; +} +/** + * Namespace-level Agent Memory binding. + * + * Used as the type of an `env.MEMORY`-style binding backed by the Agent + * Memory product. + * + * @example + * ```ts + * export default { + * async fetch(_request: Request, env: Env): Promise { + * const profile = await env.MEMORY.getProfile("wrangler-e2e"); + * const summary = await profile.getSummary(); + * return Response.json(summary); + * }, + * }; + * ``` + */ +declare abstract class AgentMemoryNamespace { + /** + * Get a memory profile by name. Profiles are isolated by namespace and + * addressed by a compound key (namespaceId:profileName). + * + * @param profileName - Profile name (validated against naming rules). + * @returns RPC target for interacting with the profile. + */ + getProfile(profileName: string): Promise; + /** + * Soft-delete a profile and schedule deferred purge. Marks all + * memories and messages as deleted. + * + * @param profileName - Name of the profile to delete. + */ + deleteProfile(profileName: string): Promise; +} // ============ AI Search Error Interfaces ============ interface AiSearchInternalError extends Error { } interface AiSearchNotFoundError extends Error { } -// ============ AI Search Request Types ============ -type AiSearchSearchRequest = { - messages: Array<{ - role: 'system' | 'developer' | 'user' | 'assistant' | 'tool'; - content: string | null; - }>; - ai_search_options?: { - retrieval?: { - retrieval_type?: 'vector' | 'keyword' | 'hybrid'; - /** Match threshold (0-1, default 0.4) */ - match_threshold?: number; - /** Maximum number of results (1-50, default 10) */ - max_num_results?: number; - filters?: VectorizeVectorMetadataFilter; - /** Context expansion (0-3, default 0) */ - context_expansion?: number; - [key: string]: unknown; - }; - query_rewrite?: { - enabled?: boolean; - model?: string; - rewrite_prompt?: string; - [key: string]: unknown; - }; - reranking?: { - enabled?: boolean; - model?: '@cf/baai/bge-reranker-base' | string; - /** Match threshold (0-1, default 0.4) */ - match_threshold?: number; - [key: string]: unknown; - }; +// ============ AI Search Common Types ============ +/** A single message in a conversation-style search or chat request. */ +type AiSearchMessage = { + role: 'system' | 'developer' | 'user' | 'assistant' | 'tool'; + content: string | null; +}; +/** + * Common shape for `ai_search_options` used by both single-instance and multi-instance requests. + * Contains retrieval, query rewrite, reranking, and cache sub-options. + */ +type AiSearchOptions = { + retrieval?: { + /** Which retrieval backend to use. Defaults to the instance's configured index_method. */ + retrieval_type?: 'vector' | 'keyword' | 'hybrid'; + /** Fusion method for combining vector + keyword results. */ + fusion_method?: 'max' | 'rrf'; + /** How keyword terms are combined: "and" = all terms must match, "or" = any term matches. */ + keyword_match_mode?: 'and' | 'or'; + /** Minimum similarity score (0-1) for a result to be included. Default 0.4. */ + match_threshold?: number; + /** Maximum number of results to return (1-50). Default 10. */ + max_num_results?: number; + /** Vectorize metadata filters applied to the search. */ + filters?: VectorizeVectorMetadataFilter; + /** Number of surrounding chunks to include for context (0-3). Default 0. */ + context_expansion?: number; + /** If true, return only item metadata without chunk text. */ + metadata_only?: boolean; + /** If true (default), return empty results on retrieval failure instead of throwing. */ + return_on_failure?: boolean; + /** Boost results by metadata field values. Max 3 entries. */ + boost_by?: Array<{ + field: string; + direction?: 'asc' | 'desc' | 'exists' | 'not_exists'; + }>; + [key: string]: unknown; + }; + query_rewrite?: { + enabled?: boolean; + model?: string; + rewrite_prompt?: string; + [key: string]: unknown; + }; + reranking?: { + enabled?: boolean; + model?: string; + /** Match threshold (0-1, default 0.4) */ + match_threshold?: number; [key: string]: unknown; }; + cache?: { + enabled?: boolean; + cache_threshold?: 'super_strict_match' | 'close_enough' | 'flexible_friend' | 'anything_goes'; + }; + [key: string]: unknown; +}; +// ============ AI Search Request Types ============ +/** + * Request body for single-instance search. + * Exactly one of `query` or `messages` must be provided. + */ +type AiSearchSearchRequest = { + /** Simple query string. */ + query: string; + messages?: never; + ai_search_options?: AiSearchOptions; +} | { + query?: never; + /** Conversation-style input. At least one user message with non-empty content is required. */ + messages: AiSearchMessage[]; + ai_search_options?: AiSearchOptions; }; type AiSearchChatCompletionsRequest = { - messages: Array<{ - role: 'system' | 'developer' | 'user' | 'assistant' | 'tool'; - content: string | null; - [key: string]: unknown; - }>; + messages: AiSearchMessage[]; model?: string; stream?: boolean; - ai_search_options?: { - retrieval?: { - retrieval_type?: 'vector' | 'keyword' | 'hybrid'; - match_threshold?: number; - max_num_results?: number; - filters?: VectorizeVectorMetadataFilter; - context_expansion?: number; - [key: string]: unknown; - }; - query_rewrite?: { - enabled?: boolean; - model?: string; - rewrite_prompt?: string; - [key: string]: unknown; - }; - reranking?: { - enabled?: boolean; - model?: '@cf/baai/bge-reranker-base' | string; - match_threshold?: number; - [key: string]: unknown; - }; - [key: string]: unknown; - }; + ai_search_options?: AiSearchOptions; [key: string]: unknown; }; +// ============ AI Search Multi-Instance Types (Namespace-Scoped) ============ +/** `ai_search_options` shape for multi-instance requests — requires `instance_ids`. */ +type AiSearchMultiSearchOptions = AiSearchOptions & { + /** Instance IDs to search across (1-10). */ + instance_ids: string[]; +}; +/** + * Request for searching across multiple instances within a namespace. + * `ai_search_options` is required and must include `instance_ids`. + * Exactly one of `query` or `messages` must be provided. + */ +type AiSearchMultiSearchRequest = { + /** Simple query string. */ + query: string; + messages?: never; + ai_search_options: AiSearchMultiSearchOptions; +} | { + query?: never; + /** Conversation-style input. */ + messages: AiSearchMessage[]; + ai_search_options: AiSearchMultiSearchOptions; +}; +/** A search result chunk tagged with the instance it originated from. */ +type AiSearchMultiSearchChunk = AiSearchSearchResponse['chunks'][number] & { + instance_id: string; +}; +/** Describes a per-instance error during a multi-instance operation. */ +type AiSearchMultiSearchError = { + instance_id: string; + message: string; +}; +/** Response from a multi-instance search, with chunks tagged by instance and optional partial-failure errors. */ +type AiSearchMultiSearchResponse = { + search_query: string; + chunks: AiSearchMultiSearchChunk[]; + errors?: AiSearchMultiSearchError[]; +}; +/** Request for chat completions across multiple instances within a namespace. `ai_search_options` is required and must include `instance_ids`. */ +type AiSearchMultiChatCompletionsRequest = Omit & { + ai_search_options: AiSearchMultiSearchOptions; +}; +/** Response from multi-instance chat completions, with chunks tagged by instance and optional partial-failure errors. */ +type AiSearchMultiChatCompletionsResponse = Omit & { + chunks: AiSearchMultiSearchChunk[]; + errors?: AiSearchMultiSearchError[]; +}; // ============ AI Search Response Types ============ type AiSearchSearchResponse = { search_query: string; @@ -3452,6 +3825,14 @@ type AiSearchSearchResponse = { keyword_score?: number; /** Vector similarity score (0-1) */ vector_score?: number; + /** Keyword rank position */ + keyword_rank?: number; + /** Vector rank position */ + vector_rank?: number; + /** Reranking model score */ + reranking_score?: number; + /** Fusion method used to combine results */ + fusion_method?: 'rrf' | 'max'; [key: string]: unknown; }; }>; @@ -3480,19 +3861,84 @@ type AiSearchStatsResponse = { skipped?: number; outdated?: number; last_activity?: string; + /** Storage engine statistics. */ + engine?: { + vectorize?: { + vectorsCount: number; + dimensions: number; + }; + r2?: { + payloadSizeBytes: number; + metadataSizeBytes: number; + objectCount: number; + }; + }; }; // ============ AI Search Instance Info Types ============ type AiSearchInstanceInfo = { id: string; type?: 'r2' | 'web-crawler' | string; source?: string; + source_params?: unknown; paused?: boolean; status?: string; namespace?: string; created_at?: string; modified_at?: string; + token_id?: string; + ai_gateway_id?: string; + rewrite_query?: boolean; + reranking?: boolean; + embedding_model?: string; + ai_search_model?: string; + rewrite_model?: string; + reranking_model?: string; + /** @deprecated Use index_method instead. */ + hybrid_search_enabled?: boolean; + /** Controls which storage backends are active. */ + index_method?: { + vector?: boolean; + keyword?: boolean; + }; + /** Fusion method for combining vector and keyword results. */ + fusion_method?: 'max' | 'rrf'; + indexing_options?: { + keyword_tokenizer?: 'porter' | 'trigram'; + } | null; + retrieval_options?: { + keyword_match_mode?: 'and' | 'or'; + boost_by?: Array<{ + field: string; + direction?: 'asc' | 'desc' | 'exists' | 'not_exists'; + }>; + } | null; + chunk?: boolean; + chunk_size?: number; + chunk_overlap?: number; + score_threshold?: number; + max_num_results?: number; + cache?: boolean; + cache_threshold?: 'super_strict_match' | 'close_enough' | 'flexible_friend' | 'anything_goes'; + custom_metadata?: Array<{ + field_name: string; + data_type: 'text' | 'number' | 'boolean' | 'datetime'; + }>; + /** Sync interval in seconds. */ + sync_interval?: 3600 | 7200 | 14400 | 21600 | 43200 | 86400; + metadata?: Record; [key: string]: unknown; }; +/** Pagination, search, and ordering parameters for listing instances within a namespace. */ +type AiSearchListInstancesParams = { + page?: number; + per_page?: number; + /** Search instances by ID. */ + search?: string; + /** Field to sort by. */ + order_by?: 'created_at'; + /** Sort direction. */ + order_by_direction?: 'asc' | 'desc'; +}; type AiSearchListResponse = { result: AiSearchInstanceInfo[]; result_info?: { @@ -3520,13 +3966,60 @@ type AiSearchConfig = { reranking?: boolean; embedding_model?: string; ai_search_model?: string; + rewrite_model?: string; + reranking_model?: string; + /** @deprecated Use index_method instead. */ + hybrid_search_enabled?: boolean; + /** Controls which storage backends are used during indexing. Defaults to vector-only. */ + index_method?: { + vector?: boolean; + keyword?: boolean; + }; + /** Fusion method for combining vector and keyword results. "rrf" = reciprocal rank fusion (default), "max" = maximum score. */ + fusion_method?: 'max' | 'rrf'; + indexing_options?: { + keyword_tokenizer?: 'porter' | 'trigram'; + } | null; + retrieval_options?: { + keyword_match_mode?: 'and' | 'or'; + boost_by?: Array<{ + field: string; + direction?: 'asc' | 'desc' | 'exists' | 'not_exists'; + }>; + } | null; + chunk?: boolean; + chunk_size?: number; + chunk_overlap?: number; + /** Minimum similarity score (0-1) for a result to be included. */ + score_threshold?: number; + max_num_results?: number; + cache?: boolean; + /** Similarity threshold for cache hits. Stricter = fewer cache hits but higher relevance. */ + cache_threshold?: 'super_strict_match' | 'close_enough' | 'flexible_friend' | 'anything_goes'; + custom_metadata?: Array<{ + field_name: string; + data_type: 'text' | 'number' | 'boolean' | 'datetime'; + }>; + namespace?: string; + /** Sync interval in seconds. 3600=1h, 7200=2h, 14400=4h, 21600=6h, 43200=12h, 86400=24h. */ + sync_interval?: 3600 | 7200 | 14400 | 21600 | 43200 | 86400; + metadata?: Record; [key: string]: unknown; }; // ============ AI Search Item Types ============ type AiSearchItemInfo = { id: string; key: string; - status: 'completed' | 'error' | 'skipped' | 'queued' | 'processing' | 'outdated'; + status: 'completed' | 'error' | 'skipped' | 'queued' | 'running' | 'outdated'; + next_action?: 'INDEX' | 'DELETE' | null; + error?: string; + checksum?: string; + namespace?: string; + chunks_count?: number | null; + file_size?: number | null; + source_id?: string | null; + last_seen_at?: string; + created_at?: string; metadata?: Record; [key: string]: unknown; }; @@ -3542,6 +4035,16 @@ type AiSearchUploadItemOptions = { type AiSearchListItemsParams = { page?: number; per_page?: number; + /** Search items by key name. */ + search?: string; + /** Sort order for results. */ + sort_by?: 'status' | 'modified_at'; + /** Filter items by processing status. */ + status?: 'queued' | 'running' | 'completed' | 'error' | 'skipped' | 'outdated'; + /** Filter items by source (e.g. "builtin" or "web-crawler:https://example.com"). */ + source?: string; + /** JSON-encoded Vectorize filter for metadata filtering. */ + metadata_filter?: string; }; type AiSearchListItemsResponse = { result: AiSearchItemInfo[]; @@ -3552,6 +4055,61 @@ type AiSearchListItemsResponse = { total_count: number; }; }; +// ============ AI Search Item Logs Types ============ +type AiSearchItemLogsParams = { + /** Maximum number of log entries to return (1-100, default 50). */ + limit?: number; + /** Opaque cursor for pagination. Pass the `cursor` value from a previous response. */ + cursor?: string; +}; +type AiSearchItemLog = { + timestamp: string; + action: string; + message: string; + fileKey?: string; + chunkCount?: number; + processingTimeMs?: number; + errorType?: string; +}; +/** Paginated response for item processing logs (cursor-based). */ +type AiSearchItemLogsResponse = { + result: AiSearchItemLog[]; + result_info: { + count: number; + per_page: number; + cursor: string | null; + truncated: boolean; + }; +}; +// ============ AI Search Item Chunks Types ============ +type AiSearchItemChunksParams = { + /** Maximum number of chunks to return (1-100, default 20). */ + limit?: number; + /** Offset into the chunks list (default 0). */ + offset?: number; +}; +/** A single indexed chunk belonging to an item, including its text content and byte range. */ +type AiSearchItemChunk = { + id: string; + text: string; + start_byte: number; + end_byte: number; + item?: { + timestamp?: number; + key: string; + metadata?: Record; + }; +}; +/** Paginated response for item chunks (offset-based). */ +type AiSearchItemChunksResponse = { + result: AiSearchItemChunk[]; + result_info: { + count: number; + total: number; + limit: number; + offset: number; + }; +}; // ============ AI Search Job Types ============ type AiSearchJobInfo = { id: string; @@ -3600,7 +4158,7 @@ type AiSearchJobLogsResponse = { // ============ AI Search Sub-Service Classes ============ /** * Single item service for an AI Search instance. - * Provides info, delete, and download operations on a specific item. + * Provides info, download, sync, logs, and chunks operations on a specific item. */ declare abstract class AiSearchItem { /** Get metadata about this item. */ @@ -3610,6 +4168,23 @@ declare abstract class AiSearchItem { * @returns Object with body stream, content type, filename, and size. */ download(): Promise; + /** + * Trigger re-indexing of this item. + * @returns The updated item info. + */ + sync(): Promise; + /** + * Retrieve processing logs for this item (cursor-based pagination). + * @param params Optional pagination parameters (limit, cursor). + * @returns Paginated log entries for this item. + */ + logs(params?: AiSearchItemLogsParams): Promise; + /** + * List indexed chunks for this item (offset-based pagination). + * @param params Optional pagination parameters (limit, offset). + * @returns Paginated chunk entries for this item. + */ + chunks(params?: AiSearchItemChunksParams): Promise; } /** * Items collection service for an AI Search instance. @@ -3619,41 +4194,56 @@ declare abstract class AiSearchItems { /** List items in this instance. */ list(params?: AiSearchListItemsParams): Promise; /** - * Upload a file as an item. + * Upload a file as an item. Behaves as an upsert: if an item with the same + * filename already exists, it is overwritten and re-indexed. * @param name Filename for the uploaded item. - * @param content File content as a ReadableStream, ArrayBuffer, or string. + * @param content File content as a ReadableStream, Blob, or string. * @param options Optional metadata to attach to the item. * @returns The created item info. */ - upload(name: string, content: ReadableStream | ArrayBuffer | string, options?: AiSearchUploadItemOptions): Promise; + upload(name: string, content: ReadableStream | Blob | string, options?: AiSearchUploadItemOptions): Promise; /** * Upload a file and poll until processing completes. + * Behaves as an upsert: if an item with the same filename already exists, + * it is overwritten and re-indexed. * @param name Filename for the uploaded item. - * @param content File content as a ReadableStream, ArrayBuffer, or string. - * @param options Optional metadata to attach to the item. + * @param content File content as a ReadableStream, Blob, or string. + * @param options Optional metadata and polling configuration. * @returns The item info after processing completes (or timeout). */ - uploadAndPoll(name: string, content: ReadableStream | ArrayBuffer | string, options?: AiSearchUploadItemOptions): Promise; + uploadAndPoll(name: string, content: ReadableStream | Blob | string, options?: AiSearchUploadItemOptions & { + /** Polling interval in milliseconds (default 1000). */ + pollIntervalMs?: number; + /** Maximum time to wait in milliseconds (default 30000). */ + timeoutMs?: number; + }): Promise; /** * Get an item by ID. * @param itemId The item identifier. - * @returns Item service for info, delete, and download operations. + * @returns Item service for info, download, sync, logs, and chunks operations. */ get(itemId: string): AiSearchItem; - /** Delete this item from the instance. + /** + * Delete an item from the instance. * @param itemId The item identifier. */ delete(itemId: string): Promise; } /** * Single job service for an AI Search instance. - * Provides info and logs for a specific job. + * Provides info, logs, and cancel operations for a specific job. */ declare abstract class AiSearchJob { /** Get metadata about this job. */ info(): Promise; /** Get logs for this job. */ logs(params?: AiSearchJobLogsParams): Promise; + /** + * Cancel a running job. + * @returns The updated job info. + * @throws AiSearchNotFoundError if the job does not exist. + */ + cancel(): Promise; } /** * Jobs collection service for an AI Search instance. @@ -3671,7 +4261,7 @@ declare abstract class AiSearchJobs { /** * Get a job by ID. * @param jobId The job identifier. - * @returns Job service for info and logs operations. + * @returns Job service for info, logs, and cancel operations. */ get(jobId: string): AiSearchJob; } @@ -3690,7 +4280,7 @@ declare abstract class AiSearchJobs { * // Via namespace binding * const instance = env.AI_SEARCH.get("blog"); * const results = await instance.search({ - * messages: [{ role: "user", content: "How does caching work?" }], + * query: "How does caching work?", * }); * * // Via single instance binding @@ -3702,7 +4292,7 @@ declare abstract class AiSearchJobs { declare abstract class AiSearchInstance { /** * Search the AI Search instance for relevant chunks. - * @param params Search request with messages and optional AI search options. + * @param params Search request with query or messages and optional AI search options. * @returns Search response with matching chunks and search query. */ search(params: AiSearchSearchRequest): Promise; @@ -3730,7 +4320,7 @@ declare abstract class AiSearchInstance { info(): Promise; /** * Get instance statistics (item count, indexing status, etc.). - * @returns Statistics with counts per status and last activity time. + * @returns Statistics with counts per status, last activity time, and engine details. */ stats(): Promise; /** Items collection — list, upload, and manage items in this instance. */ @@ -3742,27 +4332,30 @@ declare abstract class AiSearchInstance { * Namespace-level AI Search service. * * Used as the type of `env.AI_SEARCH` (namespace binding via `ai_search_namespaces`). - * Scoped to a single namespace. Provides dynamic instance access, creation, and deletion. + * Scoped to a single namespace. Provides dynamic instance access, creation, deletion, + * and multi-instance search/chat operations. * * @example * ```ts * // Access an instance within the namespace * const blog = env.AI_SEARCH.get("blog"); - * const results = await blog.search({ - * messages: [{ role: "user", content: "How does caching work?" }], - * }); + * const results = await blog.search({ query: "How does caching work?" }); * * // List all instances in the namespace * const instances = await env.AI_SEARCH.list(); * * // Create a new instance with built-in storage - * const tenant = await env.AI_SEARCH.create({ - * id: "tenant-123", - * }); + * const tenant = await env.AI_SEARCH.create({ id: "tenant-123" }); * * // Upload items into the instance * await tenant.items.upload("doc.pdf", fileContent); * + * // Search across multiple instances + * const multi = await env.AI_SEARCH.search({ + * query: "caching", + * ai_search_options: { instance_ids: ["blog", "docs"] }, + * }); + * * // Delete an instance * await env.AI_SEARCH.delete("tenant-123"); * ``` @@ -3775,10 +4368,11 @@ declare abstract class AiSearchNamespace { */ get(name: string): AiSearchInstance; /** - * List all instances in the bound namespace. - * @returns Array of instance metadata. + * List instances in the bound namespace. + * @param params Optional pagination, search, and ordering parameters. + * @returns Array of instance metadata with pagination info. */ - list(): Promise; + list(params?: AiSearchListInstancesParams): Promise; /** * Create a new instance within the bound namespace. * @param config Instance configuration. Only `id` is required — omit `type` and `source` to create with built-in storage. @@ -3803,6 +4397,29 @@ declare abstract class AiSearchNamespace { * @param name Instance name to delete. */ delete(name: string): Promise; + /** + * Search across multiple instances within the bound namespace. + * Fans out to the specified instance_ids and merges results. + * @param params Search request with required `ai_search_options.instance_ids`. + * @returns Search response with chunks tagged by instance_id and optional partial-failure errors. + */ + search(params: AiSearchMultiSearchRequest): Promise; + /** + * Generate chat completions across multiple instances within the bound namespace (streaming). + * Fans out to the specified instance_ids, merges context, and generates a response. + * @param params Chat completions request with stream: true and required `ai_search_options.instance_ids`. + * @returns ReadableStream of server-sent events. + */ + chatCompletions(params: AiSearchMultiChatCompletionsRequest & { + stream: true; + }): Promise; + /** + * Generate chat completions across multiple instances within the bound namespace. + * Fans out to the specified instance_ids, merges context, and generates a response. + * @param params Chat completions request with required `ai_search_options.instance_ids`. + * @returns Chat completion response with choices, chunks tagged by instance_id, and optional partial-failure errors. + */ + chatCompletions(params: AiSearchMultiChatCompletionsRequest): Promise; } type AiImageClassificationInput = { image: number[]; @@ -4404,9 +5021,6 @@ type ChatCompletionChoice = { finish_reason: "stop" | "length" | "tool_calls" | "content_filter" | "function_call"; logprobs: ChatCompletionLogprobs | null; }; -type ChatCompletionsPromptInput = { - prompt: string; -} & ChatCompletionsCommonOptions; type ChatCompletionsMessagesInput = { messages: Array; } & ChatCompletionsCommonOptions; @@ -8336,11 +8950,11 @@ declare abstract class Base_Ai_Cf_Pipecat_Ai_Smart_Turn_V2 { postProcessedOutputs: Ai_Cf_Pipecat_Ai_Smart_Turn_V2_Output; } declare abstract class Base_Ai_Cf_Openai_Gpt_Oss_120B { - inputs: XOR; + inputs: XOR; postProcessedOutputs: XOR; } declare abstract class Base_Ai_Cf_Openai_Gpt_Oss_20B { - inputs: XOR; + inputs: XOR; postProcessedOutputs: XOR; } interface Ai_Cf_Leonardo_Phoenix_1_0_Input { @@ -9316,10 +9930,18 @@ declare abstract class Base_Ai_Cf_Moonshotai_Kimi_K2_5 { inputs: ChatCompletionsInput; postProcessedOutputs: ChatCompletionsOutput; } +declare abstract class Base_Ai_Cf_Moonshotai_Kimi_K2_6 { + inputs: ChatCompletionsInput; + postProcessedOutputs: ChatCompletionsOutput; +} declare abstract class Base_Ai_Cf_Nvidia_Nemotron_3_120B_A12B { inputs: ChatCompletionsInput; postProcessedOutputs: ChatCompletionsOutput; } +declare abstract class Base_Ai_Cf_Google_Gemma_4_26B_A4B_IT { + inputs: ChatCompletionsInput; + postProcessedOutputs: ChatCompletionsOutput; +} interface AiModels { "@cf/huggingface/distilbert-sst-2-int8": BaseAiTextClassification; "@cf/stabilityai/stable-diffusion-xl-base-1.0": BaseAiTextToImage; @@ -9409,7 +10031,9 @@ interface AiModels { "@cf/black-forest-labs/flux-2-klein-9b": Base_Ai_Cf_Black_Forest_Labs_Flux_2_Klein_9B; "@cf/zai-org/glm-4.7-flash": Base_Ai_Cf_Zai_Org_Glm_4_7_Flash; "@cf/moonshotai/kimi-k2.5": Base_Ai_Cf_Moonshotai_Kimi_K2_5; + "@cf/moonshotai/kimi-k2.6": Base_Ai_Cf_Moonshotai_Kimi_K2_6; "@cf/nvidia/nemotron-3-120b-a12b": Base_Ai_Cf_Nvidia_Nemotron_3_120B_A12B; + "@cf/google/gemma-4-26b-a4b-it": Base_Ai_Cf_Google_Gemma_4_26B_A4B_IT; } type AiOptions = { /** @@ -9462,15 +10086,16 @@ type AiModelsSearchObject = { value: string; }[]; }; -type ChatCompletionsBase = XOR; -type ChatCompletionsInput = XOR; +type ChatCompletionsBase = ChatCompletionsMessagesInput; +type ChatCompletionsInput = ChatCompletionsMessagesInput; interface InferenceUpstreamError extends Error { } interface AiInternalError extends Error { } type AiModelListType = Record; +type AiAsyncBatchResponse = { + request_id: string; +}; declare abstract class Ai { aiGatewayLogId: string | null; gateway(gatewayId: string): AiGateway; @@ -9487,13 +10112,35 @@ declare abstract class Ai { * @param autoragId Instance ID */ autorag(autoragId: string): AutoRAG; - run(model: Name, inputs: InputOptions, options?: Options): Promise(model: Name, inputs: { + requests: AiModelList[Name]['inputs'][]; + }, options: AiOptions & { + queueRequest: true; + }): Promise; + // Raw response + run(model: Name, inputs: AiModelList[Name]['inputs'], options: AiOptions & { returnRawResponse: true; - } | { + }): Promise; + // WebSocket + run(model: Name, inputs: AiModelList[Name]['inputs'], options: AiOptions & { websocket: true; - } ? Response : InputOptions extends { + }): Promise; + // Streaming + run(model: Name, inputs: AiModelList[Name]['inputs'] & { stream: true; - } ? ReadableStream : AiModelList[Name]["postProcessedOutputs"]>; + }, options?: AiOptions): Promise; + // Normal (default) - known model + run(model: Name, inputs: AiModelList[Name]['inputs'], options?: AiOptions): Promise; + // Unknown model (fallback). + // + // The `Exclude<..., keyof AiModelList>` constraint forces TypeScript to + // route any model name that is a literal key of `AiModelList` to one of + // the known-model overloads above (so input/output mismatches surface as + // type errors rather than silently falling back to `Record`). + // Names that aren't in `AiModelList` — e.g. third-party gateway models + // like `"google/nano-banana"` — still hit this overload. + run(model: Model extends keyof AiModelList ? never : Model, inputs: Record, options?: AiOptions): Promise>; models(params?: AiModelsSearchParams): Promise; toMarkdown(): ToMarkdownService; toMarkdown(files: MarkdownDocument[], options?: ConversionRequestOptions): Promise; @@ -9591,17 +10238,237 @@ declare abstract class AiGateway { run(data: AIGatewayUniversalRequest | AIGatewayUniversalRequest[], options?: { gateway?: UniversalGatewayOptions; extraHeaders?: object; + signal?: AbortSignal; }): Promise; getUrl(provider?: AIGatewayProviders | string): Promise; // eslint-disable-line } +// Copyright (c) 2022-2025 Cloudflare, Inc. +// Licensed under the Apache 2.0 license found in the LICENSE file or at: +// https://opensource.org/licenses/Apache-2.0 /** - * @deprecated Use the standalone AI Search Workers binding instead. - * See https://developers.cloudflare.com/ai-search/usage/workers-binding/ + * Artifacts — Git-compatible file storage on Cloudflare Workers. + * + * Provides programmatic access to create, manage, and fork repositories, + * and to issue and revoke scoped access tokens. */ -interface AutoRAGInternalError extends Error { +/** Information about a repository. */ +interface ArtifactsRepoInfo { + /** Unique repository ID. */ + id: string; + /** Repository name. */ + name: string; + /** Repository description, or null if not set. */ + description: string | null; + /** Default branch name (e.g. "main"). */ + defaultBranch: string; + /** ISO 8601 creation timestamp. */ + createdAt: string; + /** ISO 8601 last-updated timestamp. */ + updatedAt: string; + /** ISO 8601 timestamp of the last push, or null if never pushed. */ + lastPushAt: string | null; + /** Fork source (e.g. "github:owner/repo", "artifacts:namespace/repo"), or null if not a fork. */ + source: string | null; + /** Whether the repository is read-only. */ + readOnly: boolean; + /** HTTPS git remote URL. */ + remote: string; +} +/** Result of creating a repository — includes the initial access token. */ +interface ArtifactsCreateRepoResult { + /** Unique repository ID. */ + id: string; + /** Repository name. */ + name: string; + /** Repository description, or null if not set. */ + description: string | null; + /** Default branch name. */ + defaultBranch: string; + /** HTTPS git remote URL. */ + remote: string; + /** Plaintext access token (only returned at creation time). */ + token: string; + /** ISO 8601 token expiry timestamp. */ + tokenExpiresAt: string; +} +/** Paginated list of repositories. */ +interface ArtifactsRepoListResult { + /** Repositories in this page (without the `remote` field). */ + repos: Omit[]; + /** Total number of repositories in the namespace. */ + total: number; + /** Cursor for the next page, if there are more results. */ + cursor?: string; +} +/** Result of creating an access token. */ +interface ArtifactsCreateTokenResult { + /** Unique token ID. */ + id: string; + /** Plaintext token (only returned at creation time). */ + plaintext: string; + /** Token scope: "read" or "write". */ + scope: 'read' | 'write'; + /** ISO 8601 token expiry timestamp. */ + expiresAt: string; +} +/** Token metadata (no plaintext). */ +interface ArtifactsTokenInfo { + /** Unique token ID. */ + id: string; + /** Token scope: "read" or "write". */ + scope: 'read' | 'write'; + /** Token state: "active", "expired", or "revoked". */ + state: 'active' | 'expired' | 'revoked'; + /** ISO 8601 creation timestamp. */ + createdAt: string; + /** ISO 8601 expiry timestamp. */ + expiresAt: string; +} +/** Paginated list of tokens for a repository. */ +interface ArtifactsTokenListResult { + /** Tokens in this page. */ + tokens: ArtifactsTokenInfo[]; + /** Total number of tokens for the repository. */ + total: number; } /** - * @deprecated Use the standalone AI Search Workers binding instead. + * Handle for a single repository. Returned by Artifacts.get(). + * + * Methods may throw `ArtifactsError` with code `INTERNAL_ERROR` if an unexpected service error occurs. + */ +interface ArtifactsRepo extends ArtifactsRepoInfo { + /** + * Create an access token for this repo. + * @param scope Token scope: "write" (default) or "read". + * @param ttl Time-to-live in seconds (default 86400, min 60, max 31536000). + * @throws {ArtifactsError} with code `INVALID_TTL` if ttl is out of range. + */ + createToken(scope?: 'write' | 'read', ttl?: number): Promise; + /** List tokens for this repo (metadata only, no plaintext). */ + listTokens(): Promise; + /** + * Revoke a token by plaintext or ID. + * @param tokenOrId Plaintext token or token ID. + * @returns true if revoked, false if not found. + * @throws {ArtifactsError} with code `INVALID_INPUT` if tokenOrId is empty. + */ + revokeToken(tokenOrId: string): Promise; + // ── Fork ── + /** + * Fork this repo to a new repo. + * @param name Target repository name. + * @param opts Optional: description, readOnly flag, defaultBranchOnly (default true). + * @throws {ArtifactsError} with code `INVALID_REPO_NAME` if name is invalid. + * @throws {ArtifactsError} with code `ALREADY_EXISTS` if the target repo already exists. + * @throws {ArtifactsError} with code `FORK_IN_PROGRESS` if a fork is already running. + */ + fork(name: string, opts?: { + description?: string; + readOnly?: boolean; + defaultBranchOnly?: boolean; + }): Promise; +} +// ── Error types ────────────────────────────────────────────────────────────── +/** + * Error codes returned by Artifacts binding operations. + * + * Each code maps to a numeric code available on `ArtifactsError.numericCode`. + */ +type ArtifactsErrorCode = 'ALREADY_EXISTS' | 'NOT_FOUND' | 'IMPORT_IN_PROGRESS' | 'FORK_IN_PROGRESS' | 'INVALID_INPUT' | 'INVALID_REPO_NAME' | 'INVALID_TTL' | 'INVALID_URL' | 'REMOTE_AUTH_REQUIRED' | 'UPSTREAM_UNAVAILABLE' | 'MEMORY_LIMIT' | 'INTERNAL_ERROR'; +/** + * Error thrown by Artifacts binding operations. + * + * Uses a string `.code` discriminator following the Cloudflare platform + * convention (StreamError, ImagesError, etc.). The `.numericCode` matches + * the REST API `errors[].code` values. + */ +interface ArtifactsError extends Error { + readonly name: 'ArtifactsError'; + /** String error code for programmatic matching. */ + readonly code: ArtifactsErrorCode; + /** Numeric error code matching the REST API. */ + readonly numericCode: number; +} +// ── Binding ────────────────────────────────────────────────────────────────── +/** + * Artifacts binding — namespace-level operations. + * + * Methods may throw `ArtifactsError` with code `INTERNAL_ERROR` if an unexpected service error occurs. + */ +interface Artifacts { + /** + * Create a new repository with an initial access token. + * @param name Repository name (alphanumeric, dots, hyphens, underscores). + * @param opts Optional: readOnly flag, description, default branch name. + * @returns Repo metadata with initial token. + * @throws {ArtifactsError} with code `INVALID_REPO_NAME` if name is invalid. + * @throws {ArtifactsError} with code `ALREADY_EXISTS` if the repo already exists. + */ + create(name: string, opts?: { + readOnly?: boolean; + description?: string; + setDefaultBranch?: string; + }): Promise; + /** + * Get a handle to an existing repository. + * @param name Repository name. + * @returns Repo handle. + * @throws {ArtifactsError} with code `NOT_FOUND` if the repo does not exist. + * @throws {ArtifactsError} with code `IMPORT_IN_PROGRESS` if the repo is still importing. + * @throws {ArtifactsError} with code `FORK_IN_PROGRESS` if the repo is still forking. + */ + get(name: string): Promise; + /** + * Import a repository from an external git remote. + * @param params Source URL and optional branch/depth, plus target name and options. + * @returns Repo metadata with initial token. + * @throws {ArtifactsError} with code `INVALID_REPO_NAME` if the target name is invalid. + * @throws {ArtifactsError} with code `INVALID_INPUT` if the source URL is not valid HTTPS. + * @throws {ArtifactsError} with code `INVALID_URL` if the source URL does not point to a git repository. + * @throws {ArtifactsError} with code `REMOTE_AUTH_REQUIRED` if the remote requires authentication. + * @throws {ArtifactsError} with code `NOT_FOUND` if the remote repository does not exist. + * @throws {ArtifactsError} with code `UPSTREAM_UNAVAILABLE` if the remote cannot be reached. + * @throws {ArtifactsError} with code `MEMORY_LIMIT` if the import exceeds service memory limits. + * @throws {ArtifactsError} with code `ALREADY_EXISTS` if the target repo already exists. + */ + import(params: { + source: { + url: string; + branch?: string; + depth?: number; + }; + target: { + name: string; + opts?: { + description?: string; + readOnly?: boolean; + }; + }; + }): Promise; + /** + * List repositories with cursor-based pagination. + * @param opts Optional: limit (1–200, default 50), cursor for next page. + */ + list(opts?: { + limit?: number; + cursor?: string; + }): Promise; + /** + * Delete a repository and all associated tokens. + * @param name Repository name. + * @returns true if deleted, false if not found. + * @throws {ArtifactsError} with code `INVALID_REPO_NAME` if name is invalid. + */ + delete(name: string): Promise; +} +/** + * @deprecated Use the standalone AI Search Workers binding instead. + * See https://developers.cloudflare.com/ai-search/usage/workers-binding/ + */ +interface AutoRAGInternalError extends Error { +} +/** + * @deprecated Use the standalone AI Search Workers binding instead. * See https://developers.cloudflare.com/ai-search/usage/workers-binding/ */ interface AutoRAGNotFoundError extends Error { @@ -9731,6 +10598,452 @@ declare abstract class AutoRAG { */ aiSearch(params: AutoRagAiSearchRequest): Promise; } +type BrowserRunLifecycleEvent = 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'; +type BrowserRunResourceType = 'document' | 'stylesheet' | 'image' | 'media' | 'font' | 'script' | 'texttrack' | 'xhr' | 'fetch' | 'prefetch' | 'eventsource' | 'websocket' | 'manifest' | 'signedexchange' | 'ping' | 'cspviolationreport' | 'preflight' | 'other'; +/** Options fields shared by all quick actions. */ +interface BrowserRunBaseOptions { + /** Adds `