@eigenpal/sdk 0.6.13 → 0.6.15

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @eigenpal/sdk
2
2
 
3
+ ## 0.6.15
4
+
5
+ ### Minor Changes
6
+
7
+ - ca87265: Unify workflow and agent run starts behind the canonical `/api/v1/run/{target}` endpoint, root `eigenpal run` / `eigenpal rerun` commands, and root SDK `client.run()` / `client.rerun()` methods.
8
+
9
+ The old nested CLI commands and SDK resource methods for starting workflow or agent runs have been removed.
10
+
3
11
  ## 0.6.10
4
12
 
5
13
  ### Patch Changes
package/README.md CHANGED
@@ -29,7 +29,7 @@ const client = new EigenpalClient({ apiKey: process.env.EIGENPAL_API_KEY });
29
29
  const result = await client.workflows.executions.runAndWait('extract-invoice', {
30
30
  contract_document: file,
31
31
  });
32
- console.log(result.status, result.result);
32
+ console.log(result.status, result.output);
33
33
  ```
34
34
 
35
35
  ## Authentication
@@ -55,23 +55,23 @@ const client = new EigenpalClient({
55
55
 
56
56
  `baseUrl` likewise wins over the `EIGENPAL_BASE_URL` env fallback. Defaults to `https://app.eigenpal.com` (the hosted cloud).
57
57
 
58
- ## Triggering workflows
58
+ ## Starting runs
59
59
 
60
- `workflows.run(workflowId, input?, options?)` enqueues a workflow execution.
60
+ `client.run(target, input?, options?)` starts a workflow or agent run. Targets can be strings such as `workflows.extract-invoice` / `agents.invoice-agent` or structured objects like `{ type: 'workflow', slug: 'extract-invoice' }`.
61
61
 
62
62
  ```ts
63
- // Async: returns immediately with { executionId }.
64
- const { executionId } = await client.workflows.run('extract-invoice', {
63
+ // Async: returns immediately with { runId }.
64
+ const { runId } = await client.run('workflows.extract-invoice', {
65
65
  contract_document: file,
66
66
  });
67
67
 
68
68
  // Sync: server holds the connection up to 60 seconds.
69
- const result = await client.workflows.run(
70
- 'extract-invoice',
69
+ const result = await client.run(
70
+ { type: 'workflow', slug: 'extract-invoice', version: 'latest' },
71
71
  { contract_document: file },
72
72
  { waitForCompletion: 60 }
73
73
  );
74
- console.log(result.status, result.result);
74
+ console.log(result.status, result.output);
75
75
 
76
76
  // Long-running: client-side polling, default 5min cap.
77
77
  const final = await client.workflows.executions.runAndWait('extract-invoice', {
@@ -79,7 +79,7 @@ const final = await client.workflows.executions.runAndWait('extract-invoice', {
79
79
  });
80
80
  ```
81
81
 
82
- The second argument is the workflow input map keyed by input name (as declared in the workflow). Pass `undefined` for inputs-less workflows. `options` carries `version`, `waitForCompletion`, and `overrides`.
82
+ The second argument is the input map keyed by input name. Pass `undefined` for inputs-less runs. `options` carries `waitForCompletion` and workflow `overrides`; put the workflow version or agent source ref in the target.
83
83
 
84
84
  ## File inputs
85
85
 
@@ -87,12 +87,12 @@ When a workflow input is a file, pass a `File`, `Blob`, or explicit `{ content,
87
87
 
88
88
  ```ts
89
89
  // Browser: File from <input type="file">
90
- await client.workflows.run('extract-invoice', { contract_document: file });
90
+ await client.run('workflows.extract-invoice', { contract_document: file });
91
91
 
92
92
  // Node: Buffer from fs
93
93
  import { readFile } from 'node:fs/promises';
94
94
  const buffer = await readFile('contract.pdf');
