@agentuity/core 2.0.1 → 2.0.3

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.
Files changed (52) hide show
  1. package/AGENTS.md +15 -0
  2. package/dist/deprecation.d.ts +1 -1
  3. package/dist/deprecation.d.ts.map +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/services/auth/index.d.ts +1 -1
  9. package/dist/services/auth/index.d.ts.map +1 -1
  10. package/dist/services/index.d.ts +1 -0
  11. package/dist/services/index.d.ts.map +1 -1
  12. package/dist/services/index.js +1 -0
  13. package/dist/services/index.js.map +1 -1
  14. package/dist/services/queue/destinations.d.ts +60 -4
  15. package/dist/services/queue/destinations.d.ts.map +1 -1
  16. package/dist/services/queue/destinations.js.map +1 -1
  17. package/dist/services/queue/types.d.ts +121 -37
  18. package/dist/services/queue/types.d.ts.map +1 -1
  19. package/dist/services/queue/types.js +66 -7
  20. package/dist/services/queue/types.js.map +1 -1
  21. package/dist/services/webhook/types.d.ts +1 -0
  22. package/dist/services/webhook/types.d.ts.map +1 -1
  23. package/dist/services/webhook/types.js +1 -0
  24. package/dist/services/webhook/types.js.map +1 -1
  25. package/dist/services/workflow/api-reference.d.ts +4 -0
  26. package/dist/services/workflow/api-reference.d.ts.map +1 -0
  27. package/dist/services/workflow/api-reference.js +337 -0
  28. package/dist/services/workflow/api-reference.js.map +1 -0
  29. package/dist/services/workflow/index.d.ts +3 -0
  30. package/dist/services/workflow/index.d.ts.map +1 -0
  31. package/dist/services/workflow/index.js +3 -0
  32. package/dist/services/workflow/index.js.map +1 -0
  33. package/dist/services/workflow/service.d.ts +235 -0
  34. package/dist/services/workflow/service.d.ts.map +1 -0
  35. package/dist/services/workflow/service.js +555 -0
  36. package/dist/services/workflow/service.js.map +1 -0
  37. package/dist/services/workflow/types.d.ts +270 -0
  38. package/dist/services/workflow/types.d.ts.map +1 -0
  39. package/dist/services/workflow/types.js +174 -0
  40. package/dist/services/workflow/types.js.map +1 -0
  41. package/package.json +2 -2
  42. package/src/deprecation.ts +1 -1
  43. package/src/index.ts +1 -1
  44. package/src/services/auth/index.ts +1 -1
  45. package/src/services/index.ts +1 -0
  46. package/src/services/queue/destinations.ts +1 -1
  47. package/src/services/queue/types.ts +72 -9
  48. package/src/services/webhook/types.ts +1 -0
  49. package/src/services/workflow/api-reference.ts +352 -0
  50. package/src/services/workflow/index.ts +2 -0
  51. package/src/services/workflow/service.ts +633 -0
  52. package/src/services/workflow/types.ts +233 -0
