@flowy-agent-store/client 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,501 @@
1
+ import { AgentDetail, AgentRunInput, AgentSummary, CancelRunInput, ClientCapabilities, ClientInfo, ConnectorDetail, ConnectorProbeResult, ConnectorStatusView, ConnectorSummary, ContextUsage, ConversationCreateInput, ConversationEvent, ConversationMessage, ConversationMessagesPage, ConversationMessagesQuery, ConversationModelOptions, ConversationSendReceipt, ConversationUpdateInput, ConversationView, ImportDetail, ImportRequest, ImportResult, ImportSummary, InitializeResult, InstallRequest, InstallResult, InstallStatus, MarketplaceAddRequest, MarketplaceDetail, MarketplaceRefreshResult, MarketplaceRemoveResult, MarketplaceSummary, ModelSummary, OAuthStartResult, OAuthStatusView, RunEvent, RunEventsQuery, RunReceipt, RunResult, RunStatus, RunView, ServerNotification, SkillDetail, SkillSummary, SteerRunInput, StoreInstallResult, StoreList, TeamDetail, TeamSummary, WorkspaceRevokeResult, WorkspaceView } from "@flowy-agent-store/protocol";
2
+ //#region src/transport.d.ts
3
+ export type NotificationListener = (notification: ServerNotification) => void;
4
+ /**
5
+ * True for loopback-only URLs (`127.0.0.0/8`, `::1`, `localhost`).
6
+ * SDK spawn contract (docs/agent-store/12-sdk-packaging.md P0-4): an SDK
7
+ * must only speak the local-trusted mode over loopback; anything else is
8
+ * rejected before connecting.
9
+ */
10
+ export declare function isLoopbackUrl(raw: string): boolean;
11
+ /**
12
+ * Transport abstraction (docs/agent-store/07-typescript-sdk.md §2.3).
13
+ * A transport only frames JSON-RPC over some channel; the
14
+ * initialize → initialized → ready lifecycle lives in `AppServerClient`,
15
+ * so business code never knows whether it runs over WebSocket (browser),
16
+ * stdio (Node/CLI, future) or a one-shot HTTP binding.
17
+ */
18
+ export interface Transport {
19
+ connect(): Promise<void>;
20
+ request<T>(method: string, params: unknown): Promise<T>;
21
+ notify(method: string, params: unknown): void;
22
+ onNotification(listener: NotificationListener): () => void;
23
+ close(): void;
24
+ }
25
+ export interface TransportOptions {
26
+ requestTimeoutMs?: number;
27
+ token?: string;
28
+ }
29
+ export declare class WebSocketTransport implements Transport {
30
+ private socket;
31
+ private nextId;
32
+ private pending;
33
+ private listeners;
34
+ private connectResolvers;
35
+ private connectRejecters;
36
+ private closedByCaller;
37
+ readonly requestTimeoutMs: number;
38
+ readonly url: string;
39
+ readonly token?: string;
40
+ constructor(url: string, options?: TransportOptions);
41
+ get connected(): boolean;
42
+ connect(): Promise<void>;
43
+ request<T>(method: string, params: unknown): Promise<T>;
44
+ notify(method: string, params: unknown): void;
45
+ onNotification(listener: NotificationListener): () => void;
46
+ close(): void;
47
+ private requireSocket;
48
+ private handleMessage;
49
+ private failAllPending;
50
+ }
51
+ //#endregion
52
+ //#region src/agents.d.ts
53
+ export declare class AgentClient {
54
+ private readonly transport;
55
+ constructor(transport: Transport);
56
+ /** List Agent Store AgentDefinitions (public summaries only). */
57
+ list(): Promise<AgentSummary[]>;
58
+ /** Fetch one AgentDefinition; raw prompts never cross the wire. */
59
+ get(agentId: string): Promise<AgentDetail>;
60
+ }
61
+ //#endregion
62
+ //#region src/conversations.d.ts
63
+ export declare class ConversationClient {
64
+ private readonly transport;
65
+ constructor(transport: Transport);
66
+ create(input: ConversationCreateInput): Promise<ConversationView>;
67
+ update(conversationId: string, input: ConversationUpdateInput): Promise<ConversationView>;
68
+ modelOptions(): Promise<ConversationModelOptions>;
69
+ list(limit?: number): Promise<ConversationView[]>;
70
+ get(conversationId: string): Promise<ConversationView>;
71
+ messages(query: ConversationMessagesQuery): Promise<ConversationMessagesPage>;
72
+ send(conversationId: string, content: string, idempotencyKey: string): Promise<ConversationSendReceipt>;
73
+ cancel(conversationId: string): Promise<ConversationView>;
74
+ delete(conversationId: string): Promise<{
75
+ conversation_id: string;
76
+ deleted: boolean;
77
+ }>;
78
+ follow(conversationId: string): Promise<ConversationSubscription>;
79
+ }
80
+ export type ConversationEventListener = (event: ConversationEvent) => void;
81
+ export type ConversationResyncListener = (reason: string) => void;
82
+ export declare class ConversationSubscription {
83
+ private readonly transport;
84
+ readonly conversationId: string;
85
+ private events;
86
+ private resyncs;
87
+ private closed;
88
+ private lastSeenSequence;
89
+ private removeListener;
90
+ constructor(transport: Transport, conversationId: string);
91
+ get lastSequence(): number;
92
+ onEvent(listener: ConversationEventListener): () => void;
93
+ onResync(listener: ConversationResyncListener): () => void;
94
+ close(): Promise<void>;
95
+ private dispatch;
96
+ }
97
+ //#endregion
98
+ //#region src/connectors.d.ts
99
+ export declare class ConnectorClient {
100
+ private readonly transport;
101
+ constructor(transport: Transport);
102
+ /** List the Agent Store Connector catalog (public summaries only). */
103
+ list(): Promise<ConnectorSummary[]>;
104
+ /** Fetch one Connector detail: namespaced tools + auth state. */
105
+ get(connectorId: string): Promise<ConnectorDetail>;
106
+ /** Combined auth × probe status. `connected` only when auth is ready AND the last probe succeeded. */
107
+ status(connectorId: string): Promise<ConnectorStatusView>;
108
+ /** Run a connection probe; the server persists the result. */
109
+ test(connectorId: string): Promise<ConnectorProbeResult>;
110
+ /** Check the current OAuth state for a connector. */
111
+ authStatus(connectorId: string): Promise<OAuthStatusView>;
112
+ /**
113
+ * Kick off the OAuth browser flow on the trusted host. Returns the start
114
+ * acknowledgement immediately; poll `authStatus` until `authenticated`.
115
+ */
116
+ authStart(connectorId: string): Promise<OAuthStartResult>;
117
+ /** Revoke the OAuth token for a connector. */
118
+ logout(connectorId: string): Promise<void>;
119
+ }
120
+ //#endregion
121
+ //#region src/runs.d.ts
122
+ export declare class RunClient {
123
+ private readonly transport;
124
+ constructor(transport: Transport);
125
+ /** Start an Agent run and return its asynchronous receipt. */
126
+ agent(input: AgentRunInput): Promise<RunReceipt>;
127
+ /** Read the authoritative run state. */
128
+ get(runId: string): Promise<RunView>;
129
+ /** Read the terminal result (fails until the run reaches a terminal state). */
130
+ result(runId: string): Promise<RunResult>;
131
+ /** Replay persisted events after a cursor. */
132
+ events(query: RunEventsQuery): Promise<RunEvent[]>;
133
+ /** Request cancellation; the terminal state is confirmed by events/run/get. */
134
+ cancel(input: CancelRunInput): Promise<RunView>;
135
+ /**
136
+ * Inject steering text into the currently active step of a running Agent
137
+ * (runtime durable conversation effect; server resolves the opaque step).
138
+ */
139
+ steer(input: SteerRunInput): Promise<RunView>;
140
+ /** Subscribe to best-effort realtime events for one run. */
141
+ follow(runId: string, options?: FollowOptions): Promise<EventSubscription>;
142
+ }
143
+ export interface FollowOptions {
144
+ /** Silent cursor catch-up after subscribe (default true). */
145
+ catchUp?: boolean;
146
+ /** Automatic `run/events`追平 on `run/resync-required` (default true). */
147
+ autoResync?: boolean;
148
+ }
149
+ export type RunEventListener = (event: RunEvent) => void;
150
+ export type RunResyncListener = (params: {
151
+ run_ids: string[];
152
+ reason: string;
153
+ }) => void;
154
+ export type RunErrorListener = (error: unknown) => void;
155
+ export declare class EventSubscription {
156
+ private readonly transport;
157
+ readonly runId: string;
158
+ private readonly fetchAfter?;
159
+ private eventListeners;
160
+ private resyncListeners;
161
+ private errorListeners;
162
+ private closed;
163
+ private unsubscribeNotification;
164
+ private lastSeenSequence;
165
+ private seenSequences;
166
+ private resyncInFlight;
167
+ private readonly autoResync;
168
+ constructor(transport: Transport, runId: string, fetchAfter?: ((afterSequence: number) => Promise<RunEvent[]>) | undefined, options?: FollowOptions);
169
+ onEvent(listener: RunEventListener): () => void;
170
+ onResync(listener: RunResyncListener): () => void;
171
+ onError(listener: RunErrorListener): () => void;
172
+ get lastSequence(): number;
173
+ close(): Promise<void>;
174
+ private dispatch;
175
+ /**
176
+ * Silent cursor baseline: mark already-persisted events seen WITHOUT
177
+ * dispatching, so the first resync never replays history as "new".
178
+ * For explicit history use `RunClient.events({ afterSequence: 0 })`.
179
+ */
180
+ catchUp(): Promise<void>;
181
+ /**
182
+ *追平 missed events via `run/events` after the cursor. Returned (and
183
+ * dispatched) in sequence order, deduplicated against live delivery.
184
+ * Concurrent calls share one flight.
185
+ */
186
+ resync(): Promise<RunEvent[]>;
187
+ private markSeen;
188
+ private emitEvent;
189
+ private emitError;
190
+ /** Forward transport-level errors into subscription error listeners. */
191
+ deliverError(error: unknown): void;
192
+ }
193
+ //#endregion
194
+ //#region src/skills.d.ts
195
+ export declare class SkillClient {
196
+ private readonly transport;
197
+ constructor(transport: Transport);
198
+ /** List the Agent Store Skill catalog (public summaries only). */
199
+ list(): Promise<SkillSummary[]>;
200
+ /** Fetch one Skill detail; instructions are a bounded public summary. */
201
+ get(skillId: string): Promise<SkillDetail>;
202
+ }
203
+ //#endregion
204
+ //#region src/teams.d.ts
205
+ export declare class TeamClient {
206
+ private readonly transport;
207
+ constructor(transport: Transport);
208
+ /** List AgentTeamDefinitions (fixed-member rosters). */
209
+ list(): Promise<TeamSummary[]>;
210
+ /** Fetch one TeamDefinition; planning-context bodies are never returned. */
211
+ get(teamId: string): Promise<TeamDetail>;
212
+ }
213
+ //#endregion
214
+ //#region src/models.d.ts
215
+ export declare class ModelClient {
216
+ private readonly transport;
217
+ constructor(transport: Transport);
218
+ /** Enabled providers' models; `is_default` marks the `agent/run` fallback. */
219
+ list(): Promise<ModelSummary[]>;
220
+ }
221
+ //#endregion
222
+ //#region src/workspaces.d.ts
223
+ export declare class WorkspaceClient {
224
+ private readonly transport;
225
+ constructor(transport: Transport);
226
+ list(): Promise<WorkspaceView[]>;
227
+ /**
228
+ * Validate + register (idempotently per canonical root) an absolute local
229
+ * directory chosen by the owner. The server canonicalizes the path and
230
+ * rejects links/reparse points; the returned view only carries the
231
+ * canonical path back to this same authenticated connection.
232
+ */
233
+ create(path: string): Promise<WorkspaceView>;
234
+ /**
235
+ * Revoke (soft-delete) an owner's active workspace. Its conversations are
236
+ * kept and their `workspace_id` reference is preserved, so re-registering
237
+ * the same path re-activates the same workspace and those conversations
238
+ * become visible again.
239
+ */
240
+ revoke(workspaceId: string): Promise<WorkspaceRevokeResult>;
241
+ }
242
+ //#endregion
243
+ //#region src/client.d.ts
244
+ export interface AppServerClientOptions {
245
+ /** Ready-made transport (07 §2.3); the host app owns its lifecycle. */
246
+ transport: Transport;
247
+ client: ClientInfo;
248
+ capabilities?: ClientCapabilities;
249
+ }
250
+ export declare class AppServerClient {
251
+ readonly transport: Transport;
252
+ /** Legacy preset/execution workflow client. */
253
+ readonly runs: RunClient;
254
+ /** Persistent presetless Nomi chat client. */
255
+ readonly conversations: ConversationClient;
256
+ /** Owner-scoped workspace registry client (user-chosen paths). */
257
+ readonly workspaces: WorkspaceClient;
258
+ /** Agent Store Skill catalog client (`skill/list`, `skill/get`). */
259
+ readonly skills: SkillClient;
260
+ /** Agent Store Connector catalog/status/probe/OAuth client. */
261
+ readonly connectors: ConnectorClient;
262
+ /** Agent Store AgentDefinition catalog client (`agent/list`, `agent/get`). */
263
+ readonly agents: AgentClient;
264
+ /** Agent Store Team catalog client (`team/list`, `team/get`). */
265
+ readonly teams: TeamClient;
266
+ /** Public model directory (`models/list`, REQ-PAR-05b). */
267
+ readonly models: ModelClient;
268
+ readonly clientInfo: ClientInfo;
269
+ readonly capabilities?: ClientCapabilities;
270
+ private initializeResult;
271
+ private notificationListeners;
272
+ constructor(options: AppServerClientOptions);
273
+ get ready(): boolean;
274
+ get initializeInfo(): InitializeResult | null;
275
+ /** Connect and perform the initialize/initialized handshake. */
276
+ connect(): Promise<InitializeResult>;
277
+ onNotification(listener: NotificationListener): () => void;
278
+ /** Close the transport; the server revokes the connection immediately. */
279
+ close(): void;
280
+ /** Import a local CodeBuddy/WorkBuddy source directory (roadmap Phase 1). */
281
+ runImport(input: ImportRequest): Promise<ImportResult>;
282
+ listImports(): Promise<ImportSummary[]>;
283
+ /** One immutable snapshot with its standardized components. */
284
+ getImport(snapshotId: string): Promise<ImportDetail>;
285
+ /** Install a snapshot into the runtime (roadmap Phase 2). */
286
+ runInstall(input: InstallRequest): Promise<InstallResult>;
287
+ /** Per-component installation state of a snapshot. */
288
+ getInstallStatus(snapshotId: string): Promise<InstallStatus>;
289
+ /** Disable installed components (runtime artifacts stay). */
290
+ disableInstall(snapshotId: string, componentIds: string[]): Promise<InstallStatus>;
291
+ /** Re-enable previously disabled components. */
292
+ enableInstall(snapshotId: string, componentIds: string[]): Promise<InstallStatus>;
293
+ /** Uninstall: remove runtime artifacts and clear the state (snapshot kept). */
294
+ uninstallInstall(snapshotId: string, componentIds: string[]): Promise<InstallStatus>;
295
+ /** Register a marketplace source on the trusted host. */
296
+ addMarketplace(input: MarketplaceAddRequest): Promise<MarketplaceSummary>;
297
+ /** All active marketplaces. */
298
+ listMarketplaces(): Promise<MarketplaceSummary[]>;
299
+ /** One marketplace with its discovered entries. */
300
+ getMarketplace(marketplaceId: string): Promise<MarketplaceDetail>;
301
+ /** Remove a marketplace (`cascade` uninstalls snapshots installed from it). */
302
+ removeMarketplace(marketplaceId: string, cascade: boolean): Promise<MarketplaceRemoveResult>;
303
+ /** Toggle auto-update for a marketplace. */
304
+ setMarketplaceAutoUpdate(marketplaceId: string, enabled: boolean): Promise<MarketplaceSummary>;
305
+ /** Re-fetch a marketplace source and rebuild entries when the revision changed. */
306
+ refreshMarketplace(marketplaceId: string): Promise<MarketplaceRefreshResult>;
307
+ /** Import one discovered marketplace entry (provenance linked). */
308
+ importMarketplaceEntry(marketplaceId: string, entryName: string): Promise<ImportResult>;
309
+ /** All store items across enabled marketplaces (display + install state). */
310
+ listStore(): Promise<StoreList>;
311
+ /** One-click install: import (when missing) + register in one call. */
312
+ installStoreEntry(marketplaceId: string, entryName: string): Promise<StoreInstallResult>;
313
+ }
314
+ //#endregion
315
+ //#region src/conversation-handle.d.ts
316
+ /** One completed (or in-flight / timed-out) turn in a conversation. */
317
+ export interface ConversationTurn {
318
+ conversation_id: string;
319
+ /** The user content that was submitted. */
320
+ content: string;
321
+ /** Durable user message id (`ConversationSendReceipt.message_id`). */
322
+ message_id: string;
323
+ /** Wire/billing turn id when the server assigned one. */
324
+ turn_id?: string | null;
325
+ accepted: boolean;
326
+ completed: boolean;
327
+ /** Events observed for this turn (sequence order). */
328
+ events: ConversationEvent[];
329
+ /** Terminal assistant text: `receipt.result_text` (authoritative backfill)
330
+ * else aggregated from `message.delta` events. */
331
+ assistant_text: string | null;
332
+ isError: boolean;
333
+ result_error?: string | null;
334
+ result_error_code?: string | null;
335
+ /** Context occupancy when the runtime reported it during the turn. */
336
+ usage?: ContextUsage | null;
337
+ }
338
+ export interface ConversationTurnOptions {
339
+ /** Idempotency key; defaults to `crypto.randomUUID()`. */
340
+ idempotencyKey?: string;
341
+ /** Per-turn model override (applied server-side when set). */
342
+ model?: ConversationCreateInput["model"];
343
+ reasoningEffort?: string;
344
+ }
345
+ export declare class ConversationHandle {
346
+ readonly conversationId: string;
347
+ private readonly conversations;
348
+ private readonly subscription;
349
+ private constructor();
350
+ /** Create a new conversation and subscribe to its live event stream. */
351
+ static open(conversations: ConversationClient, input?: ConversationCreateInput): Promise<ConversationHandle>;
352
+ /** Attach to an existing conversation (by id) and subscribe. */
353
+ static attach(conversations: ConversationClient, conversationId: string): Promise<ConversationHandle>;
354
+ /** Register a listener for every conversation event (returns an unsubscribe). */
355
+ onEvent(listener: (event: ConversationEvent) => void): () => void;
356
+ /**
357
+ * Send a message (a "turn") and await its terminal state. The event collector
358
+ * is installed before the send so streaming deltas / usage are captured even
359
+ * when they arrive before the send acknowledgment is parsed.
360
+ */
361
+ send(content: string, options?: ConversationTurnOptions): Promise<ConversationTurn>;
362
+ /** Cancel the in-flight turn (idempotent; erases the current transcript row). */
363
+ cancel(): Promise<void>;
364
+ /** Fetch the transcript (paginated). */
365
+ messages(query?: Partial<ConversationMessagesQuery>): Promise<ConversationMessagesPage>;
366
+ /** Unsubscribe and release the handle. */
367
+ close(): Promise<void>;
368
+ }
369
+ /** Convenience: simple transcript snapshot (all roles, newest last). */
370
+ export declare function conversationMessages(page: ConversationMessagesPage): ConversationMessage[];
371
+ //#endregion
372
+ //#region src/turn-result.d.ts
373
+ /** Token/context usage for the turn (absent until the runtime projects it). */
374
+ export interface TurnUsage {
375
+ input_tokens?: number;
376
+ output_tokens?: number;
377
+ total_tokens?: number;
378
+ }
379
+ /** One event-derived item (plan revision, task, attempt, approval, ...). */
380
+ export interface TurnItem {
381
+ sequence: number;
382
+ event_type: string;
383
+ kind: "plan" | "task" | "attempt" | "status" | "approval" | "other";
384
+ /** Attempt/step identity when the event payload carries one. */
385
+ ref_id?: string;
386
+ status?: string;
387
+ reason?: string;
388
+ }
389
+ /** Aggregated terminal result returned by `AgentRunHandle.finished`. */
390
+ export interface TurnResult {
391
+ run_id: string;
392
+ status: RunStatus;
393
+ version: number;
394
+ /** Terminal assistant text (`run/result` summary). */
395
+ final_response: string | null;
396
+ output_files: string[];
397
+ preset_revision?: number | null;
398
+ content_digest?: string | null;
399
+ /** Persisted event stream in sequence order (authoritative backfill). */
400
+ events: RunEvent[];
401
+ /** Event-derived items in the same order. */
402
+ items: TurnItem[];
403
+ usage?: TurnUsage;
404
+ }
405
+ /** Build the terminal turn result from the authoritative view + event stream. */
406
+ export declare function aggregateTurnResult(view: RunView, events: RunEvent[]): TurnResult;
407
+ //#endregion
408
+ //#region src/run-handle.d.ts
409
+ /** Options for `RunClient.launch()` (Codex-parity handle). */
410
+ export interface LaunchHandleOptions {
411
+ /** Whether to attach a live `EventSubscription` (default true). */
412
+ follow?: boolean;
413
+ }
414
+ /**
415
+ * A launched Agent run. Async-iterable over live events; await `.finished`
416
+ * for the blocking Codex `thread.run()` shape.
417
+ */
418
+ export declare class AgentRunHandle {
419
+ readonly runId: string;
420
+ readonly receipt: RunReceipt;
421
+ private readonly runClient;
422
+ private readonly poll;
423
+ private subscription;
424
+ private terminalView;
425
+ private terminalResult;
426
+ private finishWaiters;
427
+ private iteratorQueue;
428
+ private iteratorWaiters;
429
+ private iteratorClosed;
430
+ private readonly bufferedEvents;
431
+ private readonly bufferedSequences;
432
+ constructor(runClient: RunClient, receipt: RunReceipt, subscription: EventSubscription | null, poll: (runId: string) => Promise<RunView>);
433
+ /**
434
+ * Resolves with the aggregated terminal turn result (≈ `thread.run()`):
435
+ * authoritative status/version plus `final_response`, output files, the
436
+ * persisted event stream and derived items.
437
+ */
438
+ get finished(): Promise<TurnResult>;
439
+ /** Latest live cursor (proxied from the subscription when attached). */
440
+ get lastSequence(): number;
441
+ /** Ask the server to cancel; terminal confirmation still arrives via events/get. */
442
+ cancel(): Promise<void>;
443
+ /**
444
+ * Inject steering text into the currently active step (≈ Codex turn steer).
445
+ * Throws `conflict` when the run already changed or has no active step —
446
+ * refresh `receipt`-level state via `runClient.get()` and retry.
447
+ */
448
+ steer(text: string): Promise<RunView>;
449
+ /** Detach the live subscription (events may still be polled via run/events). */
450
+ close(): Promise<void>;
451
+ /** Async iterator over live events (≈ `thread.runStreamed()`). */
452
+ [Symbol.asyncIterator](): AsyncIterator<RunEvent>;
453
+ private pushEvent;
454
+ /**
455
+ * Authoritative backfill for `finished`: `run/result` (terminal summary)
456
+ * plus the persisted `run/events` stream, falling back to the live buffer
457
+ * when the query fails.
458
+ */
459
+ private aggregate;
460
+ /** Poll run/get until terminal, then resolve all `finished` waiters once. */
461
+ private ensureTerminalWatch;
462
+ }
463
+ /** Codex-parity launch: start the run and return a live handle immediately. */
464
+ export declare function launchRun(runClient: RunClient, input: AgentRunInput, options?: LaunchHandleOptions): Promise<AgentRunHandle>;
465
+ //#endregion
466
+ //#region src/retry.d.ts
467
+ /**
468
+ * Retry helper (REQ-PAR-05e, ≈ Codex `retry_on_overload`): exponential backoff
469
+ * with jitter, driven by the protocol's stable `retryable` hint.
470
+ *
471
+ * Only errors the server/transport marks retryable are retried; protocol
472
+ * errors that carry `retryable: false` (validation, not_found, ...) surface
473
+ * immediately. `command_id` / `idempotency_key` callers stay safe because the
474
+ * App Server deduplicates replayed mutations.
475
+ */
476
+ export interface RetryInfo {
477
+ /** 1-based attempt that just failed and triggered the next try. */
478
+ attempt: number;
479
+ /** Delay applied before the next attempt. */
480
+ delayMs: number;
481
+ error: unknown;
482
+ }
483
+ export interface RetryOptions {
484
+ /** Total attempts including the first (default 3). */
485
+ maxAttempts?: number;
486
+ /** First backoff delay in ms (default 500). */
487
+ baseDelayMs?: number;
488
+ /** Upper bound for one delay in ms (default 8000). */
489
+ maxDelayMs?: number;
490
+ /** Jitter fraction in [0, 1] (default 0.25 → delay ∈ [0.75×, 1.0×]). */
491
+ jitter?: number;
492
+ /** Observer hook for logging/metrics. */
493
+ onRetry?: (info: RetryInfo) => void;
494
+ /** Custom predicate; defaults to the protocol `retryable` hint. */
495
+ shouldRetry?: (error: unknown, attempt: number) => boolean;
496
+ /** Deterministic delay override (tests). */
497
+ sleep?: (ms: number) => Promise<void>;
498
+ }
499
+ /** Run `operation`, retrying retryable failures with exponential backoff. */
500
+ export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
501
+ //#endregion