@usestatemachines/sdk 0.7.1 → 0.8.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.
Files changed (77) hide show
  1. package/README.md +75 -30
  2. package/agents/SKILL.md +7 -6
  3. package/agents/index.d.ts +2 -0
  4. package/agents/index.js +6 -4
  5. package/agents/llms.txt +6 -4
  6. package/esm/extensions/client.d.ts +11 -7
  7. package/esm/extensions/client.js +32 -49
  8. package/esm/extensions/credentials.d.ts +25 -8
  9. package/esm/extensions/credentials.js +75 -40
  10. package/esm/extensions/environment.d.ts +1 -1
  11. package/esm/extensions/errors.js +1 -1
  12. package/esm/extensions/index.d.ts +2 -2
  13. package/esm/extensions/yaml.js +14 -12
  14. package/esm/funcs/environments-creators.d.ts +11 -0
  15. package/esm/funcs/environments-creators.js +90 -0
  16. package/esm/funcs/environments-list.js +2 -0
  17. package/esm/funcs/requests-list.js +5 -1
  18. package/esm/funcs/requests-stats.js +5 -1
  19. package/esm/lib/config.d.ts +2 -2
  20. package/esm/lib/config.js +2 -2
  21. package/esm/models/app-entry.d.ts +8 -0
  22. package/esm/models/app-entry.js +11 -0
  23. package/esm/models/create-environment-app.d.ts +25 -0
  24. package/esm/models/create-environment-app.js +14 -0
  25. package/esm/models/create-environment.d.ts +3 -26
  26. package/esm/models/create-environment.js +2 -19
  27. package/esm/models/credential.d.ts +50 -0
  28. package/esm/models/credential.js +60 -0
  29. package/esm/models/credentials.d.ts +26 -5
  30. package/esm/models/credentials.js +20 -3
  31. package/esm/models/environment-failure.d.ts +3 -2
  32. package/esm/models/environment-failure.js +3 -2
  33. package/esm/models/environment.d.ts +4 -1
  34. package/esm/models/environment.js +2 -1
  35. package/esm/models/error.d.ts +1 -0
  36. package/esm/models/error.js +1 -0
  37. package/esm/models/index.d.ts +6 -1
  38. package/esm/models/index.js +6 -1
  39. package/esm/models/mcp-server.d.ts +11 -0
  40. package/esm/models/mcp-server.js +16 -0
  41. package/esm/models/mcp-tool.d.ts +12 -0
  42. package/esm/models/mcp-tool.js +16 -0
  43. package/esm/models/me.d.ts +2 -0
  44. package/esm/models/me.js +2 -0
  45. package/esm/models/operations/create-credentials.d.ts +2 -0
  46. package/esm/models/operations/create-credentials.js +1 -0
  47. package/esm/models/operations/get-request-stats.d.ts +10 -2
  48. package/esm/models/operations/get-request-stats.js +5 -1
  49. package/esm/models/operations/index.d.ts +1 -0
  50. package/esm/models/operations/index.js +1 -0
  51. package/esm/models/operations/list-environment-creators.d.ts +23 -0
  52. package/esm/models/operations/list-environment-creators.js +20 -0
  53. package/esm/models/operations/list-environments.d.ts +5 -1
  54. package/esm/models/operations/list-environments.js +2 -0
  55. package/esm/models/operations/list-requests.d.ts +10 -2
  56. package/esm/models/operations/list-requests.js +5 -1
  57. package/esm/models/request-detail.d.ts +8 -1
  58. package/esm/models/request-detail.js +5 -1
  59. package/esm/models/request-stats.d.ts +8 -0
  60. package/esm/models/request-stats.js +9 -0
  61. package/esm/models/request.d.ts +8 -1
  62. package/esm/models/request.js +5 -1
  63. package/esm/models/service.d.ts +25 -0
  64. package/esm/models/service.js +28 -0
  65. package/esm/models/snapshot.d.ts +7 -0
  66. package/esm/models/snapshot.js +3 -0
  67. package/esm/models/version.d.ts +2 -2
  68. package/esm/models/version.js +2 -2
  69. package/esm/sdk/environments.d.ts +1 -0
  70. package/esm/sdk/environments.js +4 -0
  71. package/esm/types/discriminated-union.d.ts +24 -0
  72. package/esm/types/discriminated-union.js +60 -0
  73. package/esm/types/smart-union.js +2 -1
  74. package/openapi.json +596 -116
  75. package/package.json +1 -1
  76. package/esm/models/api.d.ts +0 -17
  77. package/esm/models/api.js +0 -21
@@ -2,7 +2,7 @@ import { SDK_METADATA } from '../lib/config.js';
2
2
  import { HTTPClient } from '../lib/http.js';
3
3
  import { StateMachines as Generated } from '../sdk/sdk.js';