@@ -0,0 +1,633 @@
1
+ import { buildUrl, toServiceException } from '../_util.ts';
2
+ import { StructuredError } from '../../error.ts';
3
+ import type {
4
+ CreateWorkflowRequest,
5
+ ListWorkflowsRequest,
6
+ UpdateWorkflowGraphRequest,
7
+ UpdateWorkflowRequest,
8
+ WorkflowActivity,
9
+ WorkflowCreateResult,
10
+ WorkflowDelivery,
11
+ WorkflowExecution,
12
+ WorkflowGetResult,
13
+ WorkflowListResult,
14
+ WorkflowUpdateResult,
15
+ TestWorkflowRequest,
16
+ TestWorkflowResult,
17
+ } from './types.ts';
18
+ import type { FetchAdapter } from '../adapter.ts';
19
+
20
+ /**
21
+ * Thrown when the API returns a success HTTP status but the response body indicates failure.
22
+ */
23
+ const WorkflowResponseError = StructuredError('WorkflowResponseError')<{
24
+ status: number;
25
+ }>();
26
+
27
+ /**
28
+ * Creates an {@link AbortSignal} that will abort after the specified timeout.
29
+ *
30
+ * @remarks
31
+ * Falls back to a manual `AbortController` + `setTimeout` if `AbortSignal.timeout`
32
+ * is not available in the runtime.
33
+ *
34
+ * @param ms - Timeout in milliseconds
35
+ * @returns An abort signal that triggers after `ms` milliseconds
36
+ *
37
+ * @default 30000
38
+ */
39
+ function createTimeoutSignal(ms = 30_000): AbortSignal {
40
+ if (typeof AbortSignal.timeout === 'function') {
41
+ return AbortSignal.timeout(ms);
42
+ }
43
+ const controller = new AbortController();
44
+ const timer = setTimeout(() => controller.abort(), ms);
45
+ controller.signal.addEventListener('abort', () => clearTimeout(timer), { once: true });
46
+ return controller.signal;
47
+ }
48
+
49
+ /**
50
+ * Internal API success response envelope for workflow operations.
51
+ */
52
+ type WorkflowSuccessResponse<T> = { success: true; data: T };
53
+
54
+ /**
55
+ * Internal API error response envelope for workflow operations.
56
+ */
57
+ type WorkflowErrorResponse = { success: false; message: string };
58
+
59
+ /**
60
+ * Discriminated union of API success and error responses for workflow operations.
61
+ */
62
+ type WorkflowResponse<T> = WorkflowSuccessResponse<T> | WorkflowErrorResponse;
63
+
64
+ /**
65
+ * Client for the Agentuity Workflow service.
66
+ *
67
+ * Provides methods for creating and managing workflows that route events from
68
+ * sources (email, queue, webhook, schedule) to configured destinations. The
69
+ * service supports:
70
+ *
71
+ * - **Workflows**: Named routing configurations with a source and graph
72
+ * - **Executions**: Records of workflow runs with step-level detail
73
+ * - **Deliveries**: Records of destination delivery attempts
74
+ * - **Testing**: Send test payloads through a workflow
75
+ *
76
+ * All methods are instrumented with OpenTelemetry spans for observability.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const workflows = new WorkflowService(baseUrl, adapter);
81
+ *
82
+ * // Create a workflow
83
+ * const { workflow } = await workflows.create({
84
+ * name: 'GitHub to Slack',
85
+ * source_type: 'webhook',
86
+ * source_ref_id: 'wh_abc123',
87
+ * });
88
+ *
89
+ * // List active workflows
90
+ * const { workflows: list } = await workflows.list({ status: 'enabled' });
91
+ * ```
92
+ */
93
+ export class WorkflowService {
94
+ #baseUrl: string;
95
+ #adapter: FetchAdapter;
96
+
97
+ /**
98
+ * Creates a new WorkflowService instance.
99
+ *
100
+ * @param baseUrl - The base URL of the workflow API
101
+ * @param adapter - The HTTP fetch adapter used for making API requests
102
+ */
103
+ constructor(baseUrl: string, adapter: FetchAdapter) {
104
+ this.#baseUrl = baseUrl;
105
+ this.#adapter = adapter;
106
+ }
107
+
108
+ #createUrl(path: string): string {
109
+ const url = buildUrl(this.#baseUrl, path);
110
+ return url;
111
+ }
112
+
113
+ /**
114
+ * Lists all workflows for the authenticated organization.
115
+ *
116
+ * @param params - Optional filter and pagination parameters
117
+ * @returns A promise resolving to the paginated list of workflows
118
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
119
+ * @throws {@link ServiceException} If the HTTP request fails
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const result = await service.list({ status: 'enabled', limit: 10 });
124
+ * console.log(`Found ${result.total} workflows`);
125
+ * for (const wf of result.workflows) {
126
+ * console.log(`${wf.name} (${wf.source_type})`);
127
+ * }
128
+ * ```
129
+ */
130
+ async list(params?: ListWorkflowsRequest): Promise<WorkflowListResult> {
131
+ const url = this.#createUrl('/workflow/list');
132
+ const signal = createTimeoutSignal();
133
+ const queryParams: Record<string, string> = {};
134
+ if (params?.limit !== undefined) queryParams['limit'] = String(params.limit);
135
+ if (params?.offset !== undefined) queryParams['offset'] = String(params.offset);
136
+ if (params?.status) queryParams['status'] = params.status;
137
+ if (params?.source_type) queryParams['source_type'] = params.source_type;
138
+ if (params?.filter) queryParams['filter'] = params.filter;
139
+
140
+ const qs = new URLSearchParams(queryParams);
141
+ const qsStr = qs.toString();
142
+ const finalUrl = qsStr ? `${url}?${qsStr}` : url;
143
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowListResult>>(finalUrl, {
144
+ method: 'GET',
145
+ signal,
146
+ contentType: 'application/json',
147
+ telemetry: {
148
+ name: 'agentuity.workflow.list',
149
+ },
150
+ });
151
+
152
+ if (res.ok) {
153
+ if (res.data.success) {
154
+ return res.data.data;
155
+ }
156
+ throw new WorkflowResponseError({
157
+ status: res.response.status,
158
+ message: res.data.message || 'Failed to list workflows',
159
+ });
160
+ }
161
+
162
+ throw await toServiceException('GET', url, res.response);
163
+ }
164
+
165
+ /**
166
+ * Gets a single workflow by its ID.
167
+ *
168
+ * @param workflowId - The unique workflow identifier (prefixed with wf_)
169
+ * @returns A promise resolving to the workflow details
170
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
171
+ * @throws {@link ServiceException} If the HTTP request fails
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const result = await service.get('wf_abc123');
176
+ * console.log(result.workflow.name);
177
+ * ```
178
+ */
179
+ async get(workflowId: string): Promise<WorkflowGetResult> {
180
+ const url = this.#createUrl(`/workflow/${encodeURIComponent(workflowId)}`);
181
+ const signal = createTimeoutSignal();
182
+
183
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowGetResult>>(url, {
184
+ method: 'GET',
185
+ signal,
186
+ contentType: 'application/json',
187
+ telemetry: {
188
+ name: 'agentuity.workflow.get',
189
+ attributes: {
190
+ workflowId,
191
+ },
192
+ },
193
+ });
194
+
195
+ if (res.ok) {
196
+ if (res.data.success) {
197
+ return res.data.data;
198
+ }
199
+ throw new WorkflowResponseError({
200
+ status: res.response.status,
201
+ message: res.data.message || 'Failed to get workflow',
202
+ });
203
+ }
204
+
205
+ throw await toServiceException('GET', url, res.response);
206
+ }
207
+
208
+ /**
209
+ * Creates a new workflow.
210
+ *
211
+ * @param params - The workflow creation parameters including name, source type, and source reference
212
+ * @returns A promise resolving to the newly created workflow
213
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
214
+ * @throws {@link ServiceException} If the HTTP request fails
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * const result = await service.create({
219
+ * name: 'Email to Slack',
220
+ * source_type: 'email',
221
+ * source_ref_id: 'user@example.com',
222
+ * });
223
+ * console.log('Created:', result.workflow.id);
224
+ * ```
225
+ */
226
+ async create(params: CreateWorkflowRequest): Promise<WorkflowCreateResult> {
227
+ const url = this.#createUrl('/workflow/create');
228
+ const signal = createTimeoutSignal();
229
+
230
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowCreateResult>>(url, {
231
+ method: 'POST',
232
+ signal,
233
+ body: JSON.stringify(params),
234
+ contentType: 'application/json',
235
+ telemetry: {
236
+ name: 'agentuity.workflow.create',
237
+ attributes: {
238
+ name: params.name,
239
+ source_type: params.source_type,
240
+ },
241
+ },
242
+ });
243
+
244
+ if (res.ok) {
245
+ if (res.data.success) {
246
+ return res.data.data;
247
+ }
248
+ throw new WorkflowResponseError({
249
+ status: res.response.status,
250
+ message: res.data.message || 'Failed to create workflow',
251
+ });
252
+ }
253
+
254
+ throw await toServiceException('POST', url, res.response);
255
+ }
256
+
257
+ /**
258
+ * Updates an existing workflow's name, description, or status.
259
+ *
260
+ * @param workflowId - The unique workflow identifier
261
+ * @param params - Fields to update; only provided fields are changed
262
+ * @returns A promise resolving to the updated workflow
263
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
264
+ * @throws {@link ServiceException} If the HTTP request fails
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * const result = await service.update('wf_abc123', {
269
+ * name: 'Updated Workflow Name',
270
+ * status: 'disabled',
271
+ * });
272
+ * console.log('Updated:', result.workflow.name);
273
+ * ```
274
+ */
275
+ async update(workflowId: string, params: UpdateWorkflowRequest): Promise<WorkflowUpdateResult> {
276
+ const url = this.#createUrl(`/workflow/${encodeURIComponent(workflowId)}`);
277
+ const signal = createTimeoutSignal();
278
+
279
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowUpdateResult>>(url, {
280
+ method: 'PATCH',
281
+ signal,
282
+ body: JSON.stringify(params),
283
+ contentType: 'application/json',
284
+ telemetry: {
285
+ name: 'agentuity.workflow.update',
286
+ attributes: {
287
+ workflowId,
288
+ },
289
+ },
290
+ });
291
+
292
+ if (res.ok) {
293
+ if (res.data.success) {
294
+ return res.data.data;
295
+ }
296
+ throw new WorkflowResponseError({
297
+ status: res.response.status,
298
+ message: res.data.message || 'Failed to update workflow',
299
+ });
300
+ }
301
+
302
+ throw await toServiceException('PATCH', url, res.response);
303
+ }
304
+
305
+ /**
306
+ * Updates the workflow graph (nodes and edges) for a workflow.
307
+ *
308
+ * @param workflowId - The unique workflow identifier
309
+ * @param params - The new graph definition with nodes and edges
310
+ * @returns A promise resolving to the updated workflow
311
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
312
+ * @throws {@link ServiceException} If the HTTP request fails
313
+ *
314
+ * @example
315
+ * ```typescript
316
+ * const result = await service.updateGraph('wf_abc123', {
317
+ * nodes: [{ id: 'n1', type: 'filter', data: { expr: '...' } }],
318
+ * edges: [{ id: 'e1', source: 'n1', target: 'n2' }],
319
+ * });
320
+ * ```
321
+ */
322
+ async updateGraph(
323
+ workflowId: string,
324
+ params: UpdateWorkflowGraphRequest
325
+ ): Promise<WorkflowUpdateResult> {
326
+ const url = this.#createUrl(`/workflow/graph/${encodeURIComponent(workflowId)}`);
327
+ const signal = createTimeoutSignal();
328
+
329
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowUpdateResult>>(url, {
330
+ method: 'PUT',
331
+ signal,
332
+ body: JSON.stringify({ graph_json: params }),
333
+ contentType: 'application/json',
334
+ telemetry: {
335
+ name: 'agentuity.workflow.updateGraph',
336
+ attributes: {
337
+ workflowId,
338
+ },
339
+ },
340
+ });
341
+
342
+ if (res.ok) {
343
+ if (res.data.success) {
344
+ return res.data.data;
345
+ }
346
+ throw new WorkflowResponseError({
347
+ status: res.response.status,
348
+ message: res.data.message || 'Failed to update workflow graph',
349
+ });
350
+ }
351
+
352
+ throw await toServiceException('PUT', url, res.response);
353
+ }
354
+
355
+ /**
356
+ * Deletes a workflow and all associated data.
357
+ *
358
+ * @param workflowId - The unique workflow identifier
359
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
360
+ * @throws {@link ServiceException} If the HTTP request fails
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * await service.delete('wf_abc123');
365
+ * console.log('Workflow deleted');
366
+ * ```
367
+ */
368
+ async delete(workflowId: string): Promise<void> {
369
+ const url = this.#createUrl(`/workflow/${encodeURIComponent(workflowId)}`);
370
+ const signal = createTimeoutSignal();
371
+
372
+ const res = await this.#adapter.invoke<WorkflowResponse<void>>(url, {
373
+ method: 'DELETE',
374
+ signal,
375
+ contentType: 'application/json',
376
+ telemetry: {
377
+ name: 'agentuity.workflow.delete',
378
+ attributes: {
379
+ workflowId,
380
+ },
381
+ },
382
+ });
383
+
384
+ if (res.ok) {
385
+ // Handle 204 No Content or responses without a body
386
+ if (res.response.status === 204 || res.data === undefined) {
387
+ return;
388
+ }
389
+ if (res.data.success) {
390
+ return;
391
+ }
392
+ throw new WorkflowResponseError({
393
+ status: res.response.status,
394
+ message: res.data.message || 'Failed to delete workflow',
395
+ });
396
+ }
397
+
398
+ throw await toServiceException('DELETE', url, res.response);
399
+ }
400
+
401
+ /**
402
+ * Tests a workflow with a sample payload.
403
+ *
404
+ * Sends the provided payload through the workflow and returns the execution
405
+ * result including individual step outcomes.
406
+ *
407
+ * @param workflowId - The unique workflow identifier
408
+ * @param params - The test parameters including the payload to send
409
+ * @returns A promise resolving to the test execution result
410
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
411
+ * @throws {@link ServiceException} If the HTTP request fails
412
+ *
413
+ * @example
414
+ * ```typescript
415
+ * const result = await service.test('wf_abc123', {
416
+ * payload: { event: 'push', repo: 'my-repo' },
417
+ * });
418
+ * console.log('Test status:', result.status);
419
+ * ```
420
+ */
421
+ async test(workflowId: string, params: TestWorkflowRequest): Promise<TestWorkflowResult> {
422
+ const url = this.#createUrl(`/workflow/test/${encodeURIComponent(workflowId)}`);
423
+ const signal = createTimeoutSignal();
424
+
425
+ const res = await this.#adapter.invoke<WorkflowResponse<TestWorkflowResult>>(url, {
426
+ method: 'POST',
427
+ signal,
428
+ body: JSON.stringify(params),
429
+ contentType: 'application/json',
430
+ telemetry: {
431
+ name: 'agentuity.workflow.test',
432
+ attributes: {
433
+ workflowId,
434
+ },
435
+ },
436
+ });
437
+
438
+ if (res.ok) {
439
+ if (res.data.success) {
440
+ return res.data.data;
441
+ }
442
+ throw new WorkflowResponseError({
443
+ status: res.response.status,
444
+ message: res.data.message || 'Failed to test workflow',
445
+ });
446
+ }
447
+
448
+ throw await toServiceException('POST', url, res.response);
449
+ }
450
+
451
+ /**
452
+ * Gets workflow activity statistics for the authenticated organization.
453
+ *
454
+ * Returns aggregate counts of workflows, executions, and their statuses.
455
+ *
456
+ * @param days - Optional number of days to look back for activity (default: server-side default)
457
+ * @returns A promise resolving to the activity statistics
458
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
459
+ * @throws {@link ServiceException} If the HTTP request fails
460
+ *
461
+ * @example
462
+ * ```typescript
463
+ * const activity = await service.activity(7);
464
+ * console.log(`${activity.total_workflows} workflows, ${activity.total_executions} executions`);
465
+ * ```
466
+ */
467
+ async activity(days?: number): Promise<WorkflowActivity> {
468
+ const url = this.#createUrl('/workflow/activity');
469
+ const signal = createTimeoutSignal();
470
+ const queryParams: Record<string, string> = {};
471
+ if (days !== undefined) queryParams['days'] = String(days);
472
+
473
+ const qs = new URLSearchParams(queryParams);
474
+ const qsStr = qs.toString();
475
+ const finalUrl = qsStr ? `${url}?${qsStr}` : url;
476
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowActivity>>(finalUrl, {
477
+ method: 'GET',
478
+ signal,
479
+ contentType: 'application/json',
480
+ telemetry: {
481
+ name: 'agentuity.workflow.activity',
482
+ },
483
+ });
484
+
485
+ if (res.ok) {
486
+ if (res.data.success) {
487
+ return res.data.data;
488
+ }
489
+ throw new WorkflowResponseError({
490
+ status: res.response.status,
491
+ message: res.data.message || 'Failed to get workflow activity',
492
+ });
493
+ }
494
+
495
+ throw await toServiceException('GET', url, res.response);
496
+ }
497
+
498
+ /**
499
+ * Lists execution records for a specific workflow.
500
+ *
501
+ * @param workflowId - The unique workflow identifier
502
+ * @returns A promise resolving to the list of executions
503
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
504
+ * @throws {@link ServiceException} If the HTTP request fails
505
+ *
506
+ * @example
507
+ * ```typescript
508
+ * const executions = await service.listExecutions('wf_abc123');
509
+ * for (const exec of executions) {
510
+ * console.log(`${exec.id}: ${exec.status}`);
511
+ * }
512
+ * ```
513
+ */
514
+ async listExecutions(workflowId: string): Promise<WorkflowExecution[]> {
515
+ const url = this.#createUrl(`/workflow/executions/${encodeURIComponent(workflowId)}`);
516
+ const signal = createTimeoutSignal();
517
+
518
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowExecution[]>>(url, {
519
+ method: 'GET',
520
+ signal,
521
+ contentType: 'application/json',
522
+ telemetry: {
523
+ name: 'agentuity.workflow.listExecutions',
524
+ attributes: {
525
+ workflowId,
526
+ },
527
+ },
528
+ });
529
+
530
+ if (res.ok) {
531
+ if (res.data.success) {
532
+ return res.data.data;
533
+ }
534
+ throw new WorkflowResponseError({
535
+ status: res.response.status,
536
+ message: res.data.message || 'Failed to list workflow executions',
537
+ });
538
+ }
539
+
540
+ throw await toServiceException('GET', url, res.response);
541
+ }
542
+
543
+ /**
544
+ * Lists delivery records for a specific workflow execution.
545
+ *
546
+ * @param executionId - The unique execution identifier
547
+ * @returns A promise resolving to the list of deliveries
548
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
549
+ * @throws {@link ServiceException} If the HTTP request fails
550
+ *
551
+ * @example
552
+ * ```typescript
553
+ * const deliveries = await service.listDeliveries('exec_abc123');
554
+ * for (const d of deliveries) {
555
+ * console.log(`${d.destination_type}: ${d.status}`);
556
+ * }
557
+ * ```
558
+ */
559
+ async listDeliveries(executionId: string): Promise<WorkflowDelivery[]> {
560
+ const url = this.#createUrl(`/workflow/deliveries/${encodeURIComponent(executionId)}`);
561
+ const signal = createTimeoutSignal();
562
+
563
+ const res = await this.#adapter.invoke<WorkflowResponse<WorkflowDelivery[]>>(url, {
564
+ method: 'GET',
565
+ signal,
566
+ contentType: 'application/json',
567
+ telemetry: {
568
+ name: 'agentuity.workflow.listDeliveries',
569
+ attributes: {
570
+ executionId,
571
+ },
572
+ },
573
+ });
574
+
575
+ if (res.ok) {
576
+ if (res.data.success) {
577
+ return res.data.data;
578
+ }
579
+ throw new WorkflowResponseError({
580
+ status: res.response.status,
581
+ message: res.data.message || 'Failed to list workflow deliveries',
582
+ });
583
+ }
584
+
585
+ throw await toServiceException('GET', url, res.response);
586
+ }
587
+
588
+ /**
589
+ * Gets the most recent payload received by a workflow.
590
+ *
591
+ * Useful for inspecting the last event that triggered the workflow, e.g.
592
+ * when building or debugging workflow graphs.
593
+ *
594
+ * @param workflowId - The unique workflow identifier
595
+ * @returns A promise resolving to the recent payload data
596
+ * @throws {@link WorkflowResponseError} If the API returns a failure response body
597
+ * @throws {@link ServiceException} If the HTTP request fails
598
+ *
599
+ * @example
600
+ * ```typescript
601
+ * const payload = await service.getRecentPayload('wf_abc123');
602
+ * console.log('Last payload:', JSON.stringify(payload, null, 2));
603
+ * ```
604
+ */
605
+ async getRecentPayload(workflowId: string): Promise<unknown> {
606
+ const url = this.#createUrl(`/workflow/recent-payload/${encodeURIComponent(workflowId)}`);
607
+ const signal = createTimeoutSignal();
608
+
609
+ const res = await this.#adapter.invoke<WorkflowResponse<unknown>>(url, {
610
+ method: 'GET',
611
+ signal,
612
+ contentType: 'application/json',
613
+ telemetry: {
614
+ name: 'agentuity.workflow.getRecentPayload',
615
+ attributes: {
616
+ workflowId,
617
+ },
618
+ },
619
+ });
620
+
621
+ if (res.ok) {
622
+ if (res.data.success) {
623
+ return res.data.data;
624
+ }
625
+ throw new WorkflowResponseError({
626
+ status: res.response.status,
627
+ message: res.data.message || 'Failed to get recent payload',
628
+ });
629
+ }
630
+
631
+ throw await toServiceException('GET', url, res.response);
632
+ }
633
+ }