diff --git a/apps/api/package.json b/apps/api/package.json index fa6135b..7ee37dc 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -11,7 +11,10 @@ "dependencies": { "@embedly/logging": "workspace:*", "@embedly/platforms": "workspace:*", + "@hono/otel": "^1.1.2", "@hono/zod-validator": "^0.7.6", + "@microlabs/otel-cf-workers": "1.0.0-rc.52", + "@opentelemetry/api": "^1.9.1", "hono": "^4.12.15", "zod": "^4.4.1" }, @@ -20,6 +23,6 @@ "@types/node": "catalog:", "oxfmt": "catalog:", "oxlint": "catalog:", - "wrangler": "^4.4.0" + "wrangler": "^4.114.0" } } diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 0e6d5d7..658003e 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -7,7 +7,10 @@ import { getRequestId, } from "@embedly/logging"; import { Platforms } from "@embedly/platforms"; +import { httpInstrumentationMiddleware } from "@hono/otel"; import { zValidator } from "@hono/zod-validator"; +import { instrument, type ResolveConfigFn } from "@microlabs/otel-cf-workers"; +import { trace } from "@opentelemetry/api"; import { Hono } from "hono"; import { bearerAuth } from "hono/bearer-auth"; import { cors } from "hono/cors"; @@ -18,14 +21,17 @@ import { version } from "../package.json"; type ScrapeResponse = Awaited>; -function getTraceId(request: Request) { - const traceparent = request.headers.get("traceparent"); - const traceId = traceparent?.split("-")[1]; - if (!traceId || !/^[a-f0-9]{32}$/.test(traceId)) return undefined; - return traceId; -} +const config: ResolveConfigFn = (env) => { + if (!env.OTEL_ENDPOINT) throw new Error("OTEL_ENDPOINT is required."); + + return { + exporter: { url: env.OTEL_ENDPOINT }, + service: { name: "embedly-api", version }, + }; +}; const app = new Hono<{ Bindings: CloudflareBindings }>() + .use("*", httpInstrumentationMiddleware()) .use(cors()) .use(prettyJSON()) .get("/health", (c) => { @@ -45,9 +51,11 @@ const app = new Hono<{ Bindings: CloudflareBindings }>() const startedAt = Date.now(); const { id, platform, force } = c.req.valid("json"); const requestId = getRequestId(c.req.raw); + const spanContext = trace.getActiveSpan()?.spanContext(); const logContext: Record = { request_id: requestId, - trace_id: getTraceId(c.req.raw), + trace_id: spanContext?.traceId, + span_id: spanContext?.spanId, source: c.req.header("X-Embedly-Source") ?? "api", platform, post_id: id, @@ -101,8 +109,6 @@ const app = new Hono<{ Bindings: CloudflareBindings }>() try { raw = await p.fetch(id, { EMBED_USER_AGENT: c.env.EMBED_USER_AGENT, - REDDIT_CLIENT_ID: c.env.REDDIT_CLIENT_ID, - REDDIT_CLIENT_SECRET: c.env.REDDIT_CLIENT_SECRET, }); } catch (cause) { const problem = createProblem(EmbedlyErrors.PlatformFetchFailed, { @@ -171,5 +177,5 @@ const app = new Hono<{ Bindings: CloudflareBindings }>() }, ); -export default app; +export default instrument(app, config); export type AppType = typeof app; diff --git a/apps/api/worker-configuration.d.ts b/apps/api/worker-configuration.d.ts index bf4e80c..21e83c1 100644 --- a/apps/api/worker-configuration.d.ts +++ b/apps/api/worker-configuration.d.ts @@ -1,28 +1,25 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types --env-interface CloudflareBindings` (hash: 56cc732c5864b92b2f1366e3ff35facb) -// Runtime types generated with workerd@1.20260426.1 2026-04-30 nodejs_compat +// Generated by Wrangler by running `wrangler types --env-interface=CloudflareBindings` (hash: c4267e01e10627c9459c2e5417c281b2) +// Runtime types generated with workerd@1.20260722.1 2026-04-30 nodejs_compat +interface __BaseEnv_CloudflareBindings { + CACHE: KVNamespace; + AUTH_SECRET: string; + EMBED_USER_AGENT: string; + OTEL_ENDPOINT: string; +} declare namespace Cloudflare { interface GlobalProps { mainModule: typeof import("./src/index"); } - interface Env { - CACHE: KVNamespace; - AUTH_SECRET: string; - EMBED_USER_AGENT: string; - REDDIT_CLIENT_ID: string; - REDDIT_CLIENT_SECRET: string; - } + interface Env extends __BaseEnv_CloudflareBindings {} } -interface CloudflareBindings extends Cloudflare.Env {} +interface CloudflareBindings extends __BaseEnv_CloudflareBindings {} type StringifyValues> = { [Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string; }; declare namespace NodeJS { interface ProcessEnv extends StringifyValues< - Pick< - Cloudflare.Env, - "AUTH_SECRET" | "EMBED_USER_AGENT" | "REDDIT_CLIENT_ID" | "REDDIT_CLIENT_SECRET" - > + Pick > {} } @@ -488,7 +485,8 @@ interface ExecutionContext { readonly exports: Cloudflare.Exports; readonly props: Props; cache?: CacheContext; - tracing?: Tracing; + readonly access?: CloudflareAccessContext; + tracing: Tracing; } type ExportedHandlerFetchHandler = ( request: Request>, @@ -581,6 +579,10 @@ interface CachePurgeOptions { interface CacheContext { purge(options: CachePurgeOptions): Promise; } +interface CloudflareAccessContext { + readonly aud: string; + getIdentity(): Promise; +} declare abstract class ColoLocalActorNamespace { get(actorId: string): Fetcher; } @@ -626,7 +628,7 @@ declare abstract class DurableObjectNamespace< ): DurableObjectStub; jurisdiction(jurisdiction: DurableObjectJurisdiction): DurableObjectNamespace; } -type DurableObjectJurisdiction = "eu" | "fedramp" | "fedramp-high"; +type DurableObjectJurisdiction = "eu" | "fedramp" | "fedramp-high" | "us"; interface DurableObjectNamespaceNewUniqueIdOptions { jurisdiction?: DurableObjectJurisdiction; } @@ -637,6 +639,8 @@ type DurableObjectLocationHint = | "weur" | "eeur" | "apac" + | "apac-ne" + | "apac-se" | "oc" | "afr" | "me"; @@ -737,6 +741,7 @@ interface DurableObjectFacets { ): Fetcher; abort(name: string, reason: any): void; delete(name: string): void; + clone(src: string, dst: string): void; } interface FacetStartupOptions { id?: DurableObjectId | string; @@ -1044,7 +1049,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. * @@ -2297,7 +2302,7 @@ interface R2ListOptions { startAfter?: string; include?: ("httpMetadata" | "customMetadata")[]; } -declare abstract class R2Bucket { +interface R2Bucket { head(key: string): Promise; get( key: string, @@ -3652,6 +3657,28 @@ interface EventSourceEventSourceInit { withCredentials?: boolean; fetcher?: Fetcher; } +interface ExecOutput { + readonly stdout: ArrayBuffer; + readonly stderr: ArrayBuffer; + readonly exitCode: number; +} +interface ContainerExecOptions { + cwd?: string; + env?: Record; + user?: string; + stdin?: ReadableStream | "pipe"; + stdout?: "pipe" | "ignore"; + stderr?: "pipe" | "ignore" | "combined"; +} +interface ExecProcess { + readonly stdin: WritableStream | null; + readonly stdout: ReadableStream | null; + readonly stderr: ReadableStream | null; + readonly pid: number; + readonly exitCode: Promise; + output(): Promise; + kill(signal?: number): void; +} interface Container { get running(): boolean; start(options?: ContainerStartupOptions): void; @@ -3667,6 +3694,7 @@ interface Container { ): Promise; snapshotContainer(options: ContainerSnapshotOptions): Promise; interceptOutboundHttps(addr: string, binding: Fetcher): Promise; + exec(cmd: string[], options?: ContainerExecOptions): Promise; } interface ContainerDirectorySnapshot { id: string; @@ -3856,11 +3884,285 @@ interface Tracing { callback: (span: Span, ...args: A) => T, ...args: A ): T; + startActiveSpan( + 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; + end(): void; +} +/** + * Represents the identity of a user authenticated via Cloudflare Access. + * This matches the result of calling /cdn-cgi/access/get-identity. + * + * The exact structure of the returned object depends on the identity provider + * configuration for the Access application. The fields below represent commonly + * available properties, but additional provider-specific fields may be present. + */ +interface CloudflareAccessIdentity extends Record { + /** The user's email address, if available from the identity provider. */ + email?: string; + /** The user's display name. */ + name?: string; + /** The user's unique identifier. */ + user_uuid?: string; + /** The Cloudflare account ID. */ + account_id?: string; + /** Login timestamp (Unix epoch seconds). */ + iat?: number; + /** The user's IP address at authentication time. */ + ip?: string; + /** Authentication methods used (e.g., "pwd"). */ + amr?: string[]; + /** Identity provider information. */ + idp?: { + id: string; + type: string; + }; + /** Geographic information about where the user authenticated. */ + geo?: { + country: string; + }; + /** Group memberships from the identity provider. */ + groups?: Array<{ + id: string; + name: string; + email?: string; + }>; + /** Device posture check results, keyed by check ID. */ + devicePosture?: Record; + /** True if the user connected via Cloudflare WARP. */ + is_warp?: boolean; + /** True if the user is authenticated via Cloudflare Gateway. */ + is_gateway?: boolean; +} +// ============================================================================ +// 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 {} @@ -5267,9 +5569,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; @@ -9374,11 +9673,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 { @@ -10467,6 +10766,10 @@ 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; @@ -10564,7 +10867,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 = { /** @@ -10617,13 +10922,8 @@ type AiModelsSearchObject = { value: string; }[]; }; -type ChatCompletionsBase = XOR; -type ChatCompletionsInput = XOR< - ChatCompletionsBase, - { - requests: ChatCompletionsBase[]; - } ->; +type ChatCompletionsBase = ChatCompletionsMessagesInput; +type ChatCompletionsInput = ChatCompletionsMessagesInput; interface InferenceUpstreamError extends Error {} interface AiInternalError extends Error {} type AiModelListType = Record; @@ -10686,9 +10986,16 @@ declare abstract class Ai { inputs: AiModelList[Name]["inputs"], options?: AiOptions, ): Promise; - // Unknown model (gateway fallback) - run( - model: string & {}, + // 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>; @@ -10912,12 +11219,17 @@ interface ArtifactsTokenListResult { /** Total number of tokens for the repository. */ total: number; } -/** Handle for a single repository. Returned by Artifacts.get(). */ +/** + * 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). */ @@ -10926,6 +11238,7 @@ interface ArtifactsRepo extends ArtifactsRepoInfo { * 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 ── @@ -10933,6 +11246,9 @@ interface ArtifactsRepo extends ArtifactsRepoInfo { * 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, @@ -10943,13 +11259,53 @@ interface ArtifactsRepo extends ArtifactsRepoInfo { }, ): Promise; } -/** Artifacts binding — namespace-level operations. */ +// ── 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, @@ -10963,12 +11319,23 @@ interface Artifacts { * 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: { @@ -10993,6 +11360,7 @@ interface Artifacts { * 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; } @@ -11129,86 +11497,487 @@ declare abstract class AutoRAG { */ aiSearch(params: AutoRagAiSearchRequest): Promise; } -interface BasicImageTransformations { +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 `