import { type ClientOperationName, type ClientOperationTypes, type ClientOperations } from '../cli/generated/operation-client.generated.ts'; import type { StoredStreamChunk } from '../core/context.ts'; import type { AttributeFilterKey, BulkCancelResult, BulkDeleteResult, BulkRetryFailedResult, BulkSignalResult, BulkTagResult, CoordinatedUpdateResult, ForkOptions, ListFilter, PaginatedResult, PurgeResult, QueryDefinition, RetentionOverview, ReviewListEntry, ReviewListFilter, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleSummary, ScheduleUpdateOptions, SearchAttributeValue, SignalDefinition, SignalDeliveryOptions, StartOrSignalSignal, SubmitReviewOptions, TypedListFilter, UpdateDefinition, WorkflowEvent, WorkflowInput, WorkflowOutput, WorkflowRegistry, WorkflowReplay, WorkflowState, WorkflowSummary, WorkflowTimelineEntry } from '../core/types.ts'; import type { WeftClientStorage } from './client-storage.ts'; import type { WorkflowEventTail } from './event-tail.ts'; import { type HttpClientOptions } from './http-request.ts'; import type { ClientHandle, ClientScheduleHandle, ClientStartOptions, ClientStartOrSignalOptions, UpdateResult, WeftClient, WeftClientActivity } from './interface.ts'; import type { KnownWorkflowName, UnknownNameWhenRegistryEmpty } from './workflow-name-typing.ts'; /** * Remote Weft client backed by HTTP requests. * * **Error handling** * * - **404 on GET → `null`:** When a GET request returns 404, the client * treats it as "resource not found" and resolves with `null` instead of * throwing `HttpClientError`. * - **400/422 in `submitCoordinatedUpdate` → error envelope:** A 400 or 422 * response from `submitCoordinatedUpdate` is translated into a * `CoordinatedUpdateResult` with an `error` field rather than throwing. * * **Connection resolution** * * With no `baseUrl`/`token`, the client resolves the server address and bearer * token through {@link resolveConnection}: explicit options, then `WEFT_ADDR`/ * `WEFT_TOKEN`, then the `~/.weft/config` profile, then `http://localhost:7233`. * The CLI-only run lockfile is not consulted. A caller-supplied * `headers.Authorization` always takes precedence over a resolved token. * * @example * ```ts * import { HttpClient } from '@lostgradient/weft'; * * // Explicit address and token. * const client = new HttpClient({ * baseUrl: 'http://localhost:3000', * headers: { Authorization: 'Bearer my-token' }, * }); * const handle = await client.start('greet', { name: 'Alice' }); * const result = await handle.result(); * void result; * * // Or resolve WEFT_ADDR / WEFT_TOKEN from the environment. * const envClient = new HttpClient(); * void envClient; * ``` */ export declare class HttpClient implements WeftClient { #private; /** @internal Exposed for handle access. */ readonly baseUrl: string; /** @internal Exposed for handle access. */ readonly headers: Record; /** Typed low-level accessor over JSON-RPC and generated ordinary REST bindings. */ readonly operations: ClientOperations; /** Raw storage administration over the byte-oriented REST bindings. */ readonly storage: WeftClientStorage; /** * Out-of-band ("async") activity completion over HTTP. POSTs to * `/v1/activities/{complete,fail}`; mirrors {@link LocalClient}'s `activity`. */ readonly activity: WeftClientActivity; constructor(options?: HttpClientOptions); call(name: Name, input: ClientOperationTypes[Name]['input']): Promise; start(type: TName, input: WorkflowInput, options?: ClientStartOptions): Promise>>; start(type: UnknownNameWhenRegistryEmpty, input: unknown, options?: ClientStartOptions): Promise; startOrSignal(type: TName, input: WorkflowInput, signal: StartOrSignalSignal, options?: ClientStartOrSignalOptions): Promise>>; startOrSignal(type: UnknownNameWhenRegistryEmpty, input: unknown, signal: StartOrSignalSignal, options?: ClientStartOrSignalOptions): Promise; schedule(type: TName, input: WorkflowInput, spec: string | ScheduleSpec, options?: ScheduleOptions): Promise; schedule(type: UnknownNameWhenRegistryEmpty, input: unknown, spec: string | ScheduleSpec, options?: ScheduleOptions): Promise; get(id: string): Promise; getHandle(id: string): Promise; getHandle(id: string): Promise> | null>; getSchedule(id: string): Promise; list(filter?: TypedListFilter): Promise>; listSchedules(filter?: ScheduleFilter): Promise>; cancel(id: string): Promise; suspend(id: string): Promise; pauseSchedule(id: string): Promise; resumeSchedule(id: string): Promise; cancelSchedule(id: string): Promise; updateSchedule(id: string, newSpec: string | ScheduleSpec, options?: ScheduleUpdateOptions): Promise; signal(id: string, name: SignalDefinition): Promise; signal(id: string, name: SignalDefinition, payload: TInput, options?: SignalDeliveryOptions): Promise; signal(id: string, name: string, payload?: unknown, options?: SignalDeliveryOptions): Promise; query(id: string, name: QueryDefinition): Promise; query(id: string, name: QueryDefinition, input: TInput): Promise; query(id: string, name: string, input?: unknown): Promise; update(id: string, name: UpdateDefinition, payload?: void, options?: { timeout?: number; }): Promise; update(id: string, name: UpdateDefinition, payload: TInput, options?: { timeout?: number; }): Promise; update(id: string, name: string, payload?: unknown, options?: { timeout?: number; }): Promise; resume(id: string): Promise; recoverAll(): Promise; timeout(id: string): Promise; getAttributes(id: string): Promise | null>; setAttributes(id: string, attributes: Record): Promise; addTags(id: string, ...tags: string[]): Promise; removeTags(id: string, ...tags: string[]): Promise; getEvents(id: string): Promise; /** * @internal Open a live event subscription over the `/watch` WebSocket * channel. Shared by {@link HttpHandle} (push-based `addEventListener`) and * {@link tail}. The subscription catches up from `getEvents` on every * (re)connect, so it covers events emitted before it connected. * * `bufferForIteration` defaults off for the callback-only `addEventListener` * path; {@link tail} sets it so the connect catch-up is buffered for the * async iterator instead of dropped. */ openEventSubscription(id: string, onEvent: (event: WorkflowEvent) => void, bufferForIteration?: boolean): WorkflowEventTail; tail(id: string): WorkflowEventTail; getTimeline(id: string): Promise; replayTo(id: string, step: number): Promise; listReviews(filter?: ReviewListFilter): Promise; submitReview(reviewId: string, options: SubmitReviewOptions): Promise; getStreamChunks(workflowId: string, key: string, options?: { after?: number; }): Promise; fork(id: string, options?: ForkOptions): Promise; getRetentionOverview(): Promise; purge(filter?: ListFilter): Promise; cancelAll(filter: ListFilter): Promise; retryFailedAll(filter: ListFilter): Promise; signalAll(filter: ListFilter, name: string, payload?: unknown): Promise; deleteAll(filter: ListFilter): Promise; tagAll(filter: ListFilter, tags: string[]): Promise; untagAll(filter: ListFilter, tags: string[]): Promise; submitCoordinatedUpdate(id: string, name: string, payload?: unknown, options?: { timeout?: number; idempotencyKey?: string; }): Promise; getUpdateResult(updateId: string): Promise; }