4
4
  import { bindCredentials } from './credentials.js';
5
- import { CallerAbortedError, StateMachinesError, toStateMachinesError, } from './errors.js';
5
+ import { CallerAbortedError, toStateMachinesError } from './errors.js';
6
6
  import { linkSignal } from './signal.js';
7
7
  import { environmentAt, poll, snapshotAt, } from './wait.js';
8
8
  export class StateMachines {
@@ -10,10 +10,9 @@ export class StateMachines {
10
10
  #fetch;
11
11
  #workspaceId;
12
12
  #callSignals = new Map();
13
- #apis = new Map();
14
13
  #lastCall = 0;
15
14
  constructor(options = {}) {
16
- const apiKey = options.apiKey ?? environmentApiKey();
15
+ const apiKey = options.apiKey ?? environmentVariable('STATEMACHINES_API_KEY');
17
16
  if (!apiKey) {
18
17
  throw new TypeError('Pass apiKey or set STATEMACHINES_API_KEY.');
19
18
  }
@@ -25,6 +24,7 @@ export class StateMachines {
25
24
  if (!(attemptTimeoutMs > 0 && Number.isFinite(attemptTimeoutMs))) {
26
25
  throw new RangeError('attemptTimeoutMs must be a positive, finite number.');
27
26
  }
27
+ const baseUrl = baseUrlOrigin(options.baseUrl ?? environmentVariable('STATEMACHINES_BASE_URL'));
28
28
  const fetcher = options.fetch;
29
29
  // The arrow keeps `this` unbound; runtimes such as workerd reject fetch called on another object.
30
30
  const httpClient = new HTTPClient(fetcher ? { fetcher: (input) => fetcher(input) } : {});
@@ -35,10 +35,10 @@ export class StateMachines {
35
35
  apiKey,
36
36
  userAgent: `statemachines-sdk-ts/${SDK_METADATA.sdkVersion}`,
37
37
  httpClient,
38
- ...(options.baseUrl ? { serverURL: options.baseUrl } : {}),
38
+ ...(baseUrl === undefined ? {} : { serverURL: baseUrl }),
39
39
  });
40
40
  }
41
- /** The caller: its principal, organization, workspace, permissions and limits. */
41
+ /** The caller: its credential, principal, organization, workspace, permissions and limits. */
42
42
  me() {
43
43
  return this.#call(undefined, (call) => this.#sdk.me(call));
44
44
  }
@@ -80,7 +80,7 @@ export class StateMachines {
80
80
  */
81
81
  wait: async (environmentId, options) => this.#bind(await poll(environmentId, (signal) => this.#read(signal, (call) => this.#sdk.environments.get({ environmentId }, call)), environmentAt(options.status), options)),
82
82
  /** Credentials for one app of the environment. */
83
- connect: (environmentId, app, options = {}) => this.#connect(environmentId, null, app, options),
83
+ connect: (environmentId, appName, options = {}) => this.#connect(environmentId, appName, options),
84
84
  };
85
85
  snapshots = {
86
86
  /** Creates a snapshot of a running environment and, unless `wait` is false, waits until it is `ready`. */
@@ -129,51 +129,18 @@ export class StateMachines {
129
129
  ? { ...input, workspaceId: this.#workspaceId }
130
130
  : input;
131
131
  }
132
- async #connect(environmentId, known, app, options) {
133
- const body = options.actorId === undefined ? {} : { actorId: options.actorId };
134
- const [credentials, apis] = await Promise.all([
135
- this.#call(undefined, (call) => this.#sdk.environments.connect({ environmentId, appName: app, body }, call)),
136
- (async () => {
137
- const environment = known ?? (await this.environments.get(environmentId));
138
- const entry = environment.apps.find(({ name }) => name === app);
139
- return entry ? this.#versionApis(entry.appId, entry.versionId) : [];
140
- })(),
141
- ]);
142
- return bindCredentials(credentials, apis, this.#fetch);
143
- }
144
- /** A version's APIs never change, so each is read once per client. */
145
- #versionApis(appId, versionId) {
146
- let apis = this.#apis.get(versionId);
147
- if (!apis) {
148
- apis = this.#findVersion(appId, versionId);
149
- apis.catch(() => this.#apis.delete(versionId));
150
- this.#apis.set(versionId, apis);
151
- }
152
- return apis;
153
- }
154
- async #findVersion(appId, versionId) {
155
- let cursor;
156
- do {
157
- const page = await this.apps.versions(appId, cursor ? { cursor } : {});
158
- const version = page.data.find(({ id }) => id === versionId);
159
- if (version) {
160
- return version.apis;
161
- }
162
- cursor = page.nextCursor ?? undefined;
163
- } while (cursor);
164
- throw new StateMachinesError({
165
- message: `Version ${versionId} of ${appId} was not found.`,
166
- status: null,
167
- code: 'not_found',
168
- requestId: null,
169
- fields: null,
170
- retryAfterMs: null,
171
- });
132
+ async #connect(environmentId, appName, options) {
133
+ const body = {
134
+ ...(options.actorId === undefined ? {} : { actorId: options.actorId }),
135
+ ...(options.services === undefined ? {} : { services: options.services }),
136
+ };
137
+ const credentials = await this.#call(undefined, (call) => this.#sdk.environments.connect({ environmentId, appName, body }, call));
138
+ return bindCredentials(credentials, this.#fetch);
172
139
  }
173
140
  #bind(data) {
174
141
  const { id } = data;
175
142
  const helpers = {
176
- connect: (app, options = {}) => this.#connect(id, data, app, options),
143
+ connect: (appName, options = {}) => this.#connect(id, appName, options),
177
144
  delete: (options) => this.environments.delete(id, options),
178
145
  refresh: () => this.environments.get(id),
179
146
  snapshots: {
@@ -257,7 +224,23 @@ function waitOptions(options) {
257
224
  ...(options.signal ? { signal: options.signal } : {}),
258
225
  };
259
226
  }
260
- function environmentApiKey() {
227
+ function baseUrlOrigin(value) {
228
+ if (value === undefined) {
229
+ return undefined;
230
+ }
231
+ const origin = value.endsWith('/') ? value.slice(0, -1) : value;
232
+ const url = URL.canParse(origin) ? new URL(origin) : undefined;
233
+ if (!url ||
234
+ /[{}]/.test(origin) ||
235
+ origin !== url.origin ||
236
+ !(url.protocol === 'https:' ||
237
+ (url.protocol === 'http:' &&
238
+ (url.hostname === 'localhost' || url.hostname === '127.0.0.1')))) {
239
+ throw new TypeError('baseUrl or STATEMACHINES_BASE_URL must be an HTTPS origin, or HTTP with localhost or 127.0.0.1.');
240
+ }
241
+ return origin;
242
+ }
243
+ function environmentVariable(name) {
261
244
  const runtime = globalThis;
262
- return runtime.process?.env?.STATEMACHINES_API_KEY;
245
+ return runtime.process?.env?.[name];
263
246
  }
@@ -1,13 +1,30 @@
1
- import type { Api } from '../models/api.js';
2
- import type { Credentials as CredentialsData } from '../models/credentials.js';
3
- /** The API's `Credentials`, plus `fetch` to call the app with them. */
1
+ import type { Credentials as CredentialsData, CredentialsService as CredentialsServiceData } from '../models/credentials.js';
2
+ /** What a client needs to reach one MCP server of a service: send `headers` with every request to `url`. */
3
+ export interface McpServerCredentials {
4
+ url: string;
5
+ headers: Record<string, string>;
6
+ }
7
+ /** One service from the credentials, plus `server` to hand one of its MCP servers to a client. */
8
+ export type ServiceCredentials = CredentialsServiceData & {
9
+ /**
10
+ * The URL of one MCP server the service serves, with the service's headers.
11
+ * Throws a `TypeError` naming the served MCP servers when it serves no MCP server
12
+ * named `name`.
13
+ */
14
+ server(name: string): McpServerCredentials;
15
+ };
16
+ /** The API's `Credentials`, plus `fetch` to call the app and `service` to find one service. */
4
17
  export type Credentials = CredentialsData & {
5
18
  /**
6
- * Sends one request to the app: `path` is joined to `url`, `headers` are added, and
7
- * `token` goes in the header of the API whose path matches (`Authorization: Bearer`
8
- * for Salesforce REST and Bulk 2.0). Never retries, never follows redirects, never
9
- * sends the State Machines API key. The SOAP session header is the caller's job.
19
+ * Sends one request to the `api` service: `path` is joined to its `url`.
20
+ * Its `headers` are defaults, so a header the caller sets, such as another
21
+ * session's `Authorization`, is sent instead. The environment token header
22
+ * is always the service's. Never retries, never follows redirects, never
23
+ * sends the State Machines API key. Throws a `TypeError` when the
24
+ * credentials list no `api` service.
10
25
  */
11
26
  fetch(path: string, init?: RequestInit): Promise<Response>;
27
+ /** The service with this ID. Throws a `TypeError` naming the listed services when there is none. */
28
+ service(id: string): ServiceCredentials;
12
29
  };
13
- export declare function bindCredentials(data: CredentialsData, apis: readonly Api[], fetcher: typeof fetch | undefined): Credentials;
30
+ export declare function bindCredentials(data: CredentialsData, fetcher: typeof fetch | undefined): Credentials;
@@ -1,56 +1,91 @@
1
- const HTTP_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
1
+ /** The gateway admits a request by this header, so a caller cannot replace it. */
2
+ const ENVIRONMENT_TOKEN_HEADER = 'StateMachines-Environment-Token';
2
3
  // Checked on the path part only. Covers protocol-relative starts, backslashes, control
3
4
  // characters and encoded dots, slashes and backslashes, including double encoding.
4
5
  const UNSAFE_PATH = /^\/\/|\\|%(?:25)*(?:2e|2f|5c)|\p{Cc}/iu;
5
- const OUTSIDE = 'Credentials.fetch only reaches paths under the app url.';
6
- export function bindCredentials(data, apis, fetcher) {
7
- const base = URL.canParse(data.url) ? new URL(data.url) : null;
8
- if (!base || !/^https?:$/.test(base.protocol) || base.search || base.hash) {
9
- throw new TypeError('The credentials url is not a plain http(s) URL.');
10
- }
11
- if (!base.pathname.endsWith('/')) {
12
- base.pathname += '/';
6
+ const OUTSIDE = 'Credentials.fetch only reaches paths under the api service url.';
7
+ export function bindCredentials(data, fetcher) {
8
+ return new BoundCredentials(data, fetcher);
9
+ }
10
+ // Methods live on the prototype, so neither JSON nor a spread copies them.
11
+ class BoundCredentials {
12
+ actorId;
13
+ appName;
14
+ environmentId;
15
+ expiresAt;
16
+ login;
17
+ services;
18
+ token;
19
+ #api;
20
+ #fetcher;
21
+ constructor(data, fetcher) {
22
+ this.actorId = data.actorId;
23
+ this.appName = data.appName;
24
+ this.environmentId = data.environmentId;
25
+ this.expiresAt = data.expiresAt;
26
+ this.login = data.login;
27
+ this.services = data.services;
28
+ this.token = data.token;
29
+ this.#fetcher = fetcher;
30
+ const api = data.services.find((candidate) => candidate.id === 'api');
31
+ this.#api = api
32
+ ? { base: baseUrl(api.url), headers: { ...api.headers } }
33
+ : null;
13
34
  }
14
- const send = async (path, init = {}) => {
35
+ async fetch(path, init = {}) {
36
+ const { base, headers: apiHeaders } = this.#api ?? this.#unlisted('api');
15
37
  const url = resolve(base, path);
16
38
  const headers = new Headers(init.headers);
17
- const actor = actorHeader(apis, `/${url.pathname.slice(base.pathname.length)}`, data.token);
18
- // Ours go last so a caller header of the same name cannot replace them.
19
- for (const [name, value] of Object.entries(data.headers)) {
20
- headers.set(name, value);
21
- }
22
- if (actor) {
23
- headers.set(actor.name, actor.value);
39
+ for (const [name, value] of Object.entries(apiHeaders)) {
40
+ if (!headers.has(name) ||
41
+ name.toLowerCase() === ENVIRONMENT_TOKEN_HEADER.toLowerCase()) {
42
+ headers.set(name, value);
43
+ }
24
44
  }
25
45
  const request = new Request(url, { ...init, headers, redirect: 'manual' });
26
46
  // Called on `globalThis` at use time: a stored unbound `fetch` throws "Illegal invocation" in Workers.
27
- return fetcher ? fetcher(request) : globalThis.fetch(request);
28
- };
29
- return Object.defineProperty({ ...data }, 'fetch', {
30
- value: send,
31
- enumerable: false,
32
- });
47
+ return this.#fetcher ? this.#fetcher(request) : globalThis.fetch(request);
48
+ }
49
+ service(id) {
50
+ const entry = this.services.find((candidate) => candidate.id === id);
51
+ return entry ? new BoundService(entry) : this.#unlisted(id);
52
+ }
53
+ #unlisted(id) {
54
+ const listed = this.services.map((each) => each.id).join(', ') || 'none';
55
+ throw new TypeError(`These credentials list no service named ${JSON.stringify(id)}. They list ${listed}.`);
56
+ }
33
57
  }
34
- /** The longest `pathTemplate` that prefixes the path names the API; `{...}` matches one segment. */
35
- function actorHeader(apis, path, token) {
36
- let match = null;
37
- for (const api of apis) {
38
- const pattern = api.pathTemplate
39
- .replace(/\/+$/, '')
40
- .split(/\{[^}]*\}/)
41
- .map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
42
- .join('[^/]+');
43
- if (new RegExp(`^${pattern}(?:/|$)`).test(path) &&
44
- api.pathTemplate.length > (match?.pathTemplate.length ?? -1)) {
45
- match = api;
58
+ class BoundService {
59
+ headers;
60
+ id;
61
+ url;
62
+ constructor(entry) {
63
+ this.headers = entry.headers;
64
+ this.id = entry.id;
65
+ this.url = entry.url;
66
+ // Set only when present, so a spread or JSON of a service without servers has no `servers` key.
67
+ if (entry.servers) {
68
+ this.servers = entry.servers;
69
+ }
70
+ }
71
+ server(name) {
72
+ const found = this.servers?.find((candidate) => candidate.name === name);
73
+ if (!found) {
74
+ const served = this.servers?.map((each) => each.name).join(', ') || 'none';
75
+ throw new TypeError(`The ${this.id} service serves no MCP server named ${JSON.stringify(name)}. It serves ${served}.`);
46
76
  }
77
+ return { url: found.url, headers: { ...this.headers } };
78
+ }
79
+ }
80
+ function baseUrl(url) {
81
+ const base = URL.canParse(url) ? new URL(url) : null;
82
+ if (!base || !/^https?:$/.test(base.protocol) || base.search || base.hash) {
83
+ throw new TypeError('The api service url is not a plain http(s) URL.');
47
84
  }
48
- if (!match || !HTTP_TOKEN.test(match.actorHeader)) {
49
- return null;
85
+ if (!base.pathname.endsWith('/')) {
86
+ base.pathname += '/';
50
87
  }
51
- return match.actorHeader.toLowerCase() === 'authorization'
52
- ? { name: 'Authorization', value: `Bearer ${token}` }
53
- : { name: match.actorHeader, value: token };
88
+ return base;
54
89
  }
55
90
  function resolve(base, path) {
56
91
  const pathPart = path.split(/[?#]/, 1)[0] ?? '';
@@ -9,7 +9,7 @@ import type { Credentials } from './credentials.js';
9
9
  export type Environment = EnvironmentData & EnvironmentHelpers;
10
10
  export interface EnvironmentHelpers {
11
11
  /** Credentials for one app; `actorId` defaults to the app's default actor. */
12
- connect(app: string, options?: ConnectOptions): Promise<Credentials>;
12
+ connect(appName: string, options?: ConnectOptions): Promise<Credentials>;
13
13
  delete(options?: SignalOptions): Promise<Environment>;
14
14
  /** Reads the environment again. */
15
15
  refresh(): Promise<Environment>;
@@ -48,7 +48,7 @@ export class EnvironmentFailedError extends StateMachinesError {
48
48
  super({
49
49
  ...noResponse,
50
50
  message: failure
51
- ? `Environment ${environment.id} failed: ${failure.message} (${failure.code}, app ${failure.app}).`
51
+ ? `Environment ${environment.id} failed: ${failure.message} (${failure.code}, app ${failure.appName}).`
52
52
  : `Environment ${environment.id} failed.`,
53
53
  });
54
54
  this.environment = environment;
@@ -1,7 +1,7 @@
1
- export type { Actor, Api, App, AuditEvent, BodyPreview, CreateEnvironment, CreateEnvironmentApp, EnvironmentApp, EnvironmentFailure, EnvironmentFailureCode, EnvironmentStatus, ErrorCode, Me, Permission, Principal, RequestDetail, RequestStats, RequestT as Request, Snapshot, SnapshotStatus, Version, Workspace, } from '../models/index.js';
1
+ export type { Actor, App, AppEntry, AuditEvent, BodyPreview, CreateEnvironment, CreateEnvironmentApp, EnvironmentApp, EnvironmentFailure, EnvironmentFailureCode, EnvironmentStatus, ErrorCode, Me, Permission, Principal, RequestDetail, RequestStats, RequestT as Request, Snapshot, SnapshotStatus, Version, Workspace, } from '../models/index.js';
2
2
  export type { ConnectOptions, CreateEnvironmentOptions, CreateSnapshotOptions, ListAuditEventsQuery, ListEnvironmentsQuery, ListRequestsQuery, ListSnapshotsQuery, ListWorkspacesQuery, Page, PageQuery, RequestStatsQuery, SignalOptions, StateMachinesOptions, } from './client.js';
3
3
  export { StateMachines } from './client.js';
4
- export type { Credentials } from './credentials.js';
4
+ export type { Credentials, McpServerCredentials, ServiceCredentials, } from './credentials.js';
5
5
  export type { Environment, EnvironmentHelpers } from './environment.js';
6
6
  export { EnvironmentFailedError, SnapshotFailedError, StateMachinesError, UnexpectedStatusError, WaitTimeoutError, } from './errors.js';
7
7
  export type { WaitOptions } from './wait.js';
@@ -1,6 +1,6 @@
1
1
  import { isAlias, isScalar, parseDocument, visit } from 'yaml';
2
2
  import { invalidInput } from './errors.js';
3
- const APP_FIELDS = new Set(['app', 'name', 'settings']);
3
+ const APP_FIELDS = new Set(['appId', 'name', 'setup', 'services']);
4
4
  /**
5
5
  * Parses a YAML document with the fields of `CreateEnvironment`. The SDK checks the shape;
6
6
  * the API checks the values. Anchors, aliases, tags and duplicate keys are refused.
@@ -97,8 +97,8 @@ export function parseEnvironmentYaml(text) {
97
97
  add(key, 'Unknown field.');
98
98
  }
99
99
  }
100
- if ('apps' in value === 'snapshotId' in value) {
101
- add('$', 'Pass exactly one of apps and snapshotId.');
100
+ if (!('apps' in value) && !('snapshotId' in value)) {
101
+ add('$', 'Send apps, snapshotId or both.');
102
102
  }
103
103
  if (Object.keys(fields).length > 0) {
104
104
  throw bad(fields);
@@ -110,22 +110,24 @@ function checkApp(app, path, add) {
110
110
  return;
111
111
  }
112
112
  if (!isRecord(app)) {
113
- add(path, 'Expected an app ID or a mapping with app.');
113
+ add(path, 'Expected an app ID or a mapping with appId.');
114
114
  return;
115
115
  }
116
- const { app: id, name, settings } = app;
117
- if (typeof id !== 'string') {
118
- add(`${path}.app`, 'Expected a string.');
116
+ const { appId, name } = app;
117
+ if (typeof appId !== 'string') {
118
+ add(`${path}.appId`, 'Expected a string.');
119
119
  }
120
120
  if ('name' in app && typeof name !== 'string') {
121
121
  add(`${path}.name`, 'Expected a string.');
122
122
  }
123
- if ('settings' in app && !isRecord(settings)) {
124
- add(`${path}.settings`, 'Expected a mapping.');
123
+ for (const field of ['setup', 'services']) {
124
+ if (field in app && !isRecord(app[field])) {
125
+ add(`${path}.${field}`, 'Expected a mapping.');
126
+ }
125
127
  }
126
- for (const key of Object.keys(app)) {
127
- if (!APP_FIELDS.has(key)) {
128
- add(`${path}.${key}`, 'Unknown field.');
128
+ for (const field of Object.keys(app)) {
129
+ if (!APP_FIELDS.has(field)) {
130
+ add(`${path}.${field}`, 'Unknown field.');
129
131
  }
130
132
  }
131
133
  }
@@ -0,0 +1,11 @@
1
+ import { StateMachinesCore } from "../core.js";
2
+ import { RequestOptions } from "../lib/sdks.js";
3
+ import { ConnectionError, InvalidRequestError, RequestAbortedError, RequestTimeoutError, UnexpectedClientError } from "../models/errors/http-client-errors.js";
4
+ import * as errors from "../models/errors/index.js";
5
+ import { ResponseValidationError } from "../models/errors/response-validation-error.js";
6
+ import { SDKValidationError } from "../models/errors/sdk-validation-error.js";
7
+ import { StateMachinesHTTPError } from "../models/errors/state-machines-http-error.js";
8
+ import * as operations from "../models/operations/index.js";
9
+ import { APIPromise } from "../types/async.js";
10
+ import { Result } from "../types/fp.js";
11
+ export declare function environmentsCreators(client: StateMachinesCore, request?: operations.ListEnvironmentCreatorsRequest | undefined, options?: RequestOptions): APIPromise<Result<operations.ListEnvironmentCreatorsResponse, errors.ErrorT | StateMachinesHTTPError | ResponseValidationError | ConnectionError | RequestAbortedError | RequestTimeoutError | InvalidRequestError | UnexpectedClientError | SDKValidationError>>;
@@ -0,0 +1,90 @@
1
+ /*
2
+ * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3
+ */
4
+ import * as z from "zod/v4-mini";
5
+ import { encodeFormQuery } from "../lib/encodings.js";
6
+ import { matchStatusCode } from "../lib/http.js";
7
+ import * as M from "../lib/matchers.js";
8
+ import { compactMap } from "../lib/primitives.js";
9
+ import { safeParse } from "../lib/schemas.js";
10
+ import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js";
11
+ import { pathToFunc } from "../lib/url.js";
12
+ import * as errors from "../models/errors/index.js";
13
+ import * as operations from "../models/operations/index.js";
14
+ import { APIPromise } from "../types/async.js";
15
+ export function environmentsCreators(client, request, options) {
16
+ return new APIPromise($do(client, request, options));
17
+ }
18
+ async function $do(client, request, options) {
19
+ const parsed = safeParse(request, (value) => z.parse(z.optional(operations.ListEnvironmentCreatorsRequest$outboundSchema), value), "Input validation failed");
20
+ if (!parsed.ok) {
21
+ return [parsed, { status: "invalid" }];
22
+ }
23
+ const payload = parsed.value;
24
+ const body = null;
25
+ const path = pathToFunc("/v1/environments/creators")();
26
+ const query = encodeFormQuery({
27
+ "workspaceId": payload?.workspaceId,
28
+ });
29
+ const headers = new Headers(compactMap({
30
+ Accept: "application/json",
31
+ }));
32
+ const secConfig = await extractSecurity(client._options.apiKey);
33
+ const securityInput = secConfig == null ? {} : { apiKey: secConfig };
34
+ const requestSecurity = resolveGlobalSecurity(securityInput);
35
+ const context = {
36
+ options: client._options,
37
+ baseURL: options?.serverURL ?? client._baseURL ?? "",
38
+ operationID: "listEnvironmentCreators",
39
+ oAuth2Scopes: null,
40
+ resolvedSecurity: requestSecurity,
41
+ securitySource: client._options.apiKey,
42
+ retryConfig: options?.retries
43
+ || client._options.retryConfig
44
+ || {
45
+ strategy: "backoff",
46
+ backoff: {
47
+ initialInterval: 1000,
48
+ maxInterval: 5000,
49
+ exponent: 1.5,
50
+ maxElapsedTime: 600000,
51
+ },
52
+ retryConnectionErrors: true,
53
+ }
54
+ || { strategy: "none" },
55
+ retryCodes: options?.retryCodes || ["502", "503", "504"],
56
+ };
57
+ const requestRes = client._createRequest(context, {
58
+ security: requestSecurity,
59
+ method: "GET",
60
+ baseURL: options?.serverURL,
61
+ path: path,
62
+ headers: headers,
63
+ query: query,
64
+ body: body,
65
+ userAgent: client._options.userAgent,
66
+ timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1,
67
+ }, options);
68
+ if (!requestRes.ok) {
69
+ return [requestRes, { status: "invalid" }];
70
+ }
71
+ const req = requestRes.value;
72
+ const doResult = await client._do(req, {
73
+ context,
74
+ isErrorStatusCode: (statusCode) => matchStatusCode({ status: statusCode }, ["4XX", "5XX"]),
75
+ retryConfig: context.retryConfig,
76
+ retryCodes: context.retryCodes,
77
+ });
78
+ if (!doResult.ok) {
79
+ return [doResult, { status: "request-error", request: req }];
80
+ }
81
+ const response = doResult.value;
82
+ const responseFields = {
83
+ HttpMeta: { Response: response, Request: req },
84
+ };
85
+ const [result] = await M.match(M.json(200, operations.ListEnvironmentCreatorsResponse$inboundSchema), M.jsonErr([400, 401, 403, 404, 409, 413, 422, 429], errors.ErrorT$inboundSchema), M.jsonErr([500, 503], errors.ErrorT$inboundSchema), M.fail("4XX"), M.fail("5XX"))(response, req, { extraFields: responseFields });
86
+ if (!result.ok) {
87
+ return [result, { status: "complete", request: req, response }];
88
+ }
89
+ return [result, { status: "complete", request: req, response }];
90
+ }
@@ -24,6 +24,8 @@ async function $do(client, request, options) {
24
24
  const body = null;
25
25
  const path = pathToFunc("/v1/environments")();
26
26
  const query = encodeFormQuery({
27
+ "appId": payload?.appId,
28
+ "createdBy": payload?.createdBy,
27
29
  "cursor": payload?.cursor,
28
30
  "label": payload?.label,
29
31
  "limit": payload?.limit,
@@ -24,16 +24,20 @@ async function $do(client, request, options) {
24
24
  const body = null;
25
25
  const path = pathToFunc("/v1/requests")();
26
26
  const query = encodeFormQuery({
27
- "app": payload.app,
27
+ "appName": payload.appName,
28
28
  "cursor": payload.cursor,
29
29
  "environmentId": payload.environmentId,
30
30
  "from": payload.from,
31
31
  "limit": payload.limit,
32
+ "mcpServer": payload.mcpServer,
32
33
  "method": payload.method,
34
+ "operation": payload.operation,
33
35
  "responseStatus": payload.responseStatus,
34
36
  "search": payload.search,
37
+ "service": payload.service,
35
38
  "statusClass": payload.statusClass,
36
39
  "to": payload.to,
40
+ "tool": payload.tool,
37
41
  "writesOnly": payload.writesOnly,
38
42
  });
39
43
  const headers = new Headers(compactMap({
@@ -25,14 +25,18 @@ async function $do(client, request, options) {
25
25
  const body = null;
26
26
  const path = pathToFunc("/v1/requests/stats")();
27
27
  const query = encodeFormQuery({
28
- "app": payload.app,
28
+ "appName": payload.appName,
29
29
  "environmentId": payload.environmentId,
30
30
  "from": payload.from,
31
+ "mcpServer": payload.mcpServer,
31
32
  "method": payload.method,
33
+ "operation": payload.operation,
32
34
  "responseStatus": payload.responseStatus,
33
35
  "search": payload.search,
36
+ "service": payload.service,
34
37
  "statusClass": payload.statusClass,
35
38
  "to": payload.to,
39
+ "tool": payload.tool,
36
40
  "writesOnly": payload.writesOnly,
37
41
  });
38
42
  const headers = new Headers(compactMap({
@@ -31,7 +31,7 @@ export declare function serverURLFromOptions(options: SDKOptions): URL | null;
31
31
  export declare const SDK_METADATA: {
32
32
  readonly language: "typescript";
33
33
  readonly openapiDocVersion: "1.0.0";
34
- readonly sdkVersion: "0.7.1";
34
+ readonly sdkVersion: "0.8.0";
35
35
  readonly genVersion: "2.941.0";
36
- readonly userAgent: "speakeasy-sdk/typescript 0.7.1 2.941.0 1.0.0 @usestatemachines/sdk";
36
+ readonly userAgent: "speakeasy-sdk/typescript 0.8.0 2.941.0 1.0.0 @usestatemachines/sdk";
37
37
  };
package/esm/lib/config.js CHANGED
@@ -24,7 +24,7 @@ export function serverURLFromOptions(options) {
24
24
  export const SDK_METADATA = {
25
25
  language: "typescript",
26
26
  openapiDocVersion: "1.0.0",
27
- sdkVersion: "0.7.1",
27
+ sdkVersion: "0.8.0",
28
28
  genVersion: "2.941.0",
29
- userAgent: "speakeasy-sdk/typescript 0.7.1 2.941.0 1.0.0 @usestatemachines/sdk",
29
+ userAgent: "speakeasy-sdk/typescript 0.8.0 2.941.0 1.0.0 @usestatemachines/sdk",
30
30
  };
@@ -0,0 +1,8 @@
1
+ import * as z from "zod/v4-mini";
2
+ import { CreateEnvironmentApp, CreateEnvironmentApp$Outbound } from "./create-environment-app.js";
3
+ export type AppEntry = CreateEnvironmentApp | string;
4
+ /** @internal */
5
+ export type AppEntry$Outbound = CreateEnvironmentApp$Outbound | string;
6
+ /** @internal */
7
+ export declare const AppEntry$outboundSchema: z.ZodMiniType<AppEntry$Outbound, AppEntry>;
8
+ export declare function appEntryToJSON(appEntry: AppEntry): string;
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3
+ */
4
+ import * as z from "zod/v4-mini";
5
+ import { smartUnion } from "../types/smart-union.js";
6
+ import { CreateEnvironmentApp$outboundSchema, } from "./create-environment-app.js";
7
+ /** @internal */
8
+ export const AppEntry$outboundSchema = smartUnion([CreateEnvironmentApp$outboundSchema, z.string()]);
9
+ export function appEntryToJSON(appEntry) {
10
+ return JSON.stringify(AppEntry$outboundSchema.parse(appEntry));
11
+ }
@@ -0,0 +1,25 @@
1
+ import * as z from "zod/v4-mini";
2
+ export type CreateEnvironmentApp = {
3
+ appId: string;
4
+ name?: string | undefined;
5
+ services?: {
6
+ [k: string]: any;
7
+ } | undefined;
8
+ setup?: {
9
+ [k: string]: any;
10
+ } | undefined;
11
+ };
12
+ /** @internal */
13
+ export type CreateEnvironmentApp$Outbound = {
14
+ appId: string;
15
+ name?: string | undefined;
16
+ services?: {
17
+ [k: string]: any;
18
+ } | undefined;
19
+ setup?: {
20
+ [k: string]: any;
21
+ } | undefined;
22
+ };
23
+ /** @internal */
24
+ export declare const CreateEnvironmentApp$outboundSchema: z.ZodMiniType<CreateEnvironmentApp$Outbound, CreateEnvironmentApp>;
25
+ export declare function createEnvironmentAppToJSON(createEnvironmentApp: CreateEnvironmentApp): string;
@@ -0,0 +1,14 @@
1
+ /*
2
+ * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
3
+ */
4
+ import * as z from "zod/v4-mini";
5
+ /** @internal */
6
+ export const CreateEnvironmentApp$outboundSchema = z.object({
7
+ appId: z.string(),
8
+ name: z.optional(z.string()),
9
+ services: z.optional(z.record(z.string(), z.any())),
10
+ setup: z.optional(z.record(z.string(), z.any())),
11
+ });
12
+ export function createEnvironmentAppToJSON(createEnvironmentApp) {
13
+ return JSON.stringify(CreateEnvironmentApp$outboundSchema.parse(createEnvironmentApp));
14
+ }