inngest
Version:
Official SDK for Inngest.com. Inngest is the reliability layer for modern applications. Inngest combines durable execution, events, and queues into a zero-infra platform with built-in observability.
1 lines • 49.6 kB
Source Map (JSON)
{"version":3,"file":"InngestStepTools.cjs","names":["wrappedMatchOp: MatchOpFn<T>","getAsyncCtxSync","NonRetriableError","opts: HashedOp[\"opts\"]","StepMode","StepOpCode","UnscopedMetadataBuilder","timeStr","matchOpts: { timeout: string; if?: string }","models","msTimeStr: string","internalLoggerSymbol","z","InngestFunction","InngestFunctionReference","opts: {\n payload: MinimalEventPayload;\n function_id: string;\n timeout?: string;\n }","stepFetch","metadataSymbol","headers: Record<string, string>","step: GenericStepTools","getAsyncCtx","group: GroupTools"],"sources":["../../src/components/InngestStepTools.ts"],"sourcesContent":["import { type AiAdapter, models } from \"@inngest/ai\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { z } from \"zod/v3\";\n\nimport type { Jsonify } from \"../helpers/jsonify.ts\";\nimport { timeStr } from \"../helpers/strings.ts\";\nimport * as Temporal from \"../helpers/temporal.ts\";\nimport type {\n ExclusiveKeys,\n ParametersExceptFirst,\n SendEventPayload,\n} from \"../helpers/types.ts\";\nimport {\n type ApplyAllMiddlewareTransforms,\n type Context,\n type EventPayload,\n type HashedOp,\n type InvocationResult,\n type InvokeTargetFunctionDefinition,\n type MinimalEventPayload,\n type SendEventOutput,\n StepMode,\n StepOpCode,\n type StepOptions,\n type StepOptionsOrId,\n type TriggerEventFromFunction,\n} from \"../types.ts\";\nimport { getAsyncCtx, getAsyncCtxSync } from \"./execution/als.ts\";\nimport type { InngestExecution } from \"./execution/InngestExecution.ts\";\nimport { fetch as stepFetch } from \"./Fetch.ts\";\nimport {\n type ClientOptionsFromInngest,\n type GetFunctionOutputRaw,\n type GetStepTools,\n type Inngest,\n internalLoggerSymbol,\n} from \"./Inngest.ts\";\nimport { InngestFunction } from \"./InngestFunction.ts\";\nimport { InngestFunctionReference } from \"./InngestFunctionReference.ts\";\nimport type { GroupTools } from \"./InngestGroupTools.ts\";\nimport {\n type MetadataBuilder,\n type MetadataStepTool,\n metadataSymbol,\n UnscopedMetadataBuilder,\n} from \"./InngestMetadata.ts\";\nimport type { Middleware } from \"./middleware/index.ts\";\nimport { NonRetriableError } from \"./NonRetriableError.ts\";\nimport type { Realtime } from \"./realtime/types.ts\";\nimport type { EventType } from \"./triggers/triggers.ts\";\n\n/**\n * Middleware context for a step, created during step registration.\n *\n * Uses a \"deferred handler\" pattern: the `wrapStep` middleware chain starts\n * during discovery (so middleware can inject its own steps), but the real\n * handler isn't known until after the memoization lookup. `setActualHandler`\n * bridges the gap — the chain blocks on a deferred promise that is resolved\n * once `executeStep` determines the real result.\n */\nexport interface StepMiddlewareContext {\n /**\n * Sets the handler that the middleware pipeline will eventually call.\n * Called after memoization lookup to set either:\n * - A handler returning memoized data, OR\n * - A handler executing the step fresh\n */\n setActualHandler: (handler: () => Promise<unknown>) => void;\n\n /**\n * Step info after middleware transformations. The `options.id` may differ\n * from the original if middleware modified it via `transformStepInput`.\n */\n stepInfo: Middleware.StepInfo;\n\n /**\n * The middleware pipeline entry point. Call this to execute the step\n * through all middleware transformations.\n */\n wrappedHandler: () => Promise<unknown>;\n}\n\nexport interface FoundStep extends HashedOp {\n hashedId: string;\n fn?: (...args: unknown[]) => unknown;\n rawArgs: unknown[];\n\n /**\n * A boolean representing whether the step has been fulfilled, either\n * resolving or rejecting the `Promise` returned to userland code.\n *\n * Note that this is distinct from {@link hasStepState}, which instead tracks\n * whether the step has been given some state from the Executor. State from\n * the Executor could be data other than a resolution or rejection, such as\n * inputs.\n */\n fulfilled: boolean;\n\n /**\n * A boolean representing whether the step has been given some state from the\n * Executor. State from the Executor could be data other than a resolution or\n * rejection, such as inputs.\n *\n * This is distinct from {@link fulfilled}, which instead tracks whether the\n * step has been fulfilled, either resolving or rejecting the `Promise`\n * returned to userland code.\n */\n hasStepState: boolean;\n\n handled: boolean;\n\n /**\n * The promise that has been returned to userland code for this step.\n */\n promise: Promise<unknown>;\n\n /**\n * Returns a boolean representing whether or not the step was handled on this\n * invocation.\n */\n handle: () => boolean;\n\n // TODO This is used to track the input we want for this step. Might be\n // present in ctx from Executor.\n input?: unknown;\n\n /**\n * Middleware context for this step. Holds the `wrapStep` chain entry point\n * and the deferred handler setter used by `executeStep`.\n */\n middleware: StepMiddlewareContext;\n\n /**\n * For new steps where wrappedHandler is called during discovery,\n * this holds the resolve/reject to be called when the step's data is\n * memoized. Resolved with server-transformed data (post-wrapStepHandler),\n * which unblocks wrapStep's `next()`.\n *\n * Is undefined when any of the following is true:\n * - The step is fulfilled\n * - The step has no handler (`step.sleep`, `step.waitForSignal`, etc.)\n */\n memoizationDeferred?: {\n resolve: (value: unknown) => void;\n reject: (error: unknown) => void;\n };\n\n /**\n * For new steps where `wrappedHandler` is called during discovery, this holds\n * the promise for the wrapStep-transformed result. In checkpointing mode,\n * handle() reuses this promise to avoid a duplicate wrapStep call.\n */\n transformedResultPromise?: Promise<unknown>;\n}\n\nexport type MatchOpFn<\n T extends (...args: unknown[]) => Promise<unknown> = (\n ...args: unknown[]\n ) => Promise<unknown>,\n> = (\n stepOptions: StepOptions,\n /**\n * Arguments passed by the user.\n */\n ...args: ParametersExceptFirst<T>\n) => Omit<HashedOp, \"data\" | \"error\">;\n\nexport type StepHandler = (info: {\n matchOp: MatchOpFn;\n opts?: StepToolOptions;\n args: [StepOptionsOrId, ...unknown[]];\n}) => Promise<unknown>;\n\nexport interface StepToolOptions<\n T extends (...args: unknown[]) => Promise<unknown> = (\n ...args: unknown[]\n ) => Promise<unknown>,\n> {\n /**\n * Optionally, we can also provide a function that will be called when\n * Inngest tells us to run this operation.\n *\n * If this function is defined, the first time the tool is used it will\n * report the desired operation (including options) to the Inngest. Inngest\n * will then call back to the function to tell it to run the step and then\n * retrieve data.\n *\n * We do this in order to allow functionality such as per-step retries; this\n * gives the SDK the opportunity to tell Inngest what it wants to do before\n * it does it.\n *\n * This function is passed the arguments passed by the user. It will be run\n * when we receive an operation matching this one that does not contain a\n * `data` property.\n */\n fn?: (...args: [Context.Any, ...Parameters<T>]) => unknown;\n}\n\nexport const getStepOptions = (options: StepOptionsOrId): StepOptions => {\n if (typeof options === \"string\") {\n return { id: options };\n }\n\n return options;\n};\n\n/**\n * Suffix used to namespace steps that are automatically indexed.\n */\nexport const STEP_INDEXING_SUFFIX = \":\";\n\n/**\n * Create a new set of step function tools ready to be used in a step function.\n * This function should be run and a fresh set of tools provided every time a\n * function is run.\n *\n * An op stack (function state) is passed in as well as some mutable properties\n * that the tools can use to submit a new op.\n */\n/**\n * Merge client-level and function-level middleware into a single array type\n * for use with ApplyAllMiddlewareTransforms etc.\n */\ntype MergedMiddleware<\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined,\n> = [\n ...(ClientOptionsFromInngest<TClient>[\"middleware\"] extends Middleware.Class[]\n ? ClientOptionsFromInngest<TClient>[\"middleware\"]\n : []),\n ...(TFnMiddleware extends Middleware.Class[] ? TFnMiddleware : []),\n];\n\nexport const createStepTools = <\n TClient extends Inngest.Any,\n TFnMiddleware extends Middleware.Class[] | undefined = undefined,\n>(\n client: TClient,\n execution: InngestExecution,\n stepHandler: StepHandler,\n) => {\n /**\n * A local helper used to create tools that can be used to submit an op.\n *\n * When using this function, a generic type should be provided which is the\n * function signature exposed to the user.\n */\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n const createTool = <T extends (...args: any[]) => Promise<unknown>>(\n /**\n * A function that returns an ID for this op. This is used to ensure that\n * the op stack is correctly filled, submitted, and retrieved with the same\n * ID.\n *\n * It is passed the arguments passed by the user.\n *\n * Most simple tools will likely only need to define this.\n */\n matchOp: MatchOpFn<T>,\n opts?: StepToolOptions<T>,\n ): T => {\n const wrappedMatchOp: MatchOpFn<T> = (stepOptions, ...rest) => {\n const op = matchOp(stepOptions, ...rest);\n\n const alsCtx = getAsyncCtxSync()?.execution;\n\n if (alsCtx?.insideExperimentSelect) {\n throw new NonRetriableError(\n \"Step tools (step.run, step.sleep, etc.) cannot be called inside \" +\n \"an experiment select() callback. Move step calls into variant \" +\n \"callbacks instead.\",\n );\n }\n\n // Explicit option takes precedence, then check ALS context\n const parallelMode = stepOptions.parallelMode ?? alsCtx?.parallelMode;\n\n if (parallelMode) {\n op.opts = { ...op.opts, parallelMode };\n }\n\n // Propagate experiment context to variant sub-steps\n const experimentContext = alsCtx?.experimentContext;\n if (experimentContext) {\n op.opts = { ...op.opts, ...experimentContext };\n }\n\n // Track that a step tool was invoked inside a variant callback\n const tracker = alsCtx?.experimentStepTracker;\n if (tracker) {\n tracker.found = true;\n }\n\n return op;\n };\n\n return (async (...args: Parameters<T>): Promise<unknown> => {\n const parsedArgs = args as unknown as [StepOptionsOrId, ...unknown[]];\n return stepHandler({ args: parsedArgs, matchOp: wrappedMatchOp, opts });\n }) as T;\n };\n\n /**\n * Create a new step run tool that can be used to run a step function using\n * `step.run()` as a shim.\n */\n const createStepRun = (\n /**\n * The sub-type of this step tool, exposed via `opts.type` when the op is\n * reported.\n */\n type?: string,\n ) => {\n return createTool<\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n <TFn extends (...args: any[]) => unknown>(\n idOrOptions: StepOptionsOrId,\n\n /**\n * The function to run when this step is executed. Can be synchronous or\n * asynchronous.\n *\n * The return value of this function will be the return value of this\n * call to `run`, meaning you can return and reason about return data\n * for next steps.\n */\n fn: TFn,\n\n /**\n * Optional input to pass to the function. If this is specified, Inngest\n * will keep track of the input for this step and be able to display it\n * in the UI.\n */\n ...input: Parameters<TFn>\n ) => Promise<\n ApplyAllMiddlewareTransforms<\n MergedMiddleware<TClient, TFnMiddleware>,\n TFn extends (...args: Parameters<TFn>) => Promise<infer U>\n ? Awaited<U extends void ? null : U>\n : ReturnType<TFn> extends void\n ? null\n : ReturnType<TFn>\n >\n >\n >(\n ({ id, name }, _fn, ...input) => {\n const opts: HashedOp[\"opts\"] = {\n ...(input.length ? { input } : {}),\n ...(type ? { type } : {}),\n };\n\n return {\n id,\n mode: StepMode.Sync,\n op: StepOpCode.StepPlanned,\n name: id,\n displayName: name ?? id,\n ...(Object.keys(opts).length ? { opts } : {}),\n userland: { id },\n };\n },\n {\n fn: (_, __, fn, ...input) => fn(...input),\n },\n );\n };\n\n /**\n * Creates a metadata builder wrapper for step.metadata(\"id\").\n * Uses MetadataBuilder for config accumulation, but wraps .update() in tools.run() for memoization.\n */\n const createStepMetadataWrapper = (\n memoizationId: string,\n builder?: UnscopedMetadataBuilder,\n ) => {\n if (!client[\"experimentalMetadataEnabled\"]) {\n throw new Error(\n 'step.metadata() is experimental. Enable it by adding metadataMiddleware() from \"inngest/experimental\" to your client middleware.',\n );\n }\n const withBuilder = (next: UnscopedMetadataBuilder) =>\n createStepMetadataWrapper(memoizationId, next);\n\n if (!builder) {\n builder = new UnscopedMetadataBuilder(client).run();\n }\n\n return {\n run: (runId?: string) => withBuilder(builder.run(runId)),\n step: (stepId: string, index?: number) =>\n withBuilder(builder.step(stepId, index)),\n attempt: (attemptIndex: number) =>\n withBuilder(builder.attempt(attemptIndex)),\n span: (spanId: string) => withBuilder(builder.span(spanId)),\n update: async (\n values: Record<string, unknown>,\n kind = \"default\",\n ): Promise<void> => {\n await tools.run(memoizationId, async () => {\n await builder.update(values, kind);\n });\n },\n\n do: async (\n fn: (builder: MetadataBuilder) => Promise<void>,\n ): Promise<void> => {\n await tools.run(memoizationId, async () => {\n await fn(builder);\n });\n },\n };\n };\n\n /**\n * Define the set of tools the user has access to for their step functions.\n *\n * Each key is the function name and is expected to run `createTool` and pass\n * a generic type for that function as it will appear in the user's code.\n */\n const tools = {\n /**\n * Send one or many events to Inngest. Should always be used in place of\n * `inngest.send()` to ensure that the event send is successfully retried\n * and not sent multiple times due to memoisation.\n *\n * @example\n * ```ts\n * await step.sendEvent(\"emit-user-creation\", {\n * name: \"app/user.created\",\n * data: { id: 123 },\n * });\n *\n * await step.sendEvent(\"emit-user-updates\", [\n * {\n * name: \"app/user.created\",\n * data: { id: 123 },\n * },\n * {\n * name: \"app/user.feed.created\",\n * data: { id: 123 },\n * },\n * ]);\n * ```\n *\n * Returns a promise that will resolve once the event has been sent.\n */\n sendEvent: createTool<\n (\n idOrOptions: StepOptionsOrId,\n payload: SendEventPayload,\n ) => Promise<SendEventOutput<ClientOptionsFromInngest<TClient>>>\n >(\n ({ id, name }) => {\n return {\n id,\n mode: StepMode.Sync,\n op: StepOpCode.StepPlanned,\n name: \"sendEvent\",\n displayName: name ?? id,\n opts: {\n type: \"step.sendEvent\",\n },\n userland: { id },\n };\n },\n {\n fn: (_ctx, _idOrOptions, payload) => {\n const fn = execution[\"options\"][\"fn\"];\n return client[\"_send\"]({\n payload,\n headers: execution[\"options\"][\"headers\"],\n fnMiddleware: fn.opts.middleware ?? [],\n fn,\n });\n },\n },\n ),\n\n /**\n * EXPERIMENTAL: This API is not yet stable and may change in the future\n * without a major version bump.\n *\n * Wait for a particular signal to be received before continuing. When the\n * signal is received, its data will be returned.\n */\n waitForSignal: createTool<\n <TData>(\n idOrOptions: StepOptionsOrId,\n opts: WaitForSignalOpts,\n ) => Promise<{ signal: string; data: Jsonify<TData> } | null>\n >(({ id, name }, opts) => {\n // TODO Should support Temporal.DurationLike, Temporal.InstantLike,\n // Temporal.ZonedDateTimeLike\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.WaitForSignal,\n name: opts.signal,\n displayName: name ?? id,\n opts: {\n signal: opts.signal,\n timeout: timeStr(opts.timeout),\n conflict: opts.onConflict,\n },\n userland: { id },\n };\n }),\n\n /**\n * Step-level functionality related to realtime features.\n *\n * Unlike client-level realtime methods (`inngest.realtime.*`), these tools\n * will be their own durable steps when run. If you wish to use realtime\n * features outside of a step, make sure to use the client-level methods\n * instead.\n */\n realtime: {\n /**\n * Publish a realtime message as a durable step. Memoized and will not\n * re-fire on retry, unlike client-level `inngest.realtime.publish()`.\n *\n * Uses topic accessors: `step.realtime.publish(\"id\", chat.status, data)`\n */\n publish: createTool<\n <TData>(\n idOrOptions: StepOptionsOrId,\n topicRef: Realtime.TopicRef<TData>,\n data: TData,\n ) => Promise<TData>\n >(\n ({ id, name }) => {\n return {\n id,\n mode: StepMode.Sync,\n op: StepOpCode.StepPlanned,\n displayName: name ?? id,\n opts: {\n type: \"step.realtime.publish\",\n },\n userland: { id },\n };\n },\n {\n fn: async (ctx, _idOrOptions, topicRef, data) => {\n const topicConfig = topicRef.config;\n if (topicConfig && \"schema\" in topicConfig && topicConfig.schema) {\n const result =\n await topicConfig.schema[\"~standard\"].validate(data);\n if (result.issues) {\n throw new Error(\n `Schema validation failed for topic \"${topicRef.topic}\"`,\n );\n }\n }\n\n const res = await client[\"inngestApi\"].publish(\n {\n topics: [topicRef.topic],\n channel: topicRef.channel,\n runId: ctx.runId,\n },\n data,\n );\n\n if (!res.ok) {\n throw new Error(\n `Failed to publish to realtime: ${res.error?.error || \"Unknown error\"}`,\n );\n }\n\n return data;\n },\n },\n ),\n },\n\n /**\n * Send a Signal to Inngest.\n */\n sendSignal: createTool<\n (idOrOptions: StepOptionsOrId, opts: SendSignalOpts) => Promise<null>\n >(\n ({ id, name }, opts) => {\n return {\n id,\n mode: StepMode.Sync,\n op: StepOpCode.StepPlanned,\n name: \"sendSignal\",\n displayName: name ?? id,\n opts: {\n type: \"step.sendSignal\",\n signal: opts.signal,\n },\n userland: { id },\n };\n },\n {\n fn: (_ctx, _idOrOptions, opts) => {\n return client[\"_sendSignal\"]({\n signal: opts.signal,\n data: opts.data,\n headers: execution[\"options\"][\"headers\"],\n });\n },\n },\n ),\n\n /**\n * Wait for a particular event to be received before continuing. When the\n * event is received, it will be returned.\n *\n * You can also provide options to control the particular event that is\n * received, for example to ensure that a user ID matches between two\n * events, or to only wait a maximum amount of time before giving up and\n * returning `null` instead of any event data.\n */\n waitForEvent: createTool<\n <\n TOpts extends {\n /**\n * The event to wait for.\n */\n event:\n | string\n // biome-ignore lint/suspicious/noExplicitAny: Allow any schema\n | EventType<string, any>;\n\n /**\n * The step function will wait for the event for a maximum of this\n * time, at which point the signal will be returned as `null` instead\n * of any signal data.\n *\n * The time to wait can be specified using a `number` of milliseconds,\n * an `ms`-compatible time string like `\"1 hour\"`, `\"30 mins\"`, or\n * `\"2.5d\"`, or a `Date` object.\n *\n * {@link https://npm.im/ms}\n */\n timeout: number | string | Date;\n } & ExclusiveKeys<{ match?: string; if?: string }, \"match\", \"if\">,\n >(\n idOrOptions: StepOptionsOrId,\n opts: TOpts,\n ) => Promise<WaitForEventResult<TOpts>>\n >(\n (\n { id, name },\n\n /**\n * Options to control the event we're waiting for.\n */\n opts,\n ) => {\n const matchOpts: { timeout: string; if?: string } = {\n timeout: timeStr(typeof opts === \"string\" ? opts : opts.timeout),\n };\n\n if (typeof opts !== \"string\") {\n if (opts?.match) {\n matchOpts.if = `event.${opts.match} == async.${opts.match}`;\n } else if (opts?.if) {\n matchOpts.if = opts.if;\n }\n }\n\n // Extract event name from string or EventType object\n const eventName =\n typeof opts.event === \"string\" ? opts.event : opts.event.name;\n\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.WaitForEvent,\n name: eventName,\n opts: matchOpts,\n displayName: name ?? id,\n userland: { id },\n };\n },\n ),\n\n /**\n * Use this tool to run business logic. Each call to `run` will be retried\n * individually, meaning you can compose complex workflows that safely\n * retry dependent asynchronous actions.\n *\n * The function you pass to `run` will be called only when this \"step\" is to\n * be executed and can be synchronous or asynchronous.\n *\n * In either case, the return value of the function will be the return value\n * of the `run` tool, meaning you can return and reason about return data\n * for next steps.\n */\n run: createStepRun(),\n\n /**\n * AI tooling for running AI models and other AI-related tasks.\n */\n ai: {\n /**\n * Use this tool to have Inngest make your AI calls. Useful for agentic workflows.\n *\n * Input is also tracked for this tool, meaning you can pass input to the\n * function and it will be displayed and editable in the UI.\n */\n infer: createTool<\n <TAdapter extends AiAdapter>(\n idOrOptions: StepOptionsOrId,\n options: AiInferOpts<TAdapter>,\n ) => Promise<AiAdapter.Output<TAdapter>>\n >(({ id, name }, options) => {\n // eslint-disable-next-line\n const { model, body, ...rest } = options;\n\n const modelCopy = { ...model };\n\n // Allow the model to mutate options and body for this call\n options.model.onCall?.(modelCopy, options.body);\n\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.AiGateway,\n displayName: name ?? id,\n opts: {\n type: \"step.ai.infer\",\n url: modelCopy.url,\n headers: modelCopy.headers,\n auth_key: modelCopy.authKey,\n format: modelCopy.format,\n // eslint-disable-next-line\n body,\n // eslint-disable-next-line\n ...rest,\n },\n userland: { id },\n };\n }),\n\n /**\n * Use this tool to wrap AI models and other AI-related tasks. Each call\n * to `wrap` will be retried individually, meaning you can compose complex\n * workflows that safely retry dependent asynchronous actions.\n *\n * Input is also tracked for this tool, meaning you can pass input to the\n * function and it will be displayed and editable in the UI.\n */\n wrap: createStepRun(\"step.ai.wrap\"),\n\n /**\n * Models for AI inference and other AI-related tasks.\n */\n models: {\n ...models,\n },\n },\n\n /**\n * Wait a specified amount of time before continuing.\n *\n * The time to wait can be specified using a `number` of milliseconds or an\n * `ms`-compatible time string like `\"1 hour\"`, `\"30 mins\"`, or `\"2.5d\"`.\n *\n * {@link https://npm.im/ms}\n *\n * To wait until a particular date, use `sleepUntil` instead.\n */\n sleep: createTool<\n (\n idOrOptions: StepOptionsOrId,\n\n /**\n * The amount of time to wait before continuing.\n */\n time: number | string | Temporal.DurationLike,\n ) => Promise<void>\n >(({ id, name }, time) => {\n /**\n * The presence of this operation in the returned stack indicates that the\n * sleep is over and we should continue execution.\n */\n const msTimeStr: string = timeStr(\n Temporal.isTemporalDuration(time)\n ? time.total({ unit: \"milliseconds\" })\n : (time as number | string),\n );\n\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.Sleep,\n name: msTimeStr,\n displayName: name ?? id,\n userland: { id },\n };\n }),\n\n /**\n * Wait until a particular date before continuing by passing a `Date`.\n *\n * To wait for a particular amount of time from now, always use `sleep`\n * instead.\n */\n sleepUntil: createTool<\n (\n idOrOptions: StepOptionsOrId,\n\n /**\n * The date to wait until before continuing.\n */\n time: Date | string | Temporal.InstantLike | Temporal.ZonedDateTimeLike,\n ) => Promise<void>\n >(({ id, name }, time) => {\n try {\n const iso = Temporal.getISOString(time);\n\n /**\n * The presence of this operation in the returned stack indicates that the\n * sleep is over and we should continue execution.\n */\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.Sleep,\n name: iso,\n displayName: name ?? id,\n userland: { id },\n };\n } catch (err) {\n /**\n * If we're here, it's because the date is invalid. We'll throw a custom\n * error here to standardise this response.\n */\n client[internalLoggerSymbol].warn(\n { err },\n \"Invalid `Date`, date string, `Temporal.Instant`, or `Temporal.ZonedDateTime` passed to sleepUntil\",\n );\n\n throw new Error(\n `Invalid \\`Date\\`, date string, \\`Temporal.Instant\\`, or \\`Temporal.ZonedDateTime\\` passed to sleepUntil: ${\n time\n }`,\n );\n }\n }),\n\n /**\n * Invoke a passed Inngest `function` with the given `data`. Returns the\n * result of the returned value of the function or `null` if the function\n * does not return a value.\n */\n invoke: createTool<\n <TFunction extends InvokeTargetFunctionDefinition>(\n idOrOptions: StepOptionsOrId,\n opts: InvocationOpts<TFunction>,\n ) => InvocationResult<\n ApplyAllMiddlewareTransforms<\n MergedMiddleware<TClient, TFnMiddleware>,\n GetFunctionOutputRaw<TFunction>,\n \"functionOutputTransform\"\n >\n >\n >(({ id, name }, invokeOpts) => {\n // Create a discriminated union to operate on based on the input types\n // available for this tool.\n const optsSchema = invokePayloadSchema.extend({\n timeout: z.union([z.number(), z.string(), z.date()]).optional(),\n });\n\n const parsedFnOpts = optsSchema\n .extend({\n _type: z.literal(\"fnInstance\").optional().default(\"fnInstance\"),\n function: z.instanceof(InngestFunction),\n })\n .or(\n optsSchema.extend({\n _type: z.literal(\"refInstance\").optional().default(\"refInstance\"),\n function: z.instanceof(InngestFunctionReference),\n }),\n )\n .safeParse(invokeOpts);\n\n if (!parsedFnOpts.success) {\n throw new Error(\n `Invalid invocation options passed to invoke; must include a function instance or referenceFunction().`,\n );\n }\n\n const { _type, function: fn, data, v, timeout } = parsedFnOpts.data;\n const payload = { data, v } satisfies MinimalEventPayload;\n const opts: {\n payload: MinimalEventPayload;\n function_id: string;\n timeout?: string;\n } = {\n payload,\n function_id: \"\",\n timeout: typeof timeout === \"undefined\" ? undefined : timeStr(timeout),\n };\n\n switch (_type) {\n case \"fnInstance\":\n opts.function_id = fn.id(fn[\"client\"].id);\n break;\n\n case \"refInstance\":\n opts.function_id = [fn.opts.appId || client.id, fn.opts.functionId]\n .filter(Boolean)\n .join(\"-\");\n break;\n }\n\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.InvokeFunction,\n displayName: name ?? id,\n opts,\n userland: { id },\n };\n }),\n\n /**\n * `step.fetch` is a Fetch-API-compatible function that can be used to make\n * any HTTP code durable if it's called within an Inngest function.\n *\n * It will gracefully fall back to the global `fetch` if called outside of\n * this context, and a custom fallback can be set using the `config` method.\n */\n fetch: stepFetch,\n };\n\n // NOTE: This should be moved into the above object definition under the key\n // \"metadata\" when metadata is made non-experimental.\n (tools as unknown as ExperimentalStepTools)[metadataSymbol] = (\n memoizationId: string,\n ): MetadataStepTool => createStepMetadataWrapper(memoizationId);\n\n // Attach a step.run variant with opts.type = \"group.experiment\" for use by\n // group.experiment(). The symbol keeps it off the public `step` surface.\n (tools as unknown as ExperimentStepTools)[experimentStepRunSymbol] =\n createStepRun(\"group.experiment\");\n\n // Add an uptyped gateway\n (tools as unknown as InternalStepTools)[gatewaySymbol] = createTool(\n ({ id, name }, input, init) => {\n const url = input instanceof Request ? input.url : input.toString();\n\n const headers: Record<string, string> = {};\n if (input instanceof Request) {\n input.headers.forEach((value, key) => {\n headers[key] = value;\n });\n } else if (init?.headers) {\n const h = new Headers(init.headers);\n h.forEach((value, key) => {\n headers[key] = value;\n });\n }\n\n return {\n id,\n mode: StepMode.Async,\n op: StepOpCode.Gateway,\n displayName: name ?? id,\n opts: {\n url,\n method: init?.method ?? \"GET\",\n headers,\n body: init?.body,\n },\n userland: { id },\n };\n },\n );\n\n return tools;\n};\n\n/**\n * A generic set of step tools, without typing information about the client used\n * to create them.\n */\nexport type GenericStepTools = GetStepTools<Inngest.Any>;\n\nexport const gatewaySymbol = Symbol.for(\"inngest.step.gateway\");\n\nexport type InternalStepTools = GetStepTools<Inngest.Any> & {\n [gatewaySymbol]: (\n idOrOptions: StepOptionsOrId,\n ...args: Parameters<typeof fetch>\n ) => Promise<{\n status_code: number;\n headers: Record<string, string>;\n body: string;\n }>;\n};\n\nexport type ExperimentalStepTools = GetStepTools<Inngest.Any> & {\n [metadataSymbol]: (memoizationId: string) => MetadataStepTool;\n};\n\nexport const experimentStepRunSymbol = Symbol.for(\"inngest.group.experiment\");\n\nexport type ExperimentStepTools = GetStepTools<Inngest.Any> & {\n [experimentStepRunSymbol]: (\n idOrOptions: StepOptionsOrId,\n fn: () => unknown,\n ) => Promise<unknown>;\n};\n\n/**\n * A generic set of step tools that can be used without typing information about\n * the client used to create them.\n *\n * These tools use AsyncLocalStorage to track the context in which they are\n * used, and will throw an error if used outside of an Inngest context.\n *\n * The intention of these high-level tools is to allow usage of Inngest step\n * tools within API endpoints, though they can still be used within regular\n * Inngest functions as well.\n */\nexport const step: GenericStepTools = {\n // TODO Support `step.fetch` (this is already kinda half way deferred)\n fetch: null as unknown as GenericStepTools[\"fetch\"],\n ai: {\n infer: (...args) =>\n getDeferredStepTooling().then((tools) => tools.ai.infer(...args)),\n wrap: (...args) =>\n getDeferredStepTooling().then((tools) => tools.ai.wrap(...args)),\n models: {\n ...models,\n },\n },\n invoke: (...args) =>\n getDeferredStepTooling().then((tools) => tools.invoke(...args)),\n run: (...args) =>\n getDeferredStepTooling().then((tools) => tools.run(...args)),\n sendEvent: (...args) =>\n getDeferredStepTooling().then((tools) => tools.sendEvent(...args)),\n sendSignal: (...args) =>\n getDeferredStepTooling().then((tools) => tools.sendSignal(...args)),\n sleep: (...args) =>\n getDeferredStepTooling().then((tools) => tools.sleep(...args)),\n sleepUntil: (...args) =>\n getDeferredStepTooling().then((tools) => tools.sleepUntil(...args)),\n waitForEvent: (...args) =>\n getDeferredStepTooling().then((tools) => tools.waitForEvent(...args)),\n waitForSignal: (...args) =>\n getDeferredStepTooling().then((tools) => tools.waitForSignal(...args)),\n realtime: {\n publish: (...args) =>\n getDeferredStepTooling().then((tools) => tools.realtime.publish(...args)),\n },\n};\n\n/**\n * An internal function used to retrieve or create step tooling for the current\n * execution context.\n *\n * Note that this requires an existing context to create the step tooling;\n * something must declare the Inngest execution context before this can be used.\n */\nconst getDeferredStepTooling = async (): Promise<GenericStepTools> => {\n const ctx = await getAsyncCtx();\n if (!ctx) {\n throw new Error(\n \"`step` tools can only be used within Inngest function executions; no context was found\",\n );\n }\n\n if (!ctx.app) {\n throw new Error(\n \"`step` tools can only be used within Inngest function executions; no Inngest client was found in the execution context\",\n );\n }\n\n if (!ctx.execution) {\n throw new Error(\n \"`step` tools can only be used within Inngest function executions; no execution context was found\",\n );\n }\n\n // If we're here, we're in the context of a function execution already and\n // we can return the existing step tooling.\n return ctx.execution.ctx.step;\n};\n\nconst getDeferredGroupTooling = async (): Promise<GroupTools> => {\n const ctx = await getAsyncCtx();\n if (!ctx) {\n throw new Error(\n \"`group` tools can only be used within Inngest function executions; no context was found\",\n );\n }\n\n if (!ctx.execution) {\n throw new Error(\n \"`group` tools can only be used within Inngest function executions; no execution context was found\",\n );\n }\n\n return ctx.execution.ctx.group;\n};\n\n/**\n * A deferred proxy for `group` tools that delegates through ALS context.\n *\n * @public\n */\nexport const group: GroupTools = {\n parallel: (...args) =>\n getDeferredGroupTooling().then((tools) => tools.parallel(...args)),\n experiment: (...args) =>\n getDeferredGroupTooling().then((tools) => tools.experiment(...args)),\n};\n\n/**\n * The event payload portion of the options for `step.invoke()`. This does not\n * include non-payload options like `timeout` or the function to invoke.\n */\nexport const invokePayloadSchema = z.object({\n data: z.record(z.any()).optional(),\n v: z.string().optional(),\n});\n\ntype InvocationTargetOpts<TFunction extends InvokeTargetFunctionDefinition> = {\n function: TFunction;\n};\n\ntype InvocationOpts<TFunction extends InvokeTargetFunctionDefinition> =\n InvocationTargetOpts<TFunction> &\n Omit<TriggerEventFromFunction<TFunction>, \"id\"> & {\n /**\n * The step function will wait for the invocation to finish for a maximum\n * of this time, at which point the retured promise will be rejected\n * instead of resolved with the output of the invoked function.\n *\n * Note that the invoked function will continue to run even if this step\n * times out.\n *\n * The time to wait can be specified using a `number` of milliseconds, an\n * `ms`-compatible time string like `\"1 hour\"`, `\"30 mins\"`, or `\"2.5d\"`,\n * or a `Date` object.\n *\n * {@link https://npm.im/ms}\n */\n timeout?: number | string | Date;\n };\n\n/**\n * A set of parameters given to a `sendSignal` call.\n */\ntype SendSignalOpts = {\n /**\n * The signal to send.\n */\n signal: string;\n\n /**\n * The data to send with the signal.\n */\n data?: unknown;\n};\n\n/**\n * A set of parameters given to a `waitForSignal` call.\n */\ntype WaitForSignalOpts = {\n /**\n * The signal to wait for.\n */\n signal: string;\n\n /**\n * The step function will wait for the signal for a maximum of this time, at\n * which point the signal will be returned as `null` instead of any signal\n * data.\n *\n * The time to wait can be specified using a `number` of milliseconds, an\n * `ms`-compatible time string like `\"1 hour\"`, `\"30 mins\"`, or `\"2.5d\"`, or\n * a `Date` object.\n *\n * {@link https://npm.im/ms}\n */\n timeout: number | string | Date;\n\n /**\n * When this `step.waitForSignal()` call is made, choose whether an existing\n * wait for the same signal should be replaced, or whether this run should\n * fail.\n *\n * `\"replace\"` will replace any existing wait with this one, and the existing\n * wait will remain pending until it reaches its timeout.\n *\n * `\"fail\"` will cause this run to fail if there is already a wait for the\n * same signal.\n */\n onConflict: \"replace\" | \"fail\";\n};\n\n/**\n * Computes the return type for `waitForEvent` based on the options provided.\n *\n * Handles three cases:\n * 1. `event: EventType<TName, TSchema>` - extracts name and data from EventType\n * 2. `event: string` with `schema` - uses string as name and schema for data\n * 3. `event: string` without schema - uses string as name with untyped data\n */\ntype WaitForEventResult<TOpts> =\n // Case 1: event is an EventType with a schema\n TOpts extends {\n event: EventType<\n infer TName extends string,\n StandardSchemaV1<infer TData extends Record<string, unknown>>\n >;\n }\n ? { name: TName; data: TData; id: string; ts: number; v?: string } | null\n : // Case 2: event is an EventType without a schema\n TOpts extends {\n event: EventType<infer TName extends string, undefined>;\n }\n ? {\n name: TName;\n // biome-ignore lint/suspicious/noExplicitAny: fallback for untyped events\n data: Record<string, any>;\n id: string;\n ts: number;\n v?: string;\n } | null\n : // Case 3: event is a string with schema (spread EventType)\n TOpts extends {\n event: infer TName extends string;\n schema: StandardSchemaV1<\n infer TData extends Record<string, unknown>\n >;\n }\n ? {\n name: TName;\n data: TData;\n id: string;\n ts: number;\n v?: string;\n } | null\n : // Case 4: event is just a string\n TOpts extends { event: infer TName extends string }\n ? {\n name: TName;\n // biome-ignore lint/suspicious/noExplicitAny: fallback for untyped events\n data: Record<string, any>;\n id: string;\n ts: number;\n v?: string;\n } | null\n : EventPayload | null;\n\n/**\n * Options for `step.ai.infer()`.\n */\ntype AiInferOpts<TModel extends AiAdapter> = {\n /**\n * The model to use for the inference. Create a model by importing from\n * `\"inngest\"` or by using `step.ai.models.*`.\n *\n * @example Import `openai()`\n * ```ts\n * import { openai } from \"inngest\";\n *\n * const model = openai({ model: \"gpt-4\" });\n * ```\n *\n * @example Use a model from `step.ai.models`\n * ```ts\n * async ({ step }) => {\n * const model = step.ai.models.openai({ model: \"gpt-4\" });\n * }\n * ```\n */\n model: TModel;\n\n /**\n * The input to pass to the model.\n */\n body: AiAdapter.Input<TModel>;\n};\n"],"mappings":";;;;;;;;;;;;;;;AAsMA,MAAa,kBAAkB,YAA0C;AACvE,KAAI,OAAO,YAAY,SACrB,QAAO,EAAE,IAAI,SAAS;AAGxB,QAAO;;;;;AAMT,MAAa,uBAAuB;AAwBpC,MAAa,mBAIX,QACA,WACA,gBACG;;;;;;;CAQH,MAAM,cAUJ,SACA,SACM;EACN,MAAMA,kBAAgC,aAAa,GAAG,SAAS;GAC7D,MAAM,KAAK,QAAQ,aAAa,GAAG,KAAK;GAExC,MAAM,SAASC,6BAAiB,EAAE;AAElC,OAAI,QAAQ,uBACV,OAAM,IAAIC,4CACR,mJAGD;GAIH,MAAM,eAAe,YAAY,gBAAgB,QAAQ;AAEzD,OAAI,aACF,IAAG,OAAO;IAAE,GAAG,GAAG;IAAM;IAAc;GAIxC,MAAM,oBAAoB,QAAQ;AAClC,OAAI,kBACF,IAAG,OAAO;IAAE,GAAG,GAAG;IAAM,GAAG;IAAmB;GAIhD,MAAM,UAAU,QAAQ;AACxB,OAAI,QACF,SAAQ,QAAQ;AAGlB,UAAO;;AAGT,UAAQ,OAAO,GAAG,SAA0C;AAE1D,UAAO,YAAY;IADA;IACoB,SAAS;IAAgB;IAAM,CAAC;;;;;;;CAQ3E,MAAM,iBAKJ,SACG;AACH,SAAO,YAgCJ,EAAE,IAAI,QAAQ,KAAK,GAAG,UAAU;GAC/B,MAAMC,OAAyB;IAC7B,GAAI,MAAM,SAAS,EAAE,OAAO,GAAG,EAAE;IACjC,GAAI,OAAO,EAAE,MAAM,GAAG,EAAE;IACzB;AAED,UAAO;IACL;IACA,MAAMC,uBAAS;IACf,IAAIC,yBAAW;IACf,MAAM;IACN,aAAa,QAAQ;IACrB,GAAI,OAAO,KAAK,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,EAAE;IAC5C,UAAU,EAAE,IAAI;IACjB;KAEH,EACE,KAAK,GAAG,IAAI,IAAI,GAAG,UAAU,GAAG,GAAG,MAAM,EAC1C,CACF;;;;;;CAOH,MAAM,6BACJ,eACA,YACG;AACH,MAAI,CAAC,OAAO,+BACV,OAAM,IAAI,MACR,qIACD;EAEH,MAAM,eAAe,SACnB,0BAA0B,eAAe,KAAK;AAEhD,MAAI,CAAC,QACH,WAAU,IAAIC,gDAAwB,OAAO,CAAC,KAAK;AAGrD,SAAO;GACL,MAAM,UAAmB,YAAY,QAAQ,IAAI,MAAM,CAAC;GACxD,OAAO,QAAgB,UACrB,YAAY,QAAQ,KAAK,QAAQ,MAAM,CAAC;GAC1C,UAAU,iBACR,YAAY,QAAQ,QAAQ,aAAa,CAAC;GAC5C,OAAO,WAAmB,YAAY,QAAQ,KAAK,OAAO,CAAC;GAC3D,QAAQ,OACN,QACA,OAAO,cACW;AAClB,UAAM,MAAM,IAAI,eAAe,YAAY;AACzC,WAAM,QAAQ,OAAO,QAAQ,KAAK;MAClC;;GAGJ,IAAI,OACF,OACkB;AAClB,UAAM,MAAM,IAAI,eAAe,YAAY;AACzC,WAAM,GAAG,QAAQ;MACjB;;GAEL;;;;;;;;CASH,MAAM,QAAQ;EA2BZ,WAAW,YAMR,EAAE,IAAI,WAAW;AAChB,UAAO;IACL;IACA,MAAMF,uBAAS;IACf,IAAIC,yBAAW;IACf,MAAM;IACN,aAAa,QAAQ;IACrB,MAAM,EACJ,MAAM,kBACP;IACD,UAAU,EAAE,IAAI;IACjB;KAEH,EACE,KAAK,MAAM,cAAc,YAAY;GACnC,MAAM,KAAK,UAAU,WAAW;AAChC,UAAO,OAAO,SAAS;IACrB;IACA,SAAS,UAAU,WAAW;IAC9B,cAAc,GAAG,KAAK,cAAc,EAAE;IACtC;IACD,CAAC;KAEL,CACF;EASD,eAAe,YAKZ,EAAE,IAAI,QAAQ,SAAS;AAGxB,UAAO;IACL;IACA,MAAMD,uBAAS;IACf,IAAIC,yBAAW;IACf,MAAM,KAAK;IACX,aAAa,QAAQ;IACrB,MAAM;KACJ,QAAQ,KAAK;KACb,SAASE,wBAAQ,KAAK,QAAQ;KAC9B,UAAU,KAAK;KAChB;IACD,UAAU,EAAE,IAAI;IACjB;IACD;EAUF,UAAU,EAOR,SAAS,YAON,EAAE,IAAI,WAAW;AAChB,UAAO;IACL;IACA,MAAMH,uBAAS;IACf,IAAIC,yBAAW;IACf,aAAa,QAAQ;IACrB,MAAM,EACJ,MAAM,yBACP;IACD,UAAU,EAAE,IAAI;IACjB;KAEH,EACE,IAAI,OAAO,KAAK,cAAc,UAAU,SAAS;GAC/C,MAAM,cAAc,SAAS;AAC7B,OAAI,eAAe,YAAY,eAAe,YAAY,QAGxD;SADE,MAAM,YAAY,OAAO,aAAa,SAAS,KAAK,EAC3C,OACT,OAAM,IAAI,MACR,uCAAuC,SAAS,MAAM,GACvD;;GAIL,MAAM,MAAM,MAAM,OAAO,cAAc,QACrC;IACE,QAAQ,CAAC,SAAS,MAAM;IACxB,SAAS,SAAS;IAClB,OAAO,IAAI;IACZ,EACD,KACD;AAED,OAAI,CAAC,IAAI,GACP,OAAM,IAAI,MACR,kCAAkC,IAAI,OAAO,SAAS,kBACvD;AAGH,UAAO;KAEV,CACF,EACF;EAKD,YAAY,YAGT,EAAE,IAAI,QAAQ,SAAS;AACtB,UAAO;IACL;IACA,MAAMD,uBAAS;IACf,IAAIC,yBAAW;IACf,MAAM;IACN,aAAa,QAAQ;IACrB,MAAM;KACJ,MAAM;KACN,QAAQ,KAAK;KACd;IACD,UAAU,EAAE,IAAI;IACjB;KAEH,EACE,KAAK,MAAM,cAAc,SAAS;AAChC,UAAO,OAAO,eAAe;IAC3B,QAAQ,KAAK;IACb,MAAM,KAAK;IACX,SAAS,UAAU,WAAW;IAC/B,CAAC;KAEL,CACF;EAWD,cAAc,YA8BV,EAAE,IAAI,QAKN,SACG;GACH,MAAMG,YAA8C,EAClD,SAASD,wBAAQ,OAAO,SAAS,WAAW,OAAO,KAAK,QAAQ,EACjE;AAED,OAAI,OAAO,SAAS,UAClB;QAAI,MAAM,MACR,WAAU,KAAK,SAAS,KAAK,MAAM,YAAY,KAAK;aAC3C,MAAM,GACf,WAAU,KAAK,KAAK;;GAKxB,MAAM,YACJ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK,MAAM;AAE3D,UAAO;IACL;IACA,MAAMH,uBAAS;IACf,IAAIC,yBAAW;IACf,MAAM;IACN,MAAM;IACN,aAAa,QAAQ;IACrB,UAAU,EAAE,IAAI;IACjB;IAEJ;EAcD,KAAK,eAAe;EAKpB,IAAI;GAOF,OAAO,YAKJ,EAAE,IAAI,QAAQ,YAAY;IAE3B,MAAM,EAAE,OAAO,MAAM,GAAG,SAAS;IAEjC,MAAM,YAAY,EAAE,GAAG,OAAO;AAG9B,YAAQ,MAAM,SAAS,WAAW,QAAQ,KAAK;AAE/C,WAAO;KACL;KACA,MAAMD,uBAAS;KACf,IAAIC,yBAAW;KACf,aAAa,QAAQ;KACrB,MAAM;MACJ,MAAM;MACN,KAAK,UAAU;MACf,SAAS,UAAU;MACnB,UAAU,UAAU;MACpB,QAAQ,UAAU;MAElB;MAEA,GAAG;MACJ;KACD,UAAU,EAAE,IAAI;KACjB;KACD;GAUF,MAAM,cAAc,eAAe;GAKnC,QAAQ,EACN,GAAGI,qBACJ;GACF;EAYD,OAAO,YASJ,EAAE,IAAI,QAAQ,SAAS;;;;;GAKxB,MAAMC,YAAoBH,4DACI,KAAK,GAC7B,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC,GACnC,KACN;AAED,UAAO;IACL;IACA,MAAMH,uBAAS;IACf,IAAIC,yBAAW;IACf,MAAM;IACN,aAAa,QAAQ;IACrB,UAAU,EAAE,IAAI;IACjB;IACD;EAQF,YAAY,YAST,EAAE,IAAI,QAAQ,SAAS;AACxB,OAAI;IACF,MAAM,oCAA4B,KAAK;;;;;AAMvC,WAAO;KACL;KACA,MAAMD,uBAAS;KACf,IAAIC,yBAAW;KACf,MAAM;KACN,aAAa,QAAQ;KACrB,UAAU,EAAE,IAAI;KACjB;YACM,KAAK;;;;;AAKZ,WAAOM,sCAAsB,KAC3B,EAAE,KAAK,EACP,oGACD;AAED,UAAM,IAAI,MACR,4GACE,OAEH;;IAEH;EAOF,QAAQ,YAWL,EAAE,IAAI,QAAQ,eAAe;GAG9B,MAAM,aAAa,oBAAoB,OAAO,EAC5C,SAASC,SAAE,MAAM;IAACA,SAAE,QAAQ;IAAEA,SAAE,QAAQ;IAAEA,SAAE,MAAM;IAAC,CAAC,CAAC,UAAU,EAChE,CAAC;GAEF,MAAM,eAAe,WAClB,OAAO;IACN,OAAOA,SAAE,QAAQ,aAAa,CAAC,UAAU,CAAC,QAAQ,aAAa;IAC/D,UAAUA,SAAE,WAAWC,wCAAgB;IACxC,CAAC,CACD,GACC,WAAW,OAAO;IAChB,OAAOD,SAAE,QAAQ,cAAc,CAAC,UAAU,CAAC,QAAQ,cAAc;IACjE,UAAUA,SAAE,WAAWE,0DAAyB;IACjD,CAAC,CACH,CACA,UAAU,WAAW;AAExB,OAAI,CAAC,aAAa,QAChB,OAAM,IAAI,MACR,wGACD;GAGH,MAAM,EAAE,OAAO,UAAU,IAAI,MAAM,GAAG,YAAY,aAAa;GAE/D,MAAMC,OAIF;IACF,SANc;KAAE;KAAM;KAAG;IAOzB,aAAa;IACb,SAAS,OAAO,YAAY,cAAc,SAAYR,wBAAQ,QAAQ;IACvE;AAED,WAAQ,OAAR;IACE,KAAK;AACH,UAAK,cAAc,GAAG,GAAG,GAAG,UAAU,GAAG;AACzC;IAEF,KAAK;AACH,UAAK,cAAc,CAAC,GAAG,KAAK,SAAS,OAAO,IAAI,GAAG,KAAK,WAAW,CAChE,OAAO,QAAQ,CACf,KAAK,IAAI;AACZ;;AAGJ,UAAO;IACL;IACA,MAAMH,uBAAS;IACf,IAAIC,yBAAW;IACf,aAAa,QAAQ;IACrB;IACA,UAAU,EAAE,IAAI;IACjB;IACD;EASF,OAAOW;EACR;AAID,CAAC,MAA2CC,2CAC1C,kBACqB,0BAA0B,cAAc;AAI/D,CAAC,MAAyC,2BACxC,cAAc,mBAAmB;AAGnC,CAAC,MAAuC,iBAAiB,YACtD,EAAE,IAAI,QAAQ,OAAO,SAAS;EAC7B,MAAM,MAAM,iBAAiB,UAAU,MAAM,MAAM,MAAM,UAAU;EAEnE,MAAMC,UAAkC,EAAE;AAC1C,MAAI,iBAAiB,QACnB,OAAM,QAAQ,SAAS,OAAO,QAAQ;AACpC,WAAQ,OAAO;IACf;WACO,MAAM,QAEf,CADU,IAAI,QAAQ,KAAK,QAAQ,CACjC,SAAS,OAAO,QAAQ;AACxB,WAAQ,OAAO;IACf;AAGJ,SAAO;GACL;GACA,MAAMd,uBAAS;GACf,IAAIC,yBAAW;GACf,aAAa,QAAQ;GACrB,MAAM;IACJ;IACA,QAAQ,MAAM,UAAU;IACxB;IACA,MAAM,MAAM;IACb;GACD,UAAU,EAAE,IAAI;GACjB;GAEJ;AAED,QAAO;;AAST,MAAa,gBAAgB,OAAO,IAAI,uBAAuB;AAiB/D,MAAa,0BAA0B,OAAO,IAAI,2BAA2B;;;;;;;;;;;;AAoB7E,MAAac,OAAyB;CAEpC,OAAO;CACP,IAAI;EACF,QAAQ,GAAG,SACT,wBAAwB,CAAC,MAAM,UAAU,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;EACnE,OAAO,GAAG,SACR,wBAAwB,CAAC,MAAM,UAAU,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;EAClE,QAAQ,EACN,GAAGV,qBACJ;EACF;CACD,SAAS,GAAG,SACV,wBAAwB,CAAC,MAAM,UAAU,MAAM,OAAO,GAAG,KAAK,CAAC;CACjE,MAAM,GAAG,SACP,wBAAwB,CAAC,MAAM,UAAU,MAAM,IAAI,GAAG,KAAK,CAAC;CAC9D,YAAY,GAAG,SACb,wBAAwB,CAAC,MAAM,UAAU,MAAM,UAAU,GAAG,KAAK,CAAC;CACpE,aAAa,GAAG,SACd,wBAAwB,CAAC,MAAM,UAAU,MAAM,WAAW,GAAG,KAAK,CAAC;CACrE,QAAQ,GAAG,SACT,wBAAwB,CAAC,MAAM,UAAU,MAAM,MAAM,GAAG,KAAK,CAAC;CAChE,aAAa,GAAG,SACd,wBAAwB,CAAC,MAAM,UAAU,MAAM,WAAW,GAAG,KAAK,CAAC;CACrE,eAAe,GAAG,SAChB,wBAAwB,CAAC,MAAM,UAAU,MAAM,aAAa,GAAG,KAAK,CAAC;CACvE,gBAAgB,GAAG,SACjB,wBAAwB,CAAC,MAAM,UAAU,MAAM,cAAc,GAAG,KAAK,CAAC;CACxE,UAAU,EACR,UAAU,GAAG,SACX,wBAAwB,CAAC,MAAM,UAAU,MAAM,SAAS,QAAQ,GAAG,KAAK,CAAC,EAC5E;CACF;;;;;;;;AASD,MAAM,yBAAyB,YAAuC;CACpE,MAAM,MAAM,MAAMW,yBAAa;AAC/B,KAAI,CAAC,IACH,OAAM,IAAI,MACR,yFACD;AAGH,KAAI,CAAC,IAAI,IACP,OAAM,IAAI,MACR,yHACD;AAGH,KAAI,CAAC,IAAI,UACP,OAAM,IAAI,MACR,mGACD;AAKH,QAAO,IAAI,UAAU,IAAI;;AAG3B,MAAM,0BAA0B,YAAiC;CAC/D,MAAM,MAAM,MAAMA,yBAAa;AAC/B,KAAI,CAAC,IACH,OAAM,IAAI,MACR,0FACD;AAGH,KAAI,CAAC,IAAI,UACP,OAAM,IAAI,MACR,oGACD;AAGH,QAAO,IAAI,UAAU,IAAI;;;;;;;AAQ3B,MAAaC,QAAoB;CAC/B,WAAW,GAAG,SACZ,yBAAyB,CAAC,MAAM,UAAU,MAAM,SAAS,GAAG,KAAK,CAAC;CACpE,aAAa,GAAG,SACd,yBAAyB,CAAC,MAAM,UAAU,MAAM,WAAW,GAAG,KAAK,CAAC;CACvE;;;;;AAMD,MAAa,sBAAsBT,SAAE,OAAO;CAC1C,MAAMA,SAAE,OAAOA,SAAE,KAAK,CAAC,CAAC,UAAU;CAClC,GAAGA,SAAE,QAAQ,CAAC,UAAU;CACzB,CAAC"}