@eigenpal/sdk 0.6.17 → 0.7.0

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,15 @@
1
1
  # @eigenpal/sdk
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 963fd6c: Unify run detail on `GET /api/v1/runs/{id}`: return the canonical Run object directly (no `{ run: ... }` envelope) and merge expanded fields in-place via documented `expand` tokens. Remove the session-only `expand=internal` dashboard escape hatch; SDKs and CLI now use explicit expand lists.
8
+
9
+ ### Patch Changes
10
+
11
+ - 12c00d8: Docs: clearer wording in the file-input and TypeScript-runtime sections. No API or behavior changes.
12
+
3
13
  ## 0.6.17
4
14
 
5
15
  ### 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.output);
32
+ console.log(result.finished, result.output);
33
33
  ```
34
34
 
35
35
  ## Authentication
@@ -60,8 +60,8 @@ const client = new EigenpalClient({
60
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 { runId }.
64
- const { runId } = await client.run('workflows.extract-invoice', {
63
+ // Async: returns immediately with { id }.
64
+ const { id: runId } = await client.run('workflows.extract-invoice', {
65
65
  contract_document: file,
66
66
  });
67
67
 
@@ -71,7 +71,7 @@ const result = await client.run(
71
71
  { contract_document: file },
72
72
  { waitForCompletion: 60 }
73
73
  );
74
- console.log(result.status, result.output);
74
+ console.log(result.finished, 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', {
@@ -112,11 +112,18 @@ const runs = await client.runs.list({
112
112
  status: 'failed,cancelled',
113
113
  });
114
114
 
115
- const run = await client.runs.get(runId, { include: 'detail' });
116
- await client.runs.cancel(runId);
117
-
118
- const status = await client.runs.get(runId);
119
- // { run: { id, status, output?, error?, createdAt, completedAt? } }
115
+ const run = await client.runs.get(runId);
116
+ // { id, type, finished, output, files, error, timing, ... }
117
+
118
+ // Add heavier optional sections with `expand`.
119
+ const withUsage = await client.runs.get(runId, { expand: ['usage', 'execution'] });
120
+ console.log(
121
+ withUsage.output,
122
+ withUsage.files,
123
+ withUsage.error,
124
+ withUsage.usage,
125
+ withUsage.execution
126
+ );
120
127
 
121
128
  const list = await client.runs.list({
122
129
  type: 'workflow',
@@ -146,7 +153,7 @@ await client.workflows.versions('extract-invoice');
146
153
  await client.agents.list({ search: 'invoice' });
147
154
  await client.agents.get('invoice-agent');
148
155
 
149
- const { runId: agentRunId } = await client.run('agents.invoice-agent', {
156
+ const { id: agentRunId } = await client.run('agents.invoice-agent', {
150
157
  invoice: file,
151
158
  });
152
159
 
@@ -181,7 +188,7 @@ try {
181
188
  const result = await client.workflows.executions.runAndWait('extract-invoice', {
182
189
  language: 'en',
183
190
  });
184
- console.log(result.status, result.output);
191
+ console.log(result.finished, result.output);
185
192
  } catch (err) {
186
193
  if (err instanceof EigenpalValidationError) {
187
194
  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.17",
3
+ "version": "0.7.0",
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,7 +1,9 @@
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';
4
- import type { ApiErrorEnvelope } from './generated/types.gen';
3
+ import type {
4
+ ApiErrorEnvelope,
5
+ RunStartResponse as GeneratedRunStartResponse,
6
+ } from './generated/types.gen';
5
7
  import { buildRunJsonBody, buildRunMultipart, hasFileInput } from './lib/files';
6
8
  import { AgentsResource } from './resources/agents';
7
9
  import { AutomationsResource } from './resources/automations';
@@ -64,28 +66,27 @@ export type RunTarget =
64
66
 
65
67
  export type RunInput = Record<string, unknown>;
66
68
 
67
- export interface RunOptions {
68
- input?: RunInput;
69
+ /** Third argument to `client.run()` — transport knobs, not workflow/agent input. */
70
+ export interface RunCallOptions {
69
71
  waitForCompletion?: number;
70
72
  overrides?: { steps?: Record<string, Record<string, unknown>> };
71
73
  signal?: AbortSignal;
72
74
  }
73
75
 
74
- export type RunCallOptions = Omit<RunOptions, 'input'>;
75
-
76
76
  export interface RerunOptions {
77
77
  version?: 'latest' | 'original' | string;
78
78
  waitForCompletion?: number;
79
79
  signal?: AbortSignal;
80
80
  }
81
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
- };
82
+ /**
83
+ * Run-start response — async bodies are `{ id, type, finished: false }` (201);
84
+ * wait-expired bodies use the same shape (202); sync terminal completion matches
85
+ * `client.runs.get(id)` (200).
86
+ * Aliases the generated OpenAPI type so the handwritten and generated surfaces
87
+ * can never diverge.
88
+ */
89
+ export type RunStartResponse = GeneratedRunStartResponse;
89
90
 
90
91
  /**
91
92
  * The EigenPal SDK client.
@@ -97,15 +98,14 @@ export type RunStartResponse = Record<string, unknown> & {
97
98
  * const client = new EigenpalClient();
98
99
  *
99
100
  * // Async — enqueue and poll later.
100
- * const { runId } = await client.run('workflows.extract-invoice', {
101
- * input: { language: 'en' },
102
- * });
101
+ * const { id } = await client.run('workflows.extract-invoice', { language: 'en' });
103
102
  *
104
103
  * // Sync (server holds the connection up to 60s).
105
- * const result = await client.run('workflows.extract-invoice', {
106
- * input: { language: 'en' },
107
- * waitForCompletion: 60,
108
- * });
104
+ * const result = await client.run(
105
+ * 'workflows.extract-invoice',
106
+ * { language: 'en' },
107
+ * { waitForCompletion: 60 }
108
+ * );
109
109
  *
110
110
  * // Client-side polling for long-running executions (default 5min cap).
111
111
  * const final = await client.workflows.executions.runAndWait('wf_abc', { language: 'en' });
@@ -177,77 +177,65 @@ export class EigenpalClient {
177
177
  async run(
178
178
  target: RunTarget,
179
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
180
  options: RunCallOptions = {}
188
181
  ): 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);
182
+ assertRunTarget(target);
183
+ assertInputNotOptionsBag(input);
184
+
185
+ const { pathTarget, version } = pathTargetFromRunTarget(target);
199
186
  const query = runQuery({
200
- waitForCompletion: request.waitForCompletion,
187
+ waitForCompletion: options.waitForCompletion,
201
188
  version,
202
189
  });
203
190
 
204
- if (hasFileInput(request.input)) {
191
+ if (hasFileInput(input)) {
205
192
  const { formData } = await buildRunMultipart({
206
- input: request.input,
207
- overrides: request.overrides,
193
+ target: pathTarget,
194
+ input,
195
+ overrides: options.overrides,
208
196
  });
209
197
  return this._request<RunStartResponse>(
210
198
  () =>
211
199
  this.client.post({
212
- url: `/api/v1/run/${encodeURIComponent(pathTarget)}`,
200
+ url: '/api/v1/runs',
213
201
  query,
214
202
  body: formData,
215
203
  bodySerializer: null,
216
204
  headers: { 'Content-Type': null },
217
- signal: request.signal,
205
+ signal: options.signal,
218
206
  }) as Promise<OperationResult<RunStartResponse>>
219
207
  );
220
208
  }
221
209
 
222
- const body = buildRunJsonBody(request.input, request.overrides);
210
+ const body = buildRunJsonBody(pathTarget, input, options.overrides);
223
211
  return this._request<RunStartResponse>(
224
212
  () =>
225
- runStartWithTarget({
226
- client: this.client,
227
- path: { target: pathTarget },
213
+ this.client.post({
214
+ url: '/api/v1/runs',
228
215
  query,
229
216
  body,
230
- signal: request.signal,
217
+ signal: options.signal,
231
218
  }) as Promise<OperationResult<RunStartResponse>>
232
219
  );
233
220
  }
234
221
 
235
- async rerun(runId: string, options: RerunOptions = {}): Promise<Record<string, unknown>> {
236
- return this._request<Record<string, unknown>>(
222
+ async rerun(runId: string, options: RerunOptions = {}): Promise<RunStartResponse> {
223
+ const query: { version?: string; wait_for_completion?: number } = {};
224
+ if (options.version && options.version !== 'latest') {
225
+ query.version = options.version;
226
+ }
227
+ if (options.waitForCompletion !== undefined) {
228
+ query.wait_for_completion = options.waitForCompletion;
229
+ }
230
+
231
+ return this._request<RunStartResponse>(
237
232
  () =>
238
233
  this.client.post({
239
234
  url: '/api/v1/runs/{id}/rerun',
240
235
  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,
236
+ query: Object.keys(query).length > 0 ? query : undefined,
249
237
  signal: options.signal,
250
- }) as Promise<OperationResult<Record<string, unknown>>>
238
+ }) as Promise<OperationResult<RunStartResponse>>
251
239
  );
252
240
  }
253
241
 
@@ -338,14 +326,26 @@ function pathTargetFromRunTarget(target: RunTarget): { pathTarget: string; versi
338
326
  if (!idOrSlug) {
339
327
  throw new EigenpalError('Run target objects require `slug` or `id`.', { status: 0 });
340
328
  }
341
- const root = target.type === 'agent' ? 'agents' : 'workflows';
342
- const name = idOrSlug.includes('.') ? idOrSlug : `${root}.${idOrSlug.split('/').join('.')}`;
329
+ const name =
330
+ target.type === 'agent'
331
+ ? agentPathTarget(idOrSlug)
332
+ : `workflows.${idOrSlug.split('/').join('.')}`;
343
333
  return {
344
334
  pathTarget: name,
345
335
  version: target.version && target.version !== 'latest' ? target.version : undefined,
346
336
  };
347
337
  }
348
338
 
339
+ function agentPathTarget(idOrSlug: string): string {
340
+ if (!idOrSlug.includes('.')) return `agents.${idOrSlug.split('/').join('.')}`;
341
+ if (!idOrSlug.startsWith('agents.')) {
342
+ throw new EigenpalError(`Agent target must be rooted at "agents.", got "${idOrSlug}".`, {
343
+ status: 0,
344
+ });
345
+ }
346
+ return idOrSlug;
347
+ }
348
+
349
349
  function runQuery(options: {
350
350
  waitForCompletion?: number;
351
351
  version?: string;
@@ -373,24 +373,24 @@ function assertJsonResponse(response: Response): void {
373
373
  );
374
374
  }
375
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;
376
+ function assertRunTarget(target: RunTarget): void {
377
+ if (typeof target === 'object' && target !== null && 'target' in target) {
378
+ throw new EigenpalError(
379
+ 'Pass the run target as the first argument to client.run(target, input?, options?). ' +
380
+ 'Do not wrap it in { target }.',
381
+ { status: 0 }
382
+ );
385
383
  }
386
- return { input: inputOrOptions as RunInput };
387
384
  }
388
385
 
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
- );
386
+ function assertInputNotOptionsBag(input: RunInput | undefined): void {
387
+ if (!input || typeof input !== 'object') return;
388
+ if ('waitForCompletion' in input || 'overrides' in input || 'signal' in input) {
389
+ throw new EigenpalError(
390
+ 'Pass workflow/agent input as the second argument and { waitForCompletion, overrides, signal } as the third.',
391
+ { status: 0 }
392
+ );
393
+ }
394
394
  }
395
395
 
396
396
  function isRetriableStatus(status: number): boolean {
@@ -37,7 +37,7 @@ export const createClient = (config: Config = {}): Client => {
37
37
  ThrowOnError extends boolean = boolean,
38
38
  Url extends string = string,
39
39
  >(
40
- options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>
40
+ options: RequestOptions<TData, TResponseStyle, ThrowOnError, Url>,
41
41
  ) => {
42
42
  const opts = {
43
43
  ..._config,
@@ -1,12 +1,12 @@
1
1
  // This file is auto-generated by @hey-api/openapi-ts
2
2
 
3
3
  export type { Auth } from '../core/auth.gen';
4
+ export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
4
5
  export {
5
6
  formDataBodySerializer,
6
7
  jsonBodySerializer,
7
8
  urlSearchParamsBodySerializer,
8
9
  } from '../core/bodySerializer.gen';
9
- export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
10
10
  export { buildClientParams } from '../core/params.gen';
11
11
  export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
12
12
  export { createClient } from './client.gen';
@@ -1,7 +1,10 @@
1
1
  // This file is auto-generated by @hey-api/openapi-ts
2
2
 
3
3
  import type { Auth } from '../core/auth.gen';
4
- import type { ServerSentEventsOptions, ServerSentEventsResult } from '../core/serverSentEvents.gen';
4
+ import type {
5
+ ServerSentEventsOptions,
6
+ ServerSentEventsResult,
7
+ } from '../core/serverSentEvents.gen';
5
8
  import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen';
6
9
  import type { Middleware } from './utils.gen';
7
10
 
@@ -143,7 +146,7 @@ type MethodFn = <
143
146
  ThrowOnError extends boolean = false,
144
147
  TResponseStyle extends ResponseStyle = 'fields',
145
148
  >(
146
- options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>
149
+ options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>,
147
150
  ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
148
151
 
149
152
  type SseFn = <
@@ -152,7 +155,7 @@ type SseFn = <
152
155
  ThrowOnError extends boolean = false,
153
156
  TResponseStyle extends ResponseStyle = 'fields',
154
157
  >(
155
- options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>
158
+ options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>,
156
159
  ) => Promise<ServerSentEventsResult<TData, TError>>;
157
160
 
158
161
  type RequestFn = <
@@ -162,7 +165,7 @@ type RequestFn = <
162
165
  TResponseStyle extends ResponseStyle = 'fields',
163
166
  >(
164
167
  options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
165
- Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>
168
+ Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>,
166
169
  ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
167
170
 
168
171
  type BuildUrlFn = <
@@ -173,7 +176,7 @@ type BuildUrlFn = <
173
176
  url: string;
174
177
  },
175
178
  >(
176
- options: TData & Options<TData>
179
+ options: TData & Options<TData>,
177
180
  ) => string;
178
181
 
179
182
  export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
@@ -189,7 +192,7 @@ export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn>
189
192
  * to ensure your client always has the correct values.
190
193
  */
191
194
  export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
192
- override?: Config<ClientOptions & T>
195
+ override?: Config<ClientOptions & T>,
193
196
  ) => Config<Required<ClientOptions> & T>;
194
197
 
195
198
  export interface TDataShape {
@@ -103,7 +103,7 @@ const checkForExistence = (
103
103
  options: Pick<RequestOptions, 'auth' | 'query'> & {
104
104
  headers: Headers;
105
105
  },
106
- name?: string
106
+ name?: string,
107
107
  ): boolean => {
108
108
  if (!name) {
109
109
  return false;
@@ -208,7 +208,7 @@ export const mergeHeaders = (
208
208
  // content value in OpenAPI specification is 'application/json'
209
209
  mergedHeaders.set(
210
210
  key,
211
- typeof value === 'object' ? JSON.stringify(value) : (value as string)
211
+ typeof value === 'object' ? JSON.stringify(value) : (value as string),
212
212
  );
213
213
  }
214
214
  }
@@ -222,7 +222,7 @@ type ErrInterceptor<Err, Res, Req, Options> = (
222
222
  response: Res | undefined,
223
223
  /** request may be undefined, because error may be from building the request object itself */
224
224
  request: Req | undefined,
225
- options: Options
225
+ options: Options,
226
226
  ) => Err | Promise<Err>;
227
227
 
228
228
  type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
@@ -230,7 +230,7 @@ type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Pr
230
230
  type ResInterceptor<Res, Req, Options> = (
231
231
  response: Res,
232
232
  request: Req,
233
- options: Options
233
+ options: Options,
234
234
  ) => Res | Promise<Res>;
235
235
 
236
236
  class Interceptors<Interceptor> {
@@ -308,7 +308,7 @@ const defaultHeaders = {
308
308
  };
309
309
 
310
310
  export const createConfig = <T extends ClientOptions = ClientOptions>(
311
- override: Config<Omit<ClientOptions, keyof T> & T> = {}
311
+ override: Config<Omit<ClientOptions, keyof T> & T> = {},
312
312
  ): Config<Omit<ClientOptions, keyof T> & T> => ({
313
313
  ...jsonBodySerializer,
314
314
  headers: defaultHeaders,
@@ -13,10 +13,6 @@ import type { ClientOptions as ClientOptions2 } from './types.gen';
13
13
  * `setConfig()`. This is useful for example if you're using Next.js
14
14
  * to ensure your client always has the correct values.
15
15
  */
16
- export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (
17
- override?: Config<ClientOptions & T>
18
- ) => Config<Required<ClientOptions> & T>;
16
+ export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
19
17
 
20
- export const client = createClient(
21
- createClientConfig(createConfig<ClientOptions2>({ baseUrl: 'https://studio.eigenpal.com' }))
22
- );
18
+ export const client = createClient(createClientConfig(createConfig<ClientOptions2>({ baseUrl: 'https://studio.eigenpal.com' })));
@@ -21,7 +21,7 @@ export interface Auth {
21
21
 
22
22
  export const getAuthToken = async (
23
23
  auth: Auth,
24
- callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken
24
+ callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
25
25
  ): Promise<string | undefined> => {
26
26
  const token = typeof callback === 'function' ? await callback(auth) : callback;
27
27
 
@@ -117,7 +117,7 @@ export const serializePrimitiveParam = ({
117
117
 
118
118
  if (typeof value === 'object') {
119
119
  throw new Error(
120
- 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.'
120
+ 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',
121
121
  );
122
122
  }
123
123
 
@@ -164,7 +164,7 @@ export const serializeObjectParam = ({
164
164
  allowReserved,
165
165
  name: style === 'deepObject' ? `${name}[${key}]` : key,
166
166
  value: v as string,
167
- })
167
+ }),
168
168
  )
169
169
  .join(separator);
170
170
  return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
@@ -57,7 +57,7 @@ export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
57
57
  style,
58
58
  value: value as Record<string, unknown>,
59
59
  valueOnly: true,
60
- })
60
+ }),
61
61
  );
62
62
  continue;
63
63
  }
@@ -68,13 +68,13 @@ export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
68
68
  `;${serializePrimitiveParam({
69
69
  name,
70
70
  value: value as string,
71
- })}`
71
+ })}`,
72
72
  );
73
73
  continue;
74
74
  }
75
75
 
76
76
  const replaceValue = encodeURIComponent(
77
- style === 'label' ? `.${value as string}` : (value as string)
77
+ style === 'label' ? `.${value as string}` : (value as string),
78
78
  );
79
79
  url = url.replace(match, replaceValue);
80
80
  }