@tuvl/client 0.0.1 → 2026.2.1-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,569 @@
1
+ /**
2
+ * Low-level HTTP transport for @tuvl/client.
3
+ *
4
+ * Handles auth header injection, JSON serialisation, and returns raw
5
+ * Response objects so higher-level transports (SSE, gRPC) can consume them.
6
+ */
7
+ interface TransportOptions {
8
+ baseUrl: string;
9
+ defaultToken?: string;
10
+ }
11
+ declare class Transport {
12
+ /** Public so TuvlClient can forward it to the gRPC subtransport. */
13
+ readonly baseUrl: string;
14
+ private defaultToken;
15
+ constructor(options: TransportOptions);
16
+ /** Update the default token (e.g. after refresh). */
17
+ setToken(token: string): void;
18
+ /** Build the Authorization header value, or undefined if no token. */
19
+ private authHeader;
20
+ /** Perform a plain JSON POST and return the parsed response body. */
21
+ post<TBody = unknown, TResponse = unknown>(path: string, body: TBody, options?: {
22
+ token?: string;
23
+ signal?: AbortSignal;
24
+ }): Promise<TResponse>;
25
+ /**
26
+ * Open an SSE-capable stream and return the raw Response.
27
+ * Callers are responsible for reading `response.body`.
28
+ */
29
+ postStream(path: string, body: unknown, options?: {
30
+ token?: string;
31
+ signal?: AbortSignal;
32
+ }): Promise<Response>;
33
+ /** Simple GET returning parsed JSON. */
34
+ get<TResponse = unknown>(path: string, options?: {
35
+ token?: string;
36
+ signal?: AbortSignal;
37
+ }): Promise<TResponse>;
38
+ /** Perform a JSON PATCH and return the parsed response body. */
39
+ patch<TBody = unknown, TResponse = unknown>(path: string, body: TBody, options?: {
40
+ token?: string;
41
+ signal?: AbortSignal;
42
+ }): Promise<TResponse>;
43
+ /** Perform a DELETE request. Expects a 204 No Content response. */
44
+ delete(path: string, options?: {
45
+ token?: string;
46
+ signal?: AbortSignal;
47
+ }): Promise<void>;
48
+ }
49
+
50
+ /**
51
+ * Shared types for @tuvl/client.
52
+ *
53
+ * Mirrors the Python-side StepEvent dataclass, the SSE envelope produced by
54
+ * tuvl.core.engine.streaming, and the system_router manifest shapes.
55
+ */
56
+ /** Returned by all /auth/* login and refresh endpoints. */
57
+ interface TokenResponse {
58
+ access_token: string;
59
+ token_type: string;
60
+ }
61
+ /**
62
+ * Decoded identity and permissions for the currently authenticated user.
63
+ * Returned by GET /auth/me.
64
+ */
65
+ interface MeResponse {
66
+ /** User UUID extracted from the `user()` Datalog fact in the token. */
67
+ user_id: string;
68
+ /** Role names from all `group()` facts — e.g. ["hr_manager", "member"]. */
69
+ groups: string[];
70
+ /** Permission scopes from all `scope()` facts — e.g. ["candidate:read"]. */
71
+ scopes: string[];
72
+ }
73
+ /** A single execution event streamed by the tuvl server (SSE or gRPC). */
74
+ interface StepEvent {
75
+ event_type: "step";
76
+ step_id: string;
77
+ kind: string;
78
+ signal: string;
79
+ snapshot: Record<string, unknown>;
80
+ duration_ms: number;
81
+ error_detail?: string | null;
82
+ }
83
+ /**
84
+ * Terminal event emitted when the workflow finishes (success OR business failure).
85
+ * Wire shape from tuvl.core.api.manager._sse_generator:
86
+ * {success: true, data: <output>, error: null}
87
+ * {success: false, data: <partial>, error: {...workflow error...}}
88
+ */
89
+ interface DoneEvent {
90
+ event_type: "done";
91
+ success: boolean;
92
+ data: unknown;
93
+ error: WorkflowErrorPayload | null;
94
+ }
95
+ /** Terminal event emitted when the workflow engine itself raised an exception. */
96
+ interface ErrorEvent {
97
+ event_type: "error";
98
+ message: string;
99
+ details?: string | null;
100
+ }
101
+ /** Terminal event emitted when a workflow hits a Human-in-the-Loop step. */
102
+ interface SuspendedEvent {
103
+ event_type: "suspended";
104
+ instance_id?: string;
105
+ paused_step_id?: string;
106
+ ui?: unknown;
107
+ schema?: unknown;
108
+ context_data?: Record<string, unknown>;
109
+ output_key?: string;
110
+ [key: string]: unknown;
111
+ }
112
+ /** Shape of the `error` field on a non-success DoneEvent / REST envelope. */
113
+ interface WorkflowErrorPayload {
114
+ code?: string;
115
+ message?: string;
116
+ details?: unknown;
117
+ [key: string]: unknown;
118
+ }
119
+ /**
120
+ * Shape of the plain REST response body returned by
121
+ * `POST <workflow_trigger_path>` (and the versioned variant).
122
+ *
123
+ * `execute()` unwraps this and returns just `data` on success, throwing
124
+ * `TuvlWorkflowError` on `success === false`.
125
+ */
126
+ interface RestEnvelope<TData = unknown> {
127
+ success: boolean;
128
+ status_code: number;
129
+ data: TData | null;
130
+ error: WorkflowErrorPayload | null;
131
+ }
132
+ /** Manifest for a single workflow (from GET /api/_system/workflows/{name}). */
133
+ interface WorkflowManifest {
134
+ name: string;
135
+ trigger_path: string;
136
+ trigger_method: string;
137
+ has_slow_steps: boolean;
138
+ slow_kinds_present: string[];
139
+ required_scope: string | null;
140
+ required_group: string | null;
141
+ steps: Array<{
142
+ id: string;
143
+ kind: string;
144
+ }>;
145
+ }
146
+ /** Map of workflow manifests (from GET /api/_system/workflows). */
147
+ type WorkflowManifestMap = Record<string, Omit<WorkflowManifest, "name" | "steps">>;
148
+ /** Options passed to TuvlClient.execute(). */
149
+ interface ExecuteOptions<_TOutput = unknown> {
150
+ payload?: Record<string, unknown>;
151
+ onProgress?: (event: StepEvent) => void;
152
+ onSuspended?: (event: SuspendedEvent) => void;
153
+ mode?: "sse" | "grpc" | "rest";
154
+ token?: string;
155
+ signal?: AbortSignal;
156
+ }
157
+ /** Options passed to TuvlClient.executeVersioned(). */
158
+ interface ExecuteVersionedOptions<_TOutput = unknown> extends ExecuteOptions<_TOutput> {
159
+ /** The workflow's schema_version, e.g. "v2". Calls /{version}/run/{name}. */
160
+ version: string;
161
+ }
162
+ /** Body sent to POST /api/workflows/resume. */
163
+ interface ResumeRequest {
164
+ instance_id: string;
165
+ human_input?: Record<string, unknown>;
166
+ }
167
+ /** Options passed to TuvlClient.resumeWorkflow(). */
168
+ interface ResumeOptions<_TOutput = unknown> {
169
+ instanceId: string;
170
+ humanInput?: Record<string, unknown>;
171
+ onProgress?: (event: StepEvent) => void;
172
+ onSuspended?: (event: SuspendedEvent) => void;
173
+ mode?: "sse" | "rest";
174
+ token?: string;
175
+ signal?: AbortSignal;
176
+ }
177
+ /** Options passed to TuvlClient constructor. */
178
+ interface TuvlClientOptions {
179
+ baseUrl: string;
180
+ token?: string;
181
+ manifestCacheTtl?: number;
182
+ }
183
+ /**
184
+ * Options for listing records from a CRUD model endpoint.
185
+ *
186
+ * `filters` maps to bracket-notation query params: `filter[key]=value`.
187
+ * `include` maps to `?include=relation1,relation2` for eager-loading relations.
188
+ */
189
+ interface CrudListOptions {
190
+ limit?: number;
191
+ offset?: number;
192
+ /** Server-side field filters: { stage: "screening" } → `?filter[stage]=screening` */
193
+ filters?: Record<string, string>;
194
+ /** Relation names to embed: ["posting"] → `?include=posting` */
195
+ include?: string[];
196
+ token?: string;
197
+ signal?: AbortSignal;
198
+ }
199
+ /** Options for retrieving a single CRUD record. */
200
+ interface CrudGetOptions {
201
+ /** Relation names to embed: ["candidate"] → `?include=candidate` */
202
+ include?: string[];
203
+ token?: string;
204
+ signal?: AbortSignal;
205
+ }
206
+ /** Options for create / update / delete calls. */
207
+ interface CrudMutateOptions {
208
+ token?: string;
209
+ signal?: AbortSignal;
210
+ }
211
+ /**
212
+ * Thrown by `execute()` when a workflow finishes with `success: false`.
213
+ */
214
+ declare class TuvlWorkflowError extends Error {
215
+ readonly data: unknown;
216
+ readonly error: WorkflowErrorPayload | null;
217
+ constructor(message: string, data: unknown, error: WorkflowErrorPayload | null);
218
+ }
219
+ /**
220
+ * Thrown by `execute()` when a workflow suspends at a Human-in-the-Loop step.
221
+ */
222
+ declare class TuvlWorkflowSuspendedError extends Error {
223
+ readonly suspended: SuspendedEvent;
224
+ constructor(suspended: SuspendedEvent);
225
+ }
226
+
227
+ /**
228
+ * CrudClient — typed CRUD access for tuvl model endpoints.
229
+ *
230
+ * The tuvl server mounts auto-generated CRUD routers at:
231
+ * /models/{modelname}/ (list, create)
232
+ * /models/{modelname}/{id} (get, update, delete)
233
+ *
234
+ * Usage via TuvlClient.crud():
235
+ *
236
+ * ```ts
237
+ * const client = new TuvlClient({ baseUrl: "http://localhost:8000", token });
238
+ *
239
+ * // List all candidates
240
+ * const all = await client.crud("candidate").list();
241
+ *
242
+ * // Filter + embed relations
243
+ * const results = await client.crud("candidate").list({
244
+ * filters: { stage: "screening" },
245
+ * include: ["posting"],
246
+ * limit: 50,
247
+ * });
248
+ *
249
+ * // Get one
250
+ * const c = await client.crud("candidate").get("uuid-here");
251
+ *
252
+ * // Create
253
+ * const created = await client.crud<CandidateRead, CandidateCreate>("candidate")
254
+ * .create({ name: "Alice", email: "alice@example.com" });
255
+ *
256
+ * // Update
257
+ * const updated = await client.crud("candidate").update("uuid", { stage: "interview" });
258
+ *
259
+ * // Delete
260
+ * await client.crud("candidate").delete("uuid");
261
+ * ```
262
+ *
263
+ * Type parameters:
264
+ * TRead — shape returned by GET / POST / PATCH (defaults to `unknown`)
265
+ * TCreate — body for POST (defaults to `Partial<TRead>`)
266
+ * TUpdate — body for PATCH (defaults to `Partial<TRead>`)
267
+ */
268
+
269
+ declare class CrudClient<TRead = unknown, TCreate = Partial<TRead>, TUpdate = Partial<TRead>> {
270
+ private readonly transport;
271
+ private readonly basePath;
272
+ constructor(transport: Transport, modelName: string);
273
+ /** Build query string from list options. */
274
+ private _buildQuery;
275
+ /** Build ?include= query string for get-by-id calls. */
276
+ private _buildGetQuery;
277
+ /**
278
+ * GET /models/{model}/
279
+ * Returns all records matching the given filters (server default: up to 100).
280
+ */
281
+ list(options?: CrudListOptions): Promise<TRead[]>;
282
+ /**
283
+ * GET /models/{model}/{id}
284
+ * Returns a single record by UUID, optionally with embedded relations.
285
+ */
286
+ get(id: string, options?: CrudGetOptions): Promise<TRead>;
287
+ /**
288
+ * POST /models/{model}/
289
+ * Creates a new record and returns the created resource (HTTP 201).
290
+ */
291
+ create(body: TCreate, options?: CrudMutateOptions): Promise<TRead>;
292
+ /**
293
+ * PATCH /models/{model}/{id}
294
+ * Partially updates a record (only fields present in `body` are changed).
295
+ */
296
+ update(id: string, body: TUpdate, options?: CrudMutateOptions): Promise<TRead>;
297
+ /**
298
+ * DELETE /models/{model}/{id}
299
+ * Deletes a record (HTTP 204). Throws if the record is not found.
300
+ */
301
+ delete(id: string, options?: CrudMutateOptions): Promise<void>;
302
+ }
303
+
304
+ /**
305
+ * TuvlClient — the main entry point for @tuvl/client.
306
+ *
307
+ * Auto-detects the best transport for each workflow call:
308
+ *
309
+ * mode="rest" (default) → plain POST, unwraps the REST envelope
310
+ * mode="sse" (auto) → SSE streaming when onProgress is provided
311
+ * AND the workflow has_slow_steps === true
312
+ * mode="grpc" → gRPC-Web via sonora (requires peer deps)
313
+ *
314
+ * Return-value contract — IDENTICAL across all three transports:
315
+ *
316
+ * • on success → resolves with the `data` value
317
+ * • on workflow-business error → rejects with `TuvlWorkflowError`
318
+ * • on HITL suspension → rejects with `TuvlWorkflowSuspendedError`
319
+ * • on transport / engine error → rejects with a plain `Error`
320
+ *
321
+ * Manifest caching avoids extra round-trips on repeated calls to the same
322
+ * workflow. TTL defaults to 60 s and is configurable.
323
+ */
324
+
325
+ declare class TuvlClient {
326
+ private readonly transport;
327
+ private readonly manifestCache;
328
+ private readonly manifestCacheTtl;
329
+ constructor(options: TuvlClientOptions);
330
+ /** Update the default auth token (e.g. after token refresh). */
331
+ setToken(token: string): void;
332
+ /** Expose the base URL for callers that need raw access (e.g. gRPC). */
333
+ get baseUrl(): string;
334
+ /** Fetch (and cache) the manifest for a single workflow. */
335
+ getManifest(workflowName: string, options?: {
336
+ token?: string;
337
+ signal?: AbortSignal;
338
+ }): Promise<WorkflowManifest>;
339
+ /** Fetch manifests for all registered workflows. */
340
+ listWorkflows(options?: {
341
+ token?: string;
342
+ signal?: AbortSignal;
343
+ }): Promise<WorkflowManifestMap>;
344
+ /** Invalidate the cached manifest for a workflow (or all if no name given). */
345
+ invalidateManifest(workflowName?: string): void;
346
+ /**
347
+ * Execute a workflow and return its `data` payload.
348
+ *
349
+ * Transport selection:
350
+ * 1. mode="grpc" → gRPC-Web (always, regardless of onProgress)
351
+ * 2. mode="sse" → SSE stream
352
+ * 3. onProgress provided → SSE if workflow has_slow_steps, else REST
353
+ * 4. default → REST
354
+ *
355
+ * @throws {TuvlWorkflowError} when the workflow returns success=false
356
+ * @throws {TuvlWorkflowSuspendedError} when the workflow suspends at HITL
357
+ * @throws {Error} on transport / engine failures
358
+ */
359
+ execute<TOutput = unknown>(workflowName: string, options?: ExecuteOptions<TOutput>): Promise<TOutput>;
360
+ /**
361
+ * Execute a specific version of a workflow via `/{version}/run/{name}`.
362
+ *
363
+ * Useful when you want to pin to a particular schema_version without
364
+ * relying on the currently-active default trigger path.
365
+ *
366
+ * @throws {TuvlWorkflowError} when the workflow returns success=false
367
+ * @throws {TuvlWorkflowSuspendedError} when the workflow suspends at HITL
368
+ * @throws {Error} on transport / engine failures
369
+ */
370
+ executeVersioned<TOutput = unknown>(workflowName: string, version: string, options?: ExecuteVersionedOptions<TOutput> | ExecuteOptions<TOutput>): Promise<TOutput>;
371
+ /**
372
+ * Resume a HITL-suspended workflow instance.
373
+ *
374
+ * After the workflow throws `TuvlWorkflowSuspendedError`, capture the
375
+ * `event.instance_id` from the suspended event and pass it here along with
376
+ * the human-provided data to continue execution.
377
+ *
378
+ * @throws {TuvlWorkflowError} when the resumed workflow returns success=false
379
+ * @throws {TuvlWorkflowSuspendedError} when the workflow suspends again at another HITL step
380
+ * @throws {Error} on transport / engine failures
381
+ */
382
+ resumeWorkflow<TOutput = unknown>(options: ResumeOptions<TOutput>): Promise<TOutput>;
383
+ private _executeSse;
384
+ private _executeGrpc;
385
+ private _unwrapRest;
386
+ /**
387
+ * Return a typed CRUD client for a tuvl model endpoint.
388
+ *
389
+ * The returned client targets `/models/{modelName}/` and shares the
390
+ * same transport (base URL + auth token) as this TuvlClient instance.
391
+ *
392
+ * @example
393
+ * ```ts
394
+ * // List all candidates
395
+ * const all = await client.crud("candidate").list();
396
+ *
397
+ * // With filters + embedded relations
398
+ * const results = await client.crud("candidate").list({
399
+ * filters: { stage: "screening" },
400
+ * include: ["posting"],
401
+ * limit: 50,
402
+ * });
403
+ *
404
+ * // Get one record
405
+ * const c = await client.crud("candidate").get("uuid-here");
406
+ *
407
+ * // Strongly-typed variant
408
+ * const c2 = await client
409
+ * .crud<CandidateRead, CandidateCreate>("candidate")
410
+ * .create({ name: "Alice", email: "alice@example.com" });
411
+ * ```
412
+ */
413
+ crud<TRead = unknown, TCreate = Partial<TRead>, TUpdate = Partial<TRead>>(modelName: string): CrudClient<TRead, TCreate, TUpdate>;
414
+ }
415
+
416
+ /**
417
+ * TuvlAuth — authentication helpers for @tuvl/client.
418
+ *
419
+ * Wraps the most common /auth/* endpoints (login, refresh, logout, who-am-I,
420
+ * OAuth start, bootstrap) so consumers never have to manually construct
421
+ * form-encoded bodies or manage Bearer headers for auth operations.
422
+ *
423
+ * Admin endpoints (user/role/scope CRUD, federation config) are NOT wrapped
424
+ * — call them directly via `Transport` or `fetch` with the token.
425
+ */
426
+
427
+ interface TuvlAuthOptions {
428
+ /** Base URL of the tuvl server. Trailing slash is stripped automatically. */
429
+ baseUrl: string;
430
+ }
431
+ interface BootstrapRequest {
432
+ email: string;
433
+ password: string;
434
+ /** Optional extra scope to grant the superadmin role on creation. */
435
+ admin_scope?: string;
436
+ }
437
+ declare class TuvlAuth {
438
+ private readonly baseUrl;
439
+ constructor(options: TuvlAuthOptions);
440
+ /**
441
+ * Decode the current token server-side and return the user's identity,
442
+ * role memberships (`groups`), and permission scopes.
443
+ *
444
+ * Biscuit tokens are protobuf-encoded and cannot be decoded in pure JS,
445
+ * so this is the correct way to read "who is logged in" and "what can
446
+ * they do" from the TypeScript SDK.
447
+ *
448
+ * @throws if the token is invalid, expired, or revoked.
449
+ */
450
+ getMe(token: string): Promise<MeResponse>;
451
+ /**
452
+ * Exchange an email + password for a Biscuit bearer token.
453
+ *
454
+ * Calls `POST /auth/token` with an `application/x-www-form-urlencoded`
455
+ * body (OAuth2 password-grant). The `username` field must be the user's
456
+ * email address.
457
+ */
458
+ loginWithPassword(email: string, password: string): Promise<TokenResponse>;
459
+ /**
460
+ * Create the first superadmin user (one-time IAM bootstrap).
461
+ *
462
+ * Calls `POST /auth/bootstrap`. Returns 409 on every subsequent call
463
+ * once any user exists.
464
+ */
465
+ bootstrap(req: BootstrapRequest): Promise<TokenResponse>;
466
+ /**
467
+ * Return the URL the browser should navigate to in order to start an
468
+ * OAuth2 login flow for the given provider.
469
+ *
470
+ * Supported built-ins: `"google"`, `"github"`, `"microsoft"`. Any
471
+ * provider configured in the project's `federation/` directory also
472
+ * works.
473
+ *
474
+ * After the OAuth dance the server either:
475
+ * - redirects to `TUVL_OAUTH_UI_REDIRECT_URL?token=<biscuit_b64>`, OR
476
+ * - returns a JSON `{access_token, token_type}` body (CLI / server flows).
477
+ */
478
+ getOAuthLoginUrl(provider: string): string;
479
+ /**
480
+ * Exchange a valid (non-expired, non-revoked) token for a fresh one.
481
+ * The old token is immediately blacklisted — discard it after this call.
482
+ */
483
+ refresh(token: string): Promise<TokenResponse>;
484
+ /**
485
+ * Revoke the given token (logout). After this the token is blacklisted
486
+ * across all workers that share a Redis instance. Resolves silently on
487
+ * success (HTTP 204).
488
+ */
489
+ logout(token: string): Promise<void>;
490
+ }
491
+
492
+ /**
493
+ * SSE transport for @tuvl/client.
494
+ *
495
+ * Uses the Fetch API ReadableStream to parse SSE frames from a POST response
496
+ * opened by Transport.postStream(). This avoids the browser's native
497
+ * EventSource (which only supports GET) and works in Node 18+.
498
+ *
499
+ * Wire format produced by tuvl.core.engine.streaming:
500
+ *
501
+ * event: step data: {step_id, kind, signal, snapshot, duration_ms, error_detail}
502
+ * event: suspended data: {<hitl_request payload>}
503
+ * event: done data: {success, data, error}
504
+ * event: error data: {message, details}
505
+ *
506
+ * The JSON body has NO `event_type` field — it lives only on the `event:`
507
+ * line. This parser injects the event name as `event_type` into the yielded
508
+ * object so downstream consumers can switch on a single discriminator.
509
+ */
510
+
511
+ type SseFrame = StepEvent | DoneEvent | ErrorEvent | SuspendedEvent;
512
+ /**
513
+ * Parse an SSE stream from a Fetch Response body.
514
+ *
515
+ * Yields typed frames as they arrive. The generator terminates when it
516
+ * receives an event with event_type "done", "error", or "suspended", or
517
+ * when the stream closes.
518
+ */
519
+ declare function parseSseStream(response: Response, signal?: AbortSignal): AsyncGenerator<SseFrame>;
520
+
521
+ /**
522
+ * gRPC-Web transport for @tuvl/client.
523
+ *
524
+ * This module is an OPTIONAL transport that requires the peer dependencies:
525
+ * @protobuf-ts/grpcweb-transport
526
+ * @protobuf-ts/runtime-rpc
527
+ *
528
+ * It uses dynamic import() so the main bundle has zero overhead if you never
529
+ * use mode="grpc". The protobuf definitions are created inline rather than
530
+ * from generated stubs, keeping the SDK self-contained (no make proto step
531
+ * required on the client side).
532
+ *
533
+ * The wire format matches execution.proto:
534
+ * service ExecutionService { rpc RunWorkflow(RunRequest) → stream StepEvent }
535
+ */
536
+ /**
537
+ * gRPC StepEvent on the wire. Unlike the typed SSE `StepEvent` (which is
538
+ * narrowed to `event_type: "step"`), this can carry "step" | "done" |
539
+ * "error" | "suspended" — the discriminator the servicer chose.
540
+ */
541
+ interface GrpcStepEvent {
542
+ event_type: "step" | "done" | "error" | "suspended";
543
+ step_id: string;
544
+ kind: string;
545
+ signal: string;
546
+ /** Decoded from `snapshot_json` on the wire. */
547
+ snapshot: Record<string, unknown>;
548
+ duration_ms: number;
549
+ error_detail?: string;
550
+ }
551
+ interface GrpcRunOptions {
552
+ baseUrl: string;
553
+ workflowName: string;
554
+ payloadJson: string;
555
+ tokenFallback?: string;
556
+ token?: string;
557
+ signal?: AbortSignal;
558
+ }
559
+ /**
560
+ * Open a gRPC-Web server-streaming call to ExecutionService.RunWorkflow.
561
+ *
562
+ * Yields `GrpcStepEvent` objects (with `snapshot_json` already parsed into
563
+ * `snapshot`). The caller decides what each `event_type` means.
564
+ *
565
+ * Throws if the peer deps are not installed.
566
+ */
567
+ declare function openGrpcStream(options: GrpcRunOptions): AsyncGenerator<GrpcStepEvent>;
568
+
569
+ export { type BootstrapRequest, CrudClient, type CrudGetOptions, type CrudListOptions, type CrudMutateOptions, type DoneEvent, type ErrorEvent, type ExecuteOptions, type ExecuteVersionedOptions, type MeResponse, type RestEnvelope, type ResumeOptions, type ResumeRequest, type StepEvent, type SuspendedEvent, type TokenResponse, Transport, TuvlAuth, type TuvlAuthOptions, TuvlClient, type TuvlClientOptions, TuvlWorkflowError, TuvlWorkflowSuspendedError, type WorkflowErrorPayload, type WorkflowManifest, type WorkflowManifestMap, openGrpcStream, parseSseStream };