eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
237 lines • 8.15 kB
TypeScript
import type { StringValue } from './_ms.js';
import type { Run } from './runtime/run.js';
import type { Serializable } from './schemas.js';
/**
* An object that can be awaited to receive a value.
*/
interface Thenable<T> {
then: Promise<T>['then'];
}
/**
* A `Request` that can be responded to within a workflow
* step function by calling the `respondWith()` method.
*/
export interface RequestWithResponse extends Request {
respondWith: (response: Response) => Promise<void>;
}
/**
* A hook that can be awaited and/or iterated over to receive
* a value within a workflow from an external system.
*
* Hooks implement the TC39 Explicit Resource Management proposal,
* allowing them to be used with the `using` keyword for automatic disposal.
*/
export interface Hook<T = any> extends AsyncIterable<T>, Thenable<T> {
/**
* The token used to identify this hook.
*/
token: string;
/**
* Returns the {@link Run} already using this token, or `null` when this Hook
* registers successfully.
*
* Calling `createHook()` alone does not register the hook — registration
* only happens when the workflow suspends. Awaiting `getConflict()`
* suspends the workflow to commit the hook registration without waiting for
* payload data.
*
* If it returns a run, this Hook was not created. Awaiting the Hook instead
* rejects with `HookConflictError`.
*
* @example
* ```ts
* using hook = createHook({ token: `order:${orderId}` });
* const conflict = await hook.getConflict();
* if (conflict) {
* // another run already owns this token
* return { status: 'duplicate', runId: conflict.runId };
* }
* // this Hook registered without waiting for payload data
* ```
*/
getConflict(): Promise<Run<unknown> | null>;
/**
* Disposes the hook, releasing its token for reuse by other workflows.
*
* After calling `dispose()`, the hook will no longer receive any events.
* This is useful when you want to explicitly release a hook token before
* the workflow completes, allowing another workflow to register a hook
* with the same token.
*
* @example
* ```ts
* const hook = createHook<{ message: string }>({ token: 'my-token' });
*
* for await (const payload of hook) {
* if (payload.message === 'done') {
* hook.dispose(); // Release the token early
* break;
* }
* }
* ```
*/
dispose(): void;
/**
* Implements the TC39 Explicit Resource Management proposal.
* Called automatically when using the `using` keyword.
*
* @example
* ```ts
* {
* using hook = createHook<{ message: string }>({ token: 'my-token' });
* const payload = await hook;
* // hook is automatically disposed when the block exits
* }
* ```
*/
[Symbol.dispose](): void;
}
/**
* A webhook that can be used to suspend and resume the workflow run
* upon receiving an HTTP request to the specified URL.
*
* @see {@link createWebhook}
* @see https://developer.mozilla.org/en-US/docs/Web/API/Request
*/
export interface Webhook<T extends Request> extends Hook<T> {
/**
* The URL that external systems can call to send data to the workflow.
*/
url: string;
}
export interface HookOptions {
/**
* Unique token that is used to associate with the hook.
*
* When specifying an explicit token, the token should be constructed
* with information that the dispatching side can reliably reconstruct
* the token with the information it has available.
*
* Deterministic tokens are intended for use with `createHook()` and
* server-side `resumeHook()` only. For webhooks (`createWebhook()`),
* tokens are always randomly generated to prevent unauthorized access
* to the public webhook endpoint.
*
* If provided, the token must be a non-empty string; passing an empty
* string throws. If not provided (or `undefined`), a randomly generated
* token will be assigned.
*
* @example
*
* ```ts
* // Explicit token for a Slack bot (one workflow run per channel)
* const hook = createHook<SlackMessage>({
* token: `slack_webhook:${channelId}`,
* });
* ```
*/
token?: string;
/**
* **Experimental.** Keeps this Hook's token unavailable for at least the
* configured time after `createHook()` runs.
*
* Accepts the same values as `sleep()`: a duration string, a number of
* milliseconds, or an absolute `Date`. Relative durations start when
* `createHook()` runs, not when the workflow ends.
*
* The Hook remains active until the workflow ends, even if the configured
* time passes first. Another Hook can use the token only after both the run
* has ended and the configured time has passed.
* After the run ends, the Hook can still be found with `getHookByToken()`
* until retention ends, but it cannot be resumed.
*
* Calling `dispose()` (including through `using`) releases the token
* immediately.
*
* `createHook()` throws if the configured World does not support this
* experimental option.
*
* @example
*
* ```ts
* const hook = createHook({
* token: `order:${orderId}`,
* experimental_minRetention: '30d',
* });
* ```
*/
experimental_minRetention?: StringValue | Date | number;
/**
* Additional user-defined data to include with the hook payload.
*
* @example
*
* ```ts
* const hook = createHook<{ name: string }>({
* metadata: {
* type: "cat",
* color: "orange",
* },
* });
* ```
*/
metadata?: Serializable;
/**
* Whether this hook can be resumed via the public webhook endpoint.
*
* When `true`, the hook can be triggered by sending an HTTP request to the
* public workflow webhook URL. This is automatically set when using
* `createWebhook()`.
*
* When `false` (the default), the hook can only be resumed server-side
* via `resumeHook()`.
*
* @default false
*/
isWebhook?: boolean;
}
export interface WebhookOptions extends Omit<HookOptions, 'token' | 'isWebhook' | 'experimental_minRetention'> {
/**
* If set to a `Response` object, the webhook will automatically
* respond with the specified response.
*
* If set to `"manual"`, each individual request will need to
* be responded to manually from within the workflow by calling the
* `respondWith()` method.
*
* If not set then the webhook will automatically respond with
* a `202 Accepted` response.
*/
respondWith?: Response | 'manual';
}
/**
* Creates a {@link Hook} that can be used to suspend and resume the workflow run with a payload.
*
* Hooks allow external systems to send arbitrary serializable data into a workflow.
*
* @param options - Configuration options for the hook.
* @returns A `Hook` that can be awaited to receive one or more payloads.
*
* @example
*
* ```ts
* export async function workflowWithHook() {
* "use workflow";
*
* const hook = createHook<{ message: string }>();
* console.log('Hook token:', hook.token);
*
* const payload = await hook;
* console.log('Received:', payload.message);
* }
* ```
*/
export declare function createHook<T = any>(options?: HookOptions): Hook<T>;
/**
* Creates a {@link Webhook} that can be used to suspend and resume the workflow
* run upon receiving an HTTP request to the specified URL.
*
* Webhooks will result in a {@link https://developer.mozilla.org/en-US/docs/Web/API/Request | Request} object
* that can be interacted with in workflow functions.
*/
export declare function createWebhook(options: WebhookOptions & {
respondWith: 'manual';
}): Webhook<RequestWithResponse>;
export declare function createWebhook(options?: WebhookOptions): Webhook<Request>;
export {};
//# sourceMappingURL=create-hook.d.ts.map