diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 7840fde9a..4fcfdf7a7 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.8.1"
+ ".": "1.9.0"
}
diff --git a/.stats.yml b/.stats.yml
index 44040dae9..e8c2e4563 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-8704a652545c3831c8b7e246ec17f1a626b59911eb5701ddc922ca6cae1c8d57.yml
-openapi_spec_hash: e609bc5ed3fdce498bc7d16921bbba5e
-config_hash: eb28692edd68a6ae95cf92af931c9976
+configured_endpoints: 118
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-dd0f43e15cb67179deaf86f83ae04c6fae4ff858ee33e82a3b89231566cdc5bb.yml
+openapi_spec_hash: 569176c1c4f48efd25a44fa526fad9d1
+config_hash: cbda3692cb48ab8582a0df1674b9e5c8
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e55864f00..f7280b54a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,29 @@
# Changelog
+## 1.9.0 (2026-02-25)
+
+Full Changelog: [v1.8.1...v1.9.0](https://github.com/runloopai/api-client-ts/compare/v1.8.1...v1.9.0)
+
+### Features
+
+* Add AI gateway and MCP gateway flags to network policy create ([#7638](https://github.com/runloopai/api-client-ts/issues/7638)) ([5542b72](https://github.com/runloopai/api-client-ts/commit/5542b727869a411b7828c2779f5f683e4c35f3ea))
+
+
+### Bug Fixes
+
+* **docs/contributing:** correct pnpm link command ([df98444](https://github.com/runloopai/api-client-ts/commit/df98444d096ae0fb8d737476ebb506122e3426b8))
+* **internal:** skip tests that depend on mock server ([284aac3](https://github.com/runloopai/api-client-ts/commit/284aac38f7f281f096ebb2bd4e5605df0db77a71))
+* workflow issues for npm stable tag and docs tar ([#721](https://github.com/runloopai/api-client-ts/issues/721)) ([2c5e7a4](https://github.com/runloopai/api-client-ts/commit/2c5e7a40f2b1cbcb73bb3ec17e2f4dd6e6e2ed6d))
+
+
+### Chores
+
+* Add archive method to stainless ([#7537](https://github.com/runloopai/api-client-ts/issues/7537)) ([b68ac03](https://github.com/runloopai/api-client-ts/commit/b68ac035f2d72bee47c2790c8c814e15e4ea4a1e))
+* allow specifying smoketests jest filter to workflow ([#722](https://github.com/runloopai/api-client-ts/issues/722)) ([b9d117b](https://github.com/runloopai/api-client-ts/commit/b9d117b23b5da12b38d7bc5e138079cedb40622b))
+* **documentation:** fixed bug in doc publishing ([#720](https://github.com/runloopai/api-client-ts/issues/720)) ([1eeb486](https://github.com/runloopai/api-client-ts/commit/1eeb486190d5184e7a9b8c363b68893c5492bf57))
+* **scenarios:** make scenario status enum instead of string ([#7552](https://github.com/runloopai/api-client-ts/issues/7552)) ([c5b244c](https://github.com/runloopai/api-client-ts/commit/c5b244ce0f502984420758c63e7a7c55760026f8))
+* update mock server docs ([875216d](https://github.com/runloopai/api-client-ts/commit/875216d63a50d030df6d5d3233a364a61b1b82b1))
+
## 1.8.1 (2026-02-19)
Full Changelog: [v1.8.0...v1.8.1](https://github.com/runloopai/api-client-ts/compare/v1.8.0...v1.8.1)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 887fd5325..aa6af7e9d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -60,7 +60,7 @@ $ yarn link @runloop/api-client
# With pnpm
$ pnpm link --global
$ cd ../my-package
-$ pnpm link -—global @runloop/api-client
+$ pnpm link --global @runloop/api-client
```
## Running tests
@@ -68,7 +68,7 @@ $ pnpm link -—global @runloop/api-client
Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
```sh
-$ npx prism mock path/to/your/openapi.yml
+$ ./scripts/mock
```
```sh
diff --git a/api.md b/api.md
index 2b28ba3df..18d40cbe0 100644
--- a/api.md
+++ b/api.md
@@ -245,6 +245,7 @@ Methods:
- client.scenarios.retrieve(id) -> ScenarioView
- client.scenarios.update(id, { ...params }) -> ScenarioView
- client.scenarios.list({ ...params }) -> ScenarioViewsScenariosCursorIDPage
+- client.scenarios.archive(id) -> ScenarioView
- client.scenarios.listPublic({ ...params }) -> ScenarioViewsScenariosCursorIDPage
- client.scenarios.startRun({ ...params }) -> ScenarioRunView
diff --git a/package.json b/package.json
index 7326f4966..9c0124b5b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@runloop/api-client",
- "version": "1.8.1",
+ "version": "1.9.0",
"description": "The official TypeScript library for the Runloop API",
"author": "Runloop ",
"types": "dist/sdk.d.ts",
diff --git a/src/resources/devboxes/devboxes.ts b/src/resources/devboxes/devboxes.ts
index 5777d7f47..5da3cb4c3 100644
--- a/src/resources/devboxes/devboxes.ts
+++ b/src/resources/devboxes/devboxes.ts
@@ -1024,6 +1024,12 @@ export interface TunnelView {
*/
create_time_ms: number;
+ /**
+ * When true, HTTP traffic through the tunnel counts as activity for idle lifecycle
+ * policies, resetting the idle timer.
+ */
+ http_keep_alive: boolean;
+
/**
* The encrypted tunnel key used to construct the tunnel URL. URL format:
* https://{port}-{tunnel_key}.tunnel.runloop.{domain}
@@ -1221,6 +1227,12 @@ export namespace DevboxCreateParams {
* Authentication mode for the tunnel. Defaults to 'public' if not specified.
*/
auth_mode?: 'open' | 'authenticated' | null;
+
+ /**
+ * When true, HTTP traffic through the tunnel counts as activity for idle lifecycle
+ * policies, resetting the idle timer. Defaults to true if not specified.
+ */
+ http_keep_alive?: boolean | null;
}
}
@@ -1271,6 +1283,12 @@ export interface DevboxEnableTunnelParams {
* Authentication mode for the tunnel. Defaults to 'public' if not specified.
*/
auth_mode?: 'open' | 'authenticated' | null;
+
+ /**
+ * When true, HTTP traffic through the tunnel counts as activity for idle lifecycle
+ * policies, resetting the idle timer. Defaults to true if not specified.
+ */
+ http_keep_alive?: boolean | null;
}
/**
diff --git a/src/resources/network-policies.ts b/src/resources/network-policies.ts
index 4882ca2fa..823ba8ba5 100644
--- a/src/resources/network-policies.ts
+++ b/src/resources/network-policies.ts
@@ -88,6 +88,12 @@ export interface NetworkPolicyCreateParameters {
*/
name: string;
+ /**
+ * (Optional) If true, allows devbox egress to the AI credential gateway for
+ * credential proxying. Defaults to false.
+ */
+ allow_ai_gateway?: boolean | null;
+
/**
* (Optional) If true, all egress traffic is allowed (ALLOW_ALL policy). Defaults
* to false.
@@ -101,6 +107,12 @@ export interface NetworkPolicyCreateParameters {
*/
allow_devbox_to_devbox?: boolean | null;
+ /**
+ * (Optional) If true, allows devbox egress to the MCP hub for MCP server access.
+ * Defaults to false.
+ */
+ allow_mcp_gateway?: boolean | null;
+
/**
* (Optional) DNS-based allow list with wildcard support. Examples: ['github.com',
* '*.npmjs.org'].
@@ -138,6 +150,11 @@ export interface NetworkPolicyListView {
* Parameters for updating an existing NetworkPolicy. All fields are optional.
*/
export interface NetworkPolicyUpdateParameters {
+ /**
+ * If true, allows devbox egress to the AI credential gateway.
+ */
+ allow_ai_gateway?: boolean | null;
+
/**
* If true, all egress traffic is allowed (ALLOW_ALL policy).
*/
@@ -148,6 +165,11 @@ export interface NetworkPolicyUpdateParameters {
*/
allow_devbox_to_devbox?: boolean | null;
+ /**
+ * If true, allows devbox egress to the MCP hub.
+ */
+ allow_mcp_gateway?: boolean | null;
+
/**
* Updated DNS-based allow list with wildcard support. Examples: ['github.com',
* '*.npmjs.org'].
@@ -206,6 +228,12 @@ export namespace NetworkPolicyView {
* The egress rules for this policy.
*/
export interface Egress {
+ /**
+ * If true, allows devbox egress to the AI credential gateway for credential
+ * proxying.
+ */
+ allow_ai_gateway: boolean;
+
/**
* If true, all egress traffic is allowed and other fields are ignored. Used for
* ALLOW_ALL policies.
@@ -217,6 +245,11 @@ export namespace NetworkPolicyView {
*/
allow_devbox_to_devbox: boolean;
+ /**
+ * If true, allows devbox egress to the MCP hub for MCP server access.
+ */
+ allow_mcp_gateway: boolean;
+
/**
* DNS-based allow list with wildcard support. Examples: ['github.com',
* '*.npmjs.org', 'api.openai.com']. Empty list with allow_all=false means no
@@ -233,6 +266,12 @@ export interface NetworkPolicyCreateParams {
*/
name: string;
+ /**
+ * (Optional) If true, allows devbox egress to the AI credential gateway for
+ * credential proxying. Defaults to false.
+ */
+ allow_ai_gateway?: boolean | null;
+
/**
* (Optional) If true, all egress traffic is allowed (ALLOW_ALL policy). Defaults
* to false.
@@ -246,6 +285,12 @@ export interface NetworkPolicyCreateParams {
*/
allow_devbox_to_devbox?: boolean | null;
+ /**
+ * (Optional) If true, allows devbox egress to the MCP hub for MCP server access.
+ * Defaults to false.
+ */
+ allow_mcp_gateway?: boolean | null;
+
/**
* (Optional) DNS-based allow list with wildcard support. Examples: ['github.com',
* '*.npmjs.org'].
@@ -259,6 +304,11 @@ export interface NetworkPolicyCreateParams {
}
export interface NetworkPolicyUpdateParams {
+ /**
+ * If true, allows devbox egress to the AI credential gateway.
+ */
+ allow_ai_gateway?: boolean | null;
+
/**
* If true, all egress traffic is allowed (ALLOW_ALL policy).
*/
@@ -269,6 +319,11 @@ export interface NetworkPolicyUpdateParams {
*/
allow_devbox_to_devbox?: boolean | null;
+ /**
+ * If true, allows devbox egress to the MCP hub.
+ */
+ allow_mcp_gateway?: boolean | null;
+
/**
* Updated DNS-based allow list with wildcard support. Examples: ['github.com',
* '*.npmjs.org'].
diff --git a/src/resources/scenarios/scenarios.ts b/src/resources/scenarios/scenarios.ts
index cb2b2a976..c3d6f4287 100644
--- a/src/resources/scenarios/scenarios.ts
+++ b/src/resources/scenarios/scenarios.ts
@@ -88,6 +88,14 @@ export class Scenarios extends APIResource {
});
}
+ /**
+ * Archive a previously created Scenario. The scenario will no longer appear in
+ * list endpoints but can still be retrieved by ID.
+ */
+ archive(id: string, options?: Core.RequestOptions): Core.APIPromise {
+ return this._client.post(`/v1/scenarios/${id}/archive`, options);
+ }
+
/**
* List all public scenarios matching filter.
*/
@@ -422,9 +430,10 @@ export interface ScenarioView {
scoring_contract: ScoringContract;
/**
- * The state of the scenario.
+ * Whether the scenario is active or archived. Archived scenarios are excluded from
+ * listings and cannot be updated.
*/
- status: string;
+ status: 'active' | 'archived';
/**
* The Environment in which the Scenario is run.
diff --git a/src/version.ts b/src/version.ts
index 3c346f4fb..d6d803fa2 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '1.8.1'; // x-release-please-version
+export const VERSION = '1.9.0'; // x-release-please-version
diff --git a/tests/api-resources/devboxes/devboxes.test.ts b/tests/api-resources/devboxes/devboxes.test.ts
index 4d17c0d19..b628d9dcf 100644
--- a/tests/api-resources/devboxes/devboxes.test.ts
+++ b/tests/api-resources/devboxes/devboxes.test.ts
@@ -74,7 +74,7 @@ describe('resource devboxes', () => {
repo_connection_id: 'repo_connection_id',
secrets: { foo: 'string' },
snapshot_id: 'snapshot_id',
- tunnel: { auth_mode: 'open' },
+ tunnel: { auth_mode: 'open', http_keep_alive: true },
},
{ path: '/_stainless_unknown_path' },
),
@@ -240,7 +240,11 @@ describe('resource devboxes', () => {
test('enableTunnel: request options and params are passed correctly', async () => {
// ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
await expect(
- client.devboxes.enableTunnel('id', { auth_mode: 'open' }, { path: '/_stainless_unknown_path' }),
+ client.devboxes.enableTunnel(
+ 'id',
+ { auth_mode: 'open', http_keep_alive: true },
+ { path: '/_stainless_unknown_path' },
+ ),
).rejects.toThrow(Runloop.NotFoundError);
});
diff --git a/tests/api-resources/network-policies.test.ts b/tests/api-resources/network-policies.test.ts
index 1a9291ac0..cb3a97df0 100644
--- a/tests/api-resources/network-policies.test.ts
+++ b/tests/api-resources/network-policies.test.ts
@@ -23,8 +23,10 @@ describe('resource networkPolicies', () => {
test('create: required and optional params', async () => {
const response = await client.networkPolicies.create({
name: 'name',
+ allow_ai_gateway: true,
allow_all: true,
allow_devbox_to_devbox: true,
+ allow_mcp_gateway: true,
allowed_hostnames: ['string'],
description: 'description',
});
@@ -72,8 +74,10 @@ describe('resource networkPolicies', () => {
client.networkPolicies.update(
'id',
{
+ allow_ai_gateway: true,
allow_all: true,
allow_devbox_to_devbox: true,
+ allow_mcp_gateway: true,
allowed_hostnames: ['string'],
description: 'description',
name: 'name',
diff --git a/tests/api-resources/scenarios/runs.test.ts b/tests/api-resources/scenarios/runs.test.ts
index 0997ff36f..8d5ce1629 100644
--- a/tests/api-resources/scenarios/runs.test.ts
+++ b/tests/api-resources/scenarios/runs.test.ts
@@ -98,7 +98,8 @@ describe('resource runs', () => {
);
});
- test('downloadLogs: request options instead of params are passed correctly', async () => {
+ // Mock server doesn't support application/zip responses
+ test.skip('downloadLogs: request options instead of params are passed correctly', async () => {
// ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
await expect(
client.scenarios.runs.downloadLogs('id', { path: '/_stainless_unknown_path' }),
diff --git a/tests/api-resources/scenarios/scenarios.test.ts b/tests/api-resources/scenarios/scenarios.test.ts
index 7603ee621..84e05196a 100644
--- a/tests/api-resources/scenarios/scenarios.test.ts
+++ b/tests/api-resources/scenarios/scenarios.test.ts
@@ -211,6 +211,24 @@ describe('resource scenarios', () => {
).rejects.toThrow(Runloop.NotFoundError);
});
+ test('archive', async () => {
+ const responsePromise = client.scenarios.archive('id');
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('archive: request options instead of params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(client.scenarios.archive('id', { path: '/_stainless_unknown_path' })).rejects.toThrow(
+ Runloop.NotFoundError,
+ );
+ });
+
test('listPublic', async () => {
const responsePromise = client.scenarios.listPublic();
const rawResponse = await responsePromise.asResponse();