diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d53978..5e0adc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ concurrency: env: BUN_VERSION: 1.3.11 + NODE_VERSION: 22 jobs: quality: @@ -46,6 +47,11 @@ jobs: - name: Check out repository uses: actions/checkout@v6 + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Set up Bun uses: oven-sh/setup-bun@v2 with: @@ -84,6 +90,11 @@ jobs: - name: Check out repository uses: actions/checkout@v6 + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Set up Bun uses: oven-sh/setup-bun@v2 with: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 798ea24..9223cb4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -20,6 +20,7 @@ concurrency: env: BUN_VERSION: 1.3.11 + NODE_VERSION: 22 jobs: deploy: @@ -37,6 +38,11 @@ jobs: with: ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }} + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Set up Bun uses: oven-sh/setup-bun@v2 with: diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index 2c4e87a..ff9d1f3 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,6 +1,6 @@ /* eslint-disable */ // Generated by Wrangler by running `wrangler types` (hash: 66ec2d07ecff4cba477f98430a977e7f) -// Runtime types generated with workerd@1.20260409.1 2026-03-19 nodejs_compat +// Runtime types generated with workerd@1.20260430.1 2026-03-19 nodejs_compat declare namespace Cloudflare { interface GlobalProps { mainModule: typeof import("./src/index"); @@ -454,6 +454,8 @@ interface ExecutionContext { passThroughOnException(): void; readonly exports: Cloudflare.Exports; 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; @@ -481,6 +483,7 @@ declare abstract class Navigator { sendBeacon(url: string, body?: BodyInit): boolean; readonly userAgent: string; readonly hardwareConcurrency: number; + readonly platform: string; readonly language: string; readonly languages: string[]; } @@ -492,6 +495,22 @@ 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; } @@ -1914,8 +1933,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; @@ -1929,6 +1971,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; } @@ -1943,12 +1998,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; } @@ -1967,7 +2024,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; @@ -3390,6 +3447,7 @@ interface WorkerStub { } interface WorkerStubEntrypointOptions { props?: any; + limits?: workerdResourceLimits; } interface WorkerLoader { get(name: string | null, getCode: () => WorkerLoaderWorkerCode | Promise): WorkerStub; @@ -3408,6 +3466,7 @@ interface WorkerLoaderWorkerCode { compatibilityDate: string; compatibilityFlags?: string[]; allowExperimental?: boolean; + limits?: workerdResourceLimits; mainModule: string; modules: Record; env?: any; @@ -3415,6 +3474,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. @@ -3433,78 +3496,144 @@ 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; +} // ============ 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; }; -}; -type AiSearchChatCompletionsRequest = { - messages: Array<{ - role: 'system' | 'developer' | 'user' | 'assistant' | 'tool'; - content: string | null; + query_rewrite?: { + enabled?: boolean; + model?: string; + rewrite_prompt?: string; [key: string]: unknown; - }>; - 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; - }; + }; + 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: AiSearchMessage[]; + model?: string; + stream?: boolean; + 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; @@ -3524,6 +3653,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; }; }>; @@ -3552,19 +3689,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?: { @@ -3592,13 +3794,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; }; @@ -3614,6 +3863,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[]; @@ -3624,6 +3883,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; @@ -3672,7 +3986,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. */ @@ -3682,6 +3996,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. @@ -3691,41 +4022,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. @@ -3743,7 +4089,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; } @@ -3762,7 +4108,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 @@ -3774,7 +4120,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; @@ -3802,7 +4148,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. */ @@ -3814,27 +4160,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"); * ``` @@ -3847,10 +4196,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. @@ -3875,6 +4225,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[]; @@ -9392,6 +9765,10 @@ 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; @@ -9543,6 +9920,9 @@ 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; @@ -9559,13 +9939,28 @@ 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 (gateway fallback) + run(model: string & {}, inputs: Record, options?: AiOptions): Promise>; models(params?: AiModelsSearchParams): Promise; toMarkdown(): ToMarkdownService; toMarkdown(files: MarkdownDocument[], options?: ConversionRequestOptions): Promise; @@ -9663,9 +10058,180 @@ 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 +/** + * 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. + */ +/** 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; +} +/** Handle for a single repository. Returned by Artifacts.get(). */ +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). + */ + 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. + */ + 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). + */ + fork(name: string, opts?: { + description?: string; + readOnly?: boolean; + defaultBranchOnly?: boolean; + }): Promise; +} +/** Artifacts binding — namespace-level operations. */ +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. + */ + 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. + */ + 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. + */ + 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. + */ + delete(name: string): Promise; +} /** * @deprecated Use the standalone AI Search Workers binding instead. * See https://developers.cloudflare.com/ai-search/usage/workers-binding/ @@ -10788,8 +11354,8 @@ declare module "cloudflare:email" { * Evaluation context for targeting rules. * Keys are attribute names (e.g. "userId", "country"), values are the attribute values. */ -type EvaluationContext = Record; -interface EvaluationDetails { +type FlagshipEvaluationContext = Record; +interface FlagshipEvaluationDetails { flagKey: string; value: T; variant?: string | undefined; @@ -10797,7 +11363,7 @@ interface EvaluationDetails { errorCode?: string | undefined; errorMessage?: string | undefined; } -interface FlagEvaluationError extends Error { +interface FlagshipEvaluationError extends Error { } /** * Feature flags binding for evaluating feature flags from a Cloudflare Workers script. @@ -10818,70 +11384,70 @@ interface FlagEvaluationError extends Error { * console.log(details.variant, details.reason); * ``` */ -declare abstract class Flags { +declare abstract class Flagship { /** * Get a flag value without type checking. * @param flagKey The key of the flag to evaluate. * @param defaultValue Optional default value returned when evaluation fails. * @param context Optional evaluation context for targeting rules. */ - get(flagKey: string, defaultValue?: unknown, context?: EvaluationContext): Promise; + get(flagKey: string, defaultValue?: unknown, context?: FlagshipEvaluationContext): Promise; /** * Get a boolean flag value. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getBooleanValue(flagKey: string, defaultValue: boolean, context?: EvaluationContext): Promise; + getBooleanValue(flagKey: string, defaultValue: boolean, context?: FlagshipEvaluationContext): Promise; /** * Get a string flag value. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getStringValue(flagKey: string, defaultValue: string, context?: EvaluationContext): Promise; + getStringValue(flagKey: string, defaultValue: string, context?: FlagshipEvaluationContext): Promise; /** * Get a number flag value. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getNumberValue(flagKey: string, defaultValue: number, context?: EvaluationContext): Promise; + getNumberValue(flagKey: string, defaultValue: number, context?: FlagshipEvaluationContext): Promise; /** * Get an object flag value. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getObjectValue(flagKey: string, defaultValue: T, context?: EvaluationContext): Promise; + getObjectValue(flagKey: string, defaultValue: T, context?: FlagshipEvaluationContext): Promise; /** * Get a boolean flag value with full evaluation details. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getBooleanDetails(flagKey: string, defaultValue: boolean, context?: EvaluationContext): Promise>; + getBooleanDetails(flagKey: string, defaultValue: boolean, context?: FlagshipEvaluationContext): Promise>; /** * Get a string flag value with full evaluation details. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getStringDetails(flagKey: string, defaultValue: string, context?: EvaluationContext): Promise>; + getStringDetails(flagKey: string, defaultValue: string, context?: FlagshipEvaluationContext): Promise>; /** * Get a number flag value with full evaluation details. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getNumberDetails(flagKey: string, defaultValue: number, context?: EvaluationContext): Promise>; + getNumberDetails(flagKey: string, defaultValue: number, context?: FlagshipEvaluationContext): Promise>; /** * Get an object flag value with full evaluation details. * @param flagKey The key of the flag to evaluate. * @param defaultValue Default value returned when evaluation fails or the flag type does not match. * @param context Optional evaluation context for targeting rules. */ - getObjectDetails(flagKey: string, defaultValue: T, context?: EvaluationContext): Promise>; + getObjectDetails(flagKey: string, defaultValue: T, context?: FlagshipEvaluationContext): Promise>; } /** * Hello World binding to serve as an explanatory example. DO NOT USE @@ -11531,13 +12097,13 @@ declare namespace Cloudflare { type GlobalProp = K extends keyof GlobalProps ? GlobalProps[K] : Default; // The type of the program's main module exports, if known. Requires `GlobalProps` to declare the // `mainModule` property. - type MainModule = GlobalProp<"mainModule", {}>; + type MainModule = GlobalProp<'mainModule', {}>; // The type of ctx.exports, which contains loopback bindings for all top-level exports. type Exports = { - [K in keyof MainModule]: LoopbackForExport + [K in keyof MainModule]: LoopbackForExport & // If the export is listed in `durableNamespaces`, then it is also a // DurableObjectNamespace. - & (K extends GlobalProp<"durableNamespaces", never> ? MainModule[K] extends new (...args: any[]) => infer DoInstance ? DoInstance extends Rpc.DurableObjectBranded ? DurableObjectNamespace : DurableObjectNamespace : DurableObjectNamespace : {}); + (K extends GlobalProp<'durableNamespaces', never> ? MainModule[K] extends new (...args: any[]) => infer DoInstance ? DoInstance extends Rpc.DurableObjectBranded ? DurableObjectNamespace : DurableObjectNamespace : DurableObjectNamespace : {}); }; } declare namespace CloudflareWorkersModule { @@ -11557,7 +12123,7 @@ declare namespace CloudflareWorkersModule { email?(message: ForwardableEmailMessage): void | Promise; fetch?(request: Request): Response | Promise; connect?(socket: Socket): void | Promise; - queue?(batch: MessageBatch): void | Promise; + queue?(batch: MessageBatch): void | Promise; scheduled?(controller: ScheduledController): void | Promise; tail?(events: TraceItem[]): void | Promise; tailStream?(event: TailStream.TailEvent): TailStream.TailEventHandlerType | Promise; @@ -11601,17 +12167,31 @@ declare namespace CloudflareWorkersModule { type: string; }; export type WorkflowStepContext = { + step: { + name: string; + count: number; + }; attempt: number; + config: WorkflowStepConfig; }; + export interface RollbackContext { + error: Error; + output: NonNullable | undefined; + stepName: string; + } + export interface StepPromise extends Promise { + rollback(fn: (ctx: RollbackContext) => Promise): StepPromise; + rollback(config: WorkflowStepConfig, fn: (ctx: RollbackContext) => Promise): StepPromise; + } export abstract class WorkflowStep { - do>(name: string, callback: (ctx: WorkflowStepContext) => Promise): Promise; - do>(name: string, config: WorkflowStepConfig, callback: (ctx: WorkflowStepContext) => Promise): Promise; + do>(name: string, callback: (ctx: WorkflowStepContext) => Promise): StepPromise; + do>(name: string, config: WorkflowStepConfig, callback: (ctx: WorkflowStepContext) => Promise): StepPromise; sleep: (name: string, duration: WorkflowSleepDuration) => Promise; sleepUntil: (name: string, timestamp: Date | number) => Promise; waitForEvent>(name: string, options: { type: string; timeout?: WorkflowTimeoutDuration | number; - }): Promise>; + }): StepPromise>; } export type WorkflowInstanceStatus = 'queued' | 'running' | 'paused' | 'errored' | 'terminated' | 'complete' | 'waiting' | 'waitingForPause' | 'unknown'; export abstract class WorkflowEntrypoint | unknown = unknown> implements Rpc.WorkflowEntrypointBranded { @@ -11627,6 +12207,8 @@ declare namespace CloudflareWorkersModule { export function withEnvAndExports(newEnv: unknown, newExports: unknown, fn: () => unknown): unknown; export const env: Cloudflare.Env; export const exports: Cloudflare.Exports; + export const cache: CacheContext; + export const tracing: Tracing; } declare module 'cloudflare:workers' { export = CloudflareWorkersModule; @@ -12494,7 +13076,7 @@ declare namespace TailStream { interface ConnectEventInfo { readonly type: "connect"; } - type EventOutcome = "ok" | "canceled" | "exception" | "unknown" | "killSwitch" | "daemonDown" | "exceededCpu" | "exceededMemory" | "loadShed" | "responseStreamDisconnected" | "scriptNotFound"; + type EventOutcome = "ok" | "canceled" | "exception" | "unknown" | "killSwitch" | "daemonDown" | "exceededCpu" | "exceededMemory" | "loadShed" | "responseStreamDisconnected" | "scriptNotFound" | "internalError"; interface ScriptVersion { readonly id: string; readonly tag?: string;