import type { ContextOperationRequest } from '../context.ts'; import type { AttributeFilter, AttributeFilterScalarValue, ListFilter, PaginatedResult, ScheduleFilter, ScheduleState, ScheduleSummary, SearchAttributeValue, WorkflowState, WorkflowSummary } from '../types.ts'; /** * Durable execution-claim record stored at {@link KEYS.teardownOwed} for a workflow * that owes an engine-driven finalizer run (issue #446 Phase 2). A holder fenced-CAS's * it from `'owed'` to `'running'` before invoking the finalizer, then back to `'owed'` * (with `attempts` bumped) on a retryable failure, or deletes it on success/dead-letter. * * Liveness is decided by TIME, not by an in-memory set or a lease epoch: a `'running'` * claim is reclaimable once `claimedAt` is older than the stale threshold (the * finalizer's per-attempt timeout plus a margin — see `teardownStaleThresholdMs`). This * makes crash recovery an ordinary stale-claim retry with no special re-hydration: a * fresh process simply re-fires the surviving timer and reclaims the stale `'running'` * marker. The cost is that a finalizer running past the threshold may be re-driven * concurrently, which is why workflow finalizers must be idempotent. * * - `status`: `'owed'` until claimed, `'running'` while a holder is executing it. * - `attempts`: count of finalizer attempts so far (`0` until the first claim). * - `token`: ties the marker to its `wf-teardown:` timer so a stale timer for a * re-armed (different-token) claim cannot drive it. * - `claimedAt`: engine clock at the `owed → running` transition; `undefined` while * `'owed'`. Drives the time-based reclaim of an abandoned `'running'` claim. */ export type TeardownClaim = { status: 'owed' | 'running'; attempts: number; token: string; claimedAt?: number; }; /** Build the durable teardown timer id from its claim token (parsed by {@link parseTeardownTimerId}). */ export declare function createTeardownTimerId(token: string): string; /** Recover the claim token from a teardown timer id, or `null` when the id is malformed. */ export declare function parseTeardownTimerId(timerId: string): string | null; /** * Runtime type guard for a decoded {@link TeardownClaim} read back from storage. * * `attempts` must be a non-negative SAFE INTEGER and `claimedAt` (when present) a * finite non-negative number — not merely `typeof === 'number'`. A persisted `NaN` * or `Infinity` would otherwise drive the marker forever: `attempt >= MAX_TEARDOWN_ATTEMPTS` * is always false for `NaN` (never dead-letters) and `now - claimedAt >= threshold` never * holds for a non-finite `claimedAt` (never reclaims a stale running claim). Rejecting them * here routes a corrupt-but-claim-shaped marker through the clear path instead. `claimedAt` * is checked with `isFinite` rather than `isSafeInteger` because `getNow()` may return a * fractional timestamp. */ export declare function isTeardownClaim(value: unknown): value is TeardownClaim; type PaginationFilter = { limit?: number; offset?: number; }; /** * Build the unified `#workflowFeedListeners` map key. Uses `\0` as * the separator: workflow ID validation (`assertValidWorkflowId`) * rejects control characters, so no legal workflow ID can contain * NUL, and the selector is a fixed two-member union, so no legal * input can collide. */ export declare function workflowFeedListenerKey(workflowId: string, selector: 'events' | 'tokens'): string; /** * Safely cast a `Function` stored on a ContextOperationRequest * to a callable signature. We trust the Context layer to populate * `fn` with the correct reference—the Engine merely invokes it. */ export declare function callActivityFunction(fn: Function, input: unknown, context?: unknown): unknown; export declare function callMemoFunction(fn: Function): unknown; export declare function summarizeTimelineValue(value: unknown): string; export declare function getTimelineOperationLabel(operation: ContextOperationRequest): string; export declare function getTimelineReviewArtifactType(artifact: unknown): unknown; export declare function getTimelineBasicInputSummary(operation: ContextOperationRequest): string; export declare function getTimelineInputSummary(operation: ContextOperationRequest): string; export declare function sanitizeCheckpointLocals(locals: unknown): Record; export declare function sanitizeCheckpointSearchAttributes(searchAttributes: unknown): Record; export declare function sanitizeCheckpointState(checkpoint: import('../types.ts').CheckpointState): import('../types.ts').CheckpointState; export declare function sanitizeWorkflowEventPayload(payload: unknown): Record; export declare function sanitizeTimelineSummary(summary: string | undefined): string | undefined; export declare function normalizeForkStep(fromStep: number): number; export declare function encodeWorkflowStartHeaders(headers: Map): Uint8Array; export declare function decodeWorkflowStartHeaders(bytes: Uint8Array): Map; export declare function selectPersistedWorkflowStartHeaders(headers: Map | undefined): Map | undefined; export declare function intersectIdentifierSets(idSets: Set[]): Set | null; export declare function listFilterHasAttributeFilters(filter: ListFilter | undefined): boolean; export declare function decodeSearchAttributeRecord(attributeBytes: Uint8Array | null): Record | null; export declare function attributeFilterExactValues(filter: AttributeFilter): readonly AttributeFilterScalarValue[] | null; export declare function matchesListFilter(state: WorkflowState, filter: ListFilter | undefined, constrainedIds: Set | null, normalizedTagFilters: readonly string[] | undefined, searchAttributes?: Readonly> | null): boolean; /** * Slice an in-memory list of {@link WorkflowSummary} into a {@link PaginatedResult}. * * Important note on `total` semantics: the returned `total` reflects the number * of workflows that matched the supplied {@link ListFilter} (status, type, and * search attribute filters). It is **not** the absolute count of workflows in * storage. A UI computing "page 1 of N" from `total` will see the page count * for the active filter; the unfiltered population is intentionally not * surfaced through this response, since recovering it would require a separate * full scan that defeats the purpose of the filter fast path. */ export declare function paginateWorkflowSummaries(items: WorkflowSummary[], filter?: ListFilter): PaginatedResult; export declare function paginateItems(items: T[], filter: PaginationFilter | undefined): PaginatedResult; export declare function normalizeValueForEncodedComparison(value: unknown): unknown; export declare function encodedValuesEqual(left: unknown, right: unknown): boolean; export declare function matchesScheduleFilter(state: ScheduleState, filter: ScheduleFilter | undefined): boolean; export declare function paginateScheduleSummaries(items: ScheduleSummary[], filter?: ScheduleFilter): PaginatedResult; export declare function createScheduleTimerId(scheduleId: string): string; export declare function createTerminalCleanupTimerId(includeOutputArtifacts: boolean, terminalCleanupToken: string): string; export declare function parseTerminalCleanupTimerId(timerId: string): { includeOutputArtifacts: boolean; terminalCleanupToken: string; } | null; export declare function clearScheduleCurrentWorkflow(state: ScheduleState): ScheduleState; export {};