95
- await client.workflows.run('extract-invoice', {
95
+ await client.run('workflows.extract-invoice', {
96
96
  contract_document: {
97
97
  content: buffer,
98
98
  filename: 'contract.pdf',
@@ -112,11 +112,11 @@ const runs = await client.runs.list({
112
112
  status: 'failed,cancelled',
113
113
  });
114
114
 
115
- const run = await client.runs.get(executionId, { include: 'detail' });
116
- await client.runs.cancel(executionId);
115
+ const run = await client.runs.get(runId, { include: 'detail' });
116
+ await client.runs.cancel(runId);
117
117
 
118
- const status = await client.runs.get(executionId);
119
- // { executionId, status, result?, error?, createdAt, completedAt? }
118
+ const status = await client.runs.get(runId);
119
+ // { run: { id, status, output?, error?, createdAt, completedAt? } }
120
120
 
121
121
  const list = await client.runs.list({
122
122
  type: 'workflow',
@@ -126,7 +126,7 @@ const list = await client.runs.list({
126
126
  limit: 50,
127
127
  });
128
128
 
129
- await client.runs.cancel(executionId);
129
+ await client.runs.cancel(runId);
130
130
  ```
131
131
 
132
132
  `/api/v1/runs` is the shared run API for workflow, agent, and eval runs. Use `type=workflow|agent`
@@ -146,12 +146,12 @@ await client.workflows.versions('extract-invoice');
146
146
  await client.agents.list({ search: 'invoice' });
147
147
  await client.agents.get('invoice-agent');
148
148
 
149
- const { executionId } = await client.agents.run('invoice-agent', {
149
+ const { runId: agentRunId } = await client.run('agents.invoice-agent', {
150
150
  invoice: file,
151
151
  });
152
152
 
153
- await client.runs.get(executionId);
154
- await client.runs.cancel(executionId);
153
+ await client.runs.get(agentRunId);
154
+ await client.runs.cancel(agentRunId);
155
155
  ```
156
156
 
157
157
  Agent run listing uses the same shared runs API with `type: 'agent'` and the agent id or slug as
@@ -181,7 +181,7 @@ try {
181
181
  const result = await client.workflows.executions.runAndWait('extract-invoice', {
182
182
  language: 'en',
183
183
  });
184
- console.log(result.status, result.result);
184
+ console.log(result.status, result.output);
185
185
  } catch (err) {
186
186
  if (err instanceof EigenpalValidationError) {
187
187
  for (const issue of err.issues) console.error(`${issue.field}: ${issue.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eigenpal/sdk",
3
- "version": "0.6.13",
3
+ "version": "0.6.15",
4
4
  "description": "Official TypeScript SDK for the EigenPal API",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/client.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { EigenpalError, EigenpalTimeoutError, errorFromResponse } from './errors';
2
2
  import { createClient, createConfig, type Client, type Config } from './generated/client';
3
+ import { runStartWithTarget } from './generated/sdk.gen';
3
4
  import type { ApiErrorEnvelope } from './generated/types.gen';
5
+ import { buildRunJsonBody, buildRunMultipart, hasFileInput } from './lib/files';
4
6
  import { AgentsResource } from './resources/agents';
5
7
  import { AutomationsResource } from './resources/automations';
6
8
  import { RunsResource } from './resources/runs';
@@ -51,6 +53,40 @@ export interface OperationResult<T> {
51
53
  request?: Request;
52
54
  }
53
55
 
56
+ export type RunTarget =
57
+ | string
58
+ | {
59
+ type: 'workflow' | 'agent';
60
+ id?: string;
61
+ slug?: string;
62
+ version?: string;
63
+ };
64
+
65
+ export type RunInput = Record<string, unknown>;
66
+
67
+ export interface RunOptions {
68
+ input?: RunInput;
69
+ waitForCompletion?: number;
70
+ overrides?: { steps?: Record<string, Record<string, unknown>> };
71
+ signal?: AbortSignal;
72
+ }
73
+
74
+ export type RunCallOptions = Omit<RunOptions, 'input'>;
75
+
76
+ export interface RerunOptions {
77
+ version?: 'latest' | 'original' | string;
78
+ waitForCompletion?: number;
79
+ signal?: AbortSignal;
80
+ }
81
+
82
+ export type RunStartResponse = Record<string, unknown> & {
83
+ runId: string;
84
+ type: 'workflow' | 'agent';
85
+ status?: string;
86
+ output?: unknown;
87
+ error?: string | null;
88
+ };
89
+
54
90
  /**
55
91
  * The EigenPal SDK client.
56
92
  *
@@ -61,10 +97,13 @@ export interface OperationResult<T> {
61
97
  * const client = new EigenpalClient();
62
98
  *
63
99
  * // Async — enqueue and poll later.
64
- * const { executionId } = await client.workflows.run('wf_abc', { language: 'en' });
100
+ * const { runId } = await client.run('workflows.extract-invoice', {
101
+ * input: { language: 'en' },
102
+ * });
65
103
  *
66
104
  * // Sync (server holds the connection up to 60s).
67
- * const result = await client.workflows.run('wf_abc', { language: 'en' }, {
105
+ * const result = await client.run('workflows.extract-invoice', {
106
+ * input: { language: 'en' },
68
107
  * waitForCompletion: 60,
69
108
  * });
70
109
  *
@@ -73,9 +112,9 @@ export interface OperationResult<T> {
73
112
  * ```
74
113
  */
75
114
  export class EigenpalClient {
76
- /** Workflow operations: `list`, `get`, `versions`, `run`. */
115
+ /** Workflow definition operations: `list`, `get`, `versions`. Start runs with `client.run(...)`. */
77
116
  public readonly workflows: WorkflowsResource;
78
- /** Agent operations: `list`, `get`, `create`, `run`, `executions`. */
117
+ /** Agent operations: `list`, `get`, `create`, `executions`. Start runs with `client.run(...)`. */
79
118
  public readonly agents: AgentsResource;
80
119
  /** Source repository operations: repository metadata, raw files, releases, lockfiles, and secret decrypt. */
81
120
  public readonly source: SourceResource;
@@ -135,6 +174,83 @@ export class EigenpalClient {
135
174
  return this.client;
136
175
  }
137
176
 
177
+ async run(
178
+ target: RunTarget,
179
+ input?: RunInput,
180
+ options?: RunCallOptions
181
+ ): Promise<RunStartResponse>;
182
+ async run(target: RunTarget, options?: RunOptions): Promise<RunStartResponse>;
183
+ async run(request: { target: RunTarget } & RunOptions): Promise<RunStartResponse>;
184
+ async run(
185
+ targetOrRequest: RunTarget | ({ target: RunTarget } & RunOptions),
186
+ inputOrOptions: RunInput | RunOptions = {},
187
+ options: RunCallOptions = {}
188
+ ): Promise<RunStartResponse> {
189
+ const targetPassedDirectly =
190
+ typeof targetOrRequest === 'string' ||
191
+ (targetOrRequest &&
192
+ typeof targetOrRequest === 'object' &&
193
+ 'type' in targetOrRequest &&
194
+ !('target' in targetOrRequest));
195
+ const request = targetPassedDirectly
196
+ ? { target: targetOrRequest, ...normalizeRunArgs(inputOrOptions, options) }
197
+ : (targetOrRequest as { target: RunTarget } & RunOptions);
198
+ const { pathTarget, version } = pathTargetFromRunTarget(request.target);
199
+ const query = runQuery({
200
+ waitForCompletion: request.waitForCompletion,
201
+ version,
202
+ });
203
+
204
+ if (hasFileInput(request.input)) {
205
+ const { formData } = await buildRunMultipart({
206
+ input: request.input,
207
+ overrides: request.overrides,
208
+ });
209
+ return this._request<RunStartResponse>(
210
+ () =>
211
+ this.client.post({
212
+ url: `/api/v1/run/${encodeURIComponent(pathTarget)}`,
213
+ query,
214
+ body: formData,
215
+ bodySerializer: null,
216
+ headers: { 'Content-Type': null },
217
+ signal: request.signal,
218
+ }) as Promise<OperationResult<RunStartResponse>>
219
+ );
220
+ }
221
+
222
+ const body = buildRunJsonBody(request.input, request.overrides);
223
+ return this._request<RunStartResponse>(
224
+ () =>
225
+ runStartWithTarget({
226
+ client: this.client,
227
+ path: { target: pathTarget },
228
+ query,
229
+ body,
230
+ signal: request.signal,
231
+ }) as Promise<OperationResult<RunStartResponse>>
232
+ );
233
+ }
234
+
235
+ async rerun(runId: string, options: RerunOptions = {}): Promise<Record<string, unknown>> {
236
+ return this._request<Record<string, unknown>>(
237
+ () =>
238
+ this.client.post({
239
+ url: '/api/v1/runs/{id}/rerun',
240
+ path: { id: runId },
241
+ query:
242
+ options.waitForCompletion !== undefined
243
+ ? { wait_for_completion: options.waitForCompletion }
244
+ : undefined,
245
+ body:
246
+ options.version && options.version !== 'latest'
247
+ ? { sourceRef: options.version }
248
+ : undefined,
249
+ signal: options.signal,
250
+ }) as Promise<OperationResult<Record<string, unknown>>>
251
+ );
252
+ }
253
+
138
254
  /**
139
255
  * Run an operation with automatic retries on 5xx / 429 / network errors,
140
256
  * and centralized error mapping into typed `EigenpalError` subclasses.
@@ -208,6 +324,39 @@ export class EigenpalClient {
208
324
  }
209
325
  }
210
326
 
327
+ function pathTargetFromRunTarget(target: RunTarget): { pathTarget: string; version?: string } {
328
+ if (typeof target === 'string') {
329
+ const [pathTarget, version, extra] = target.split('@');
330
+ if (!pathTarget || version === '' || extra !== undefined) {
331
+ throw new EigenpalError('Run target strings must be <target> or <target>@<version>.', {
332
+ status: 0,
333
+ });
334
+ }
335
+ return { pathTarget, version: version && version !== 'latest' ? version : undefined };
336
+ }
337
+ const idOrSlug = target.slug ?? target.id;
338
+ if (!idOrSlug) {
339
+ throw new EigenpalError('Run target objects require `slug` or `id`.', { status: 0 });
340
+ }
341
+ const root = target.type === 'agent' ? 'agents' : 'workflows';
342
+ const name = idOrSlug.includes('.') ? idOrSlug : `${root}.${idOrSlug.split('/').join('.')}`;
343
+ return {
344
+ pathTarget: name,
345
+ version: target.version && target.version !== 'latest' ? target.version : undefined,
346
+ };
347
+ }
348
+
349
+ function runQuery(options: {
350
+ waitForCompletion?: number;
351
+ version?: string;
352
+ }): { wait_for_completion?: number; version?: string } | undefined {
353
+ const query: { wait_for_completion?: number; version?: string } = {};
354
+ if (options.waitForCompletion !== undefined)
355
+ query.wait_for_completion = options.waitForCompletion;
356
+ if (options.version) query.version = options.version;
357
+ return Object.keys(query).length > 0 ? query : undefined;
358
+ }
359
+
211
360
  function assertJsonResponse(response: Response): void {
212
361
  // 204 No Content has no body — accept silently.
213
362
  if (response.status === 204) return;
@@ -224,6 +373,26 @@ function assertJsonResponse(response: Response): void {
224
373
  );
225
374
  }
226
375
 
376
+ function normalizeRunArgs(
377
+ inputOrOptions: RunInput | RunOptions,
378
+ options: RunCallOptions
379
+ ): RunOptions {
380
+ if (Object.keys(options).length > 0) {
381
+ return { ...options, input: inputOrOptions as RunInput };
382
+ }
383
+ if (looksLikeRunOptions(inputOrOptions)) {
384
+ return inputOrOptions;
385
+ }
386
+ return { input: inputOrOptions as RunInput };
387
+ }
388
+
389
+ function looksLikeRunOptions(value: unknown): value is RunOptions {
390
+ if (!value || typeof value !== 'object') return false;
391
+ return (
392
+ 'input' in value || 'waitForCompletion' in value || 'overrides' in value || 'signal' in value
393
+ );
394
+ }
395
+
227
396
  function isRetriableStatus(status: number): boolean {
228
397
  return status >= 500 || status === 429;
229
398
  }
@@ -7,7 +7,6 @@ export {
7
7
  agentsFilesUploadBatch,
8
8
  agentsGet,
9
9
  agentsList,
10
- agentsRun,
11
10
  agentsTriggersEmailCreateAlias,
12
11
  agentsTriggersEmailDeleteAlias,
13
12
  agentsTriggersEmailGet,
@@ -17,6 +16,7 @@ export {
17
16
  agentsUpdate,
18
17
  agentsVersionsList,
19
18
  automationsSync,
19
+ runStartWithTarget,
20
20
  runsArtifactGet,
21
21
  runsCancel,
22
22
  runsComparisonGet,
@@ -46,7 +46,6 @@ export {
46
46
  sourceSecretsEncrypt,
47
47
  workflowsGet,
48
48
  workflowsList,
49
- workflowsRun,
50
49
  workflowsVersionsList,
51
50
  type Options,
52
51
  } from './sdk.gen';
@@ -77,11 +76,6 @@ export type {
77
76
  AgentsListErrors,
78
77
  AgentsListResponse,
79
78
  AgentsListResponses,
80
- AgentsRunData,
81
- AgentsRunError,
82
- AgentsRunErrors,
83
- AgentsRunResponse,
84
- AgentsRunResponses,
85
79
  AgentsTriggersEmailCreateAliasData,
86
80
  AgentsTriggersEmailCreateAliasError,
87
81
  AgentsTriggersEmailCreateAliasErrors,
@@ -142,17 +136,20 @@ export type {
142
136
  PatchAgentBody,
143
137
  PatchAgentResponse,
144
138
  RawSourceResponse,
145
- RunAgentBody,
146
- RunAgentResponse,
147
139
  RunEnvelope,
148
140
  RunFeedbackRequest,
149
141
  RunFilesResponse,
150
142
  RunRerunRequest,
151
143
  RunRerunResponse,
152
144
  RunResumeResponse,
145
+ RunStartResponse,
146
+ RunStartWithTargetData,
147
+ RunStartWithTargetError,
148
+ RunStartWithTargetErrors,
149
+ RunStartWithTargetResponse,
150
+ RunStartWithTargetResponses,
153
151
  RunSummary,
154
- RunWorkflowBody,
155
- RunWorkflowResponse,
152
+ RunTargetInputBody,
156
153
  RunsArtifactGetData,
157
154
  RunsArtifactGetError,
158
155
  RunsArtifactGetErrors,
@@ -308,11 +305,6 @@ export type {
308
305
  WorkflowsListErrors,
309
306
  WorkflowsListResponse,
310
307
  WorkflowsListResponses,
311
- WorkflowsRunData,
312
- WorkflowsRunError,
313
- WorkflowsRunErrors,
314
- WorkflowsRunResponse,
315
- WorkflowsRunResponses,
316
308
  WorkflowsVersionsListData,
317
309
  WorkflowsVersionsListError,
318
310
  WorkflowsVersionsListErrors,
@@ -24,9 +24,6 @@ import type {
24
24
  AgentsListData,
25
25
  AgentsListErrors,
26
26
  AgentsListResponses,
27
- AgentsRunData,
28
- AgentsRunErrors,
29
- AgentsRunResponses,
30
27
  AgentsTriggersEmailCreateAliasData,
31
28
  AgentsTriggersEmailCreateAliasErrors,
32
29
  AgentsTriggersEmailCreateAliasResponses,
@@ -114,6 +111,9 @@ import type {
114
111
  RunsResumeData,
115
112
  RunsResumeErrors,
116
113
  RunsResumeResponses,
114
+ RunStartWithTargetData,
115
+ RunStartWithTargetErrors,
116
+ RunStartWithTargetResponses,
117
117
  RunsTraceGetData,
118
118
  RunsTraceGetErrors,
119
119
  RunsTraceGetResponses,
@@ -141,9 +141,6 @@ import type {
141
141
  WorkflowsListData,
142
142
  WorkflowsListErrors,
143
143
  WorkflowsListResponses,
144
- WorkflowsRunData,
145
- WorkflowsRunErrors,
146
- WorkflowsRunResponses,
147
144
  WorkflowsVersionsListData,
148
145
  WorkflowsVersionsListErrors,
149
146
  WorkflowsVersionsListResponses,
@@ -253,24 +250,6 @@ export const agentsUpdate = <ThrowOnError extends boolean = false>(
253
250
  },
254
251
  });
255
252
 
256
- /**
257
- * Run an agent
258
- *
259
- * Enqueues an agent run. Returns 202 with `{ runId }` by default. Pass `wait_for_completion=<seconds>` to hold the connection until the run reaches a terminal state. File inputs are uploaded as multipart/form-data.
260
- */
261
- export const agentsRun = <ThrowOnError extends boolean = false>(
262
- options: Options<AgentsRunData, ThrowOnError>
263
- ) =>
264
- (options.client ?? client).post<AgentsRunResponses, AgentsRunErrors, ThrowOnError>({
265
- security: [{ scheme: 'bearer', type: 'http' }],
266
- url: '/api/v1/agents/{agentId}/run',
267
- ...options,
268
- headers: {
269
- 'Content-Type': 'application/json',
270
- ...options.headers,
271
- },
272
- });
273
-
274
253
  /**
275
254
  * Delete an agent email alias
276
255
  *
@@ -455,6 +434,28 @@ export const automationsSync = <ThrowOnError extends boolean = false>(
455
434
  ...options,
456
435
  });
457
436
 
437
+ /**
438
+ * Start a workflow or agent run
439
+ *
440
+ * Starts a run for a workflow or agent target. The target lives in the URL path; the optional `version` query parameter selects a release/ref and defaults to `latest`. The request body is the input object; a reserved `_overrides` key (workflow targets only) carries per-step output overrides for replay. Run provenance may be declared with the `X-Eigenpal-Trigger` header (`api` or `cli`).
441
+ */
442
+ export const runStartWithTarget = <ThrowOnError extends boolean = false>(
443
+ options: Options<RunStartWithTargetData, ThrowOnError>
444
+ ) =>
445
+ (options.client ?? client).post<
446
+ RunStartWithTargetResponses,
447
+ RunStartWithTargetErrors,
448
+ ThrowOnError
449
+ >({
450
+ security: [{ scheme: 'bearer', type: 'http' }],
451
+ url: '/api/v1/run/{target}',
452
+ ...options,
453
+ headers: {
454
+ 'Content-Type': 'application/json',
455
+ ...options.headers,
456
+ },
457
+ });
458
+
458
459
  /**
459
460
  * Download run artifact
460
461
  *
@@ -886,24 +887,6 @@ export const workflowsGet = <ThrowOnError extends boolean = false>(
886
887
  ...options,
887
888
  });
888
889
 
889
- /**
890
- * Execute a workflow (async or sync)
891
- *
892
- * Enqueues a workflow execution. Returns 201 with `{ executionId }` by default. Pass `wait_for_completion=<seconds>` (max 60) to hold the connection until the run reaches a terminal state; the body then also includes `status`, `result`, and `error`. File inputs are uploaded as `multipart/form-data` (each file as a top-level form field; `_json` field carries scalar inputs).
893
- */
894
- export const workflowsRun = <ThrowOnError extends boolean = false>(
895
- options: Options<WorkflowsRunData, ThrowOnError>
896
- ) =>
897
- (options.client ?? client).post<WorkflowsRunResponses, WorkflowsRunErrors, ThrowOnError>({
898
- security: [{ scheme: 'bearer', type: 'http' }],
899
- url: '/api/v1/workflows/{id}/run',
900
- ...options,
901
- headers: {
902
- 'Content-Type': 'application/json',
903
- ...options.headers,
904
- },
905
- });
906
-
907
890
  /**
908
891
  * List tagged versions for a workflow
909
892
  *