diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0d1bebe1c..64e0684f3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.6.0" + ".": "1.7.0" } diff --git a/.stats.yml b/.stats.yml index 4df441fe0..73c283357 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 113 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-37187e72e61b850045924e6cb40207159ab794114add75a2bf36c87915326306.yml -openapi_spec_hash: 33510c114bef0847855cdaf8f55c0774 -config_hash: 9f86425631c30497276e58b744dd3654 +configured_endpoints: 117 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/runloop-ai%2Frunloop-15b7fd06098d8cb3639efb3b401a03d7d97a8ab4960b08077aa871f0cacb33d3.yml +openapi_spec_hash: 93ab2fe88f9e57d8f262ad6d1179190e +config_hash: eb28692edd68a6ae95cf92af931c9976 diff --git a/CHANGELOG.md b/CHANGELOG.md index 074a8b888..0b9af4f20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## 1.7.0 (2026-02-05) + +Full Changelog: [v1.6.0...v1.7.0](https://github.com/runloopai/api-client-ts/compare/v1.6.0...v1.7.0) + +### Features + +* adding MCP Config routes ([#7331](https://github.com/runloopai/api-client-ts/issues/7331)) ([81054b5](https://github.com/runloopai/api-client-ts/commit/81054b5b53a4e5244d1bf8489b610deda650600e)) +* **devbox:** add mcp configuration to devbox create ([#7341](https://github.com/runloopai/api-client-ts/issues/7341)) ([6ed219b](https://github.com/runloopai/api-client-ts/commit/6ed219bbbc44d105ca43be3f2e4265263d259b22)) + + +### Bug Fixes + +* publish-docs.yml on main failing b/c yarn binary missing in ubuntu-slim ([#712](https://github.com/runloopai/api-client-ts/issues/712)) ([13c187b](https://github.com/runloopai/api-client-ts/commit/13c187b3efa409ecad35910b11bf041217dd7679)) + + +### Chores + +* additional e2e tests for gatewayconfig + network config ([#709](https://github.com/runloopai/api-client-ts/issues/709)) ([ed48249](https://github.com/runloopai/api-client-ts/commit/ed482490613dc503893edaa2808aaad10c7f75c5)) +* **ci:** migrate fast and simple actions to ubuntu-slim runner ([#703](https://github.com/runloopai/api-client-ts/issues/703)) ([3c06589](https://github.com/runloopai/api-client-ts/commit/3c06589447650885fe143c8e5470e6231473f4e8)) +* fix workflow using slim not having yarn ([#713](https://github.com/runloopai/api-client-ts/issues/713)) ([261fc58](https://github.com/runloopai/api-client-ts/commit/261fc580c7ccd3aeda0dbd99af31c2b42b4882ae)) + ## 1.6.0 (2026-02-04) Full Changelog: [v1.5.1...v1.6.0](https://github.com/runloopai/api-client-ts/compare/v1.5.1...v1.6.0) diff --git a/api.md b/api.md index 3e18b4fb5..27681f9f7 100644 --- a/api.md +++ b/api.md @@ -267,7 +267,6 @@ Types: - ScorerRetrieveResponse - ScorerUpdateResponse - ScorerListResponse -- ScorerValidateResponse Methods: @@ -275,7 +274,6 @@ Methods: - client.scenarios.scorers.retrieve(id) -> ScorerRetrieveResponse - client.scenarios.scorers.update(id, { ...params }) -> ScorerUpdateResponse - client.scenarios.scorers.list({ ...params }) -> ScorerListResponsesScenarioScorersCursorIDPage -- client.scenarios.scorers.validate(id, { ...params }) -> ScorerValidateResponse # Objects @@ -368,3 +366,20 @@ Methods: - client.gatewayConfigs.update(id, { ...params }) -> GatewayConfigView - client.gatewayConfigs.list({ ...params }) -> GatewayConfigViewsGatewayConfigsCursorIDPage - client.gatewayConfigs.delete(id) -> GatewayConfigView + +# McpConfigs + +Types: + +- McpConfigCreateParameters +- McpConfigListView +- McpConfigUpdateParameters +- McpConfigView + +Methods: + +- client.mcpConfigs.create({ ...params }) -> McpConfigView +- client.mcpConfigs.retrieve(id) -> McpConfigView +- client.mcpConfigs.update(id, { ...params }) -> McpConfigView +- client.mcpConfigs.list({ ...params }) -> McpConfigViewsMcpConfigsCursorIDPage +- client.mcpConfigs.delete(id) -> McpConfigView diff --git a/package.json b/package.json index 6730742a1..83d1de3de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@runloop/api-client", - "version": "1.6.0", + "version": "1.7.0", "description": "The official TypeScript library for the Runloop API", "author": "Runloop ", "types": "dist/sdk.d.ts", diff --git a/src/index.ts b/src/index.ts index 9b97bf0e3..15e19ad55 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,6 +19,8 @@ import { DiskSnapshotsCursorIDPageResponse, type GatewayConfigsCursorIDPageParams, GatewayConfigsCursorIDPageResponse, + type McpConfigsCursorIDPageParams, + McpConfigsCursorIDPageResponse, type NetworkPoliciesCursorIDPageParams, NetworkPoliciesCursorIDPageResponse, type ObjectsCursorIDPageParams, @@ -106,6 +108,18 @@ import { GatewayConfigViewsGatewayConfigsCursorIDPage, GatewayConfigs, } from './resources/gateway-configs'; +import { + McpConfigCreateParameters, + McpConfigCreateParams, + McpConfigDeleteParams, + McpConfigListParams, + McpConfigListView, + McpConfigUpdateParameters, + McpConfigUpdateParams, + McpConfigView, + McpConfigViewsMcpConfigsCursorIDPage, + McpConfigs, +} from './resources/mcp-configs'; import { NetworkPolicies, NetworkPolicyCreateParameters, @@ -359,6 +373,7 @@ export class Runloop extends Core.APIClient { secrets: API.Secrets = new API.Secrets(this); networkPolicies: API.NetworkPolicies = new API.NetworkPolicies(this); gatewayConfigs: API.GatewayConfigs = new API.GatewayConfigs(this); + mcpConfigs: API.McpConfigs = new API.McpConfigs(this); /** * Check whether the base URL is set to its default. @@ -426,6 +441,8 @@ Runloop.NetworkPolicies = NetworkPolicies; Runloop.NetworkPolicyViewsNetworkPoliciesCursorIDPage = NetworkPolicyViewsNetworkPoliciesCursorIDPage; Runloop.GatewayConfigs = GatewayConfigs; Runloop.GatewayConfigViewsGatewayConfigsCursorIDPage = GatewayConfigViewsGatewayConfigsCursorIDPage; +Runloop.McpConfigs = McpConfigs; +Runloop.McpConfigViewsMcpConfigsCursorIDPage = McpConfigViewsMcpConfigsCursorIDPage; export declare namespace Runloop { export type RequestOptions = Core.RequestOptions; @@ -508,6 +525,12 @@ export declare namespace Runloop { type GatewayConfigsCursorIDPageResponse as GatewayConfigsCursorIDPageResponse, }; + export import McpConfigsCursorIDPage = Pagination.McpConfigsCursorIDPage; + export { + type McpConfigsCursorIDPageParams as McpConfigsCursorIDPageParams, + type McpConfigsCursorIDPageResponse as McpConfigsCursorIDPageResponse, + }; + export { Benchmarks as Benchmarks, type BenchmarkCreateParameters as BenchmarkCreateParameters, @@ -708,6 +731,19 @@ export declare namespace Runloop { type GatewayConfigDeleteParams as GatewayConfigDeleteParams, }; + export { + McpConfigs as McpConfigs, + type McpConfigCreateParameters as McpConfigCreateParameters, + type McpConfigListView as McpConfigListView, + type McpConfigUpdateParameters as McpConfigUpdateParameters, + type McpConfigView as McpConfigView, + McpConfigViewsMcpConfigsCursorIDPage as McpConfigViewsMcpConfigsCursorIDPage, + type McpConfigCreateParams as McpConfigCreateParams, + type McpConfigUpdateParams as McpConfigUpdateParams, + type McpConfigListParams as McpConfigListParams, + type McpConfigDeleteParams as McpConfigDeleteParams, + }; + export type AfterIdle = API.AfterIdle; export type AgentMount = API.AgentMount; export type AgentSource = API.AgentSource; diff --git a/src/pagination.ts b/src/pagination.ts index 3f8349214..1db21e1b7 100644 --- a/src/pagination.ts +++ b/src/pagination.ts @@ -963,3 +963,77 @@ export class GatewayConfigsCursorIDPage return { params: { starting_after: id } }; } } + +export interface McpConfigsCursorIDPageResponse { + mcp_configs: Array; + + has_more: boolean; + + total_count: number; +} + +export interface McpConfigsCursorIDPageParams { + starting_after?: string; + + limit?: number; +} + +export class McpConfigsCursorIDPage + extends AbstractPage + implements McpConfigsCursorIDPageResponse +{ + mcp_configs: Array; + + has_more: boolean; + + total_count: number; + + constructor( + client: APIClient, + response: Response, + body: McpConfigsCursorIDPageResponse, + options: FinalRequestOptions, + ) { + super(client, response, body, options); + + this.mcp_configs = body.mcp_configs || []; + this.has_more = body.has_more || false; + this.total_count = body.total_count || 0; + } + + getPaginatedItems(): Item[] { + return this.mcp_configs ?? []; + } + + override hasNextPage(): boolean { + if (this.has_more === false) { + return false; + } + + return super.hasNextPage(); + } + + // @deprecated Please use `nextPageInfo()` instead + nextPageParams(): Partial | null { + const info = this.nextPageInfo(); + if (!info) return null; + if ('params' in info) return info.params; + const params = Object.fromEntries(info.url.searchParams); + if (!Object.keys(params).length) return null; + return params; + } + + nextPageInfo(): PageInfo | null { + const mcpConfigs = this.getPaginatedItems(); + if (!mcpConfigs.length) { + return null; + } + + const id = mcpConfigs[mcpConfigs.length - 1]?.id; + if (!id) { + return null; + } + + return { params: { starting_after: id } }; + } +} diff --git a/src/resources/devboxes/devboxes.ts b/src/resources/devboxes/devboxes.ts index 81390fe84..9210e2864 100644 --- a/src/resources/devboxes/devboxes.ts +++ b/src/resources/devboxes/devboxes.ts @@ -1104,6 +1104,14 @@ export interface DevboxCreateParams { */ launch_parameters?: Shared.LaunchParameters | null; + /** + * [Beta] (Optional) MCP specifications for MCP server access. Each spec links an + * MCP config to a secret. The devbox will receive environment variables + * (RL_MCP_URL, RL_MCP_TOKEN) for accessing MCP servers through the MCP hub. + * Example: [{'mcp_config': 'github-readonly', 'secret': 'MY_GITHUB_TOKEN'}] + */ + mcp?: Array | null; + /** * User defined metadata to attach to the devbox for organization. */ @@ -1164,6 +1172,24 @@ export namespace DevboxCreateParams { secret: string; } + /** + * [Beta] McpSpec links an MCP configuration to a secret for MCP server access in a + * devbox. The MCP hub will proxy requests to upstream MCP servers using the + * specified credential, with tool-level access control based on the MCP config's + * allowed_tools. + */ + export interface Mcp { + /** + * The MCP config to use. Can be an MCP config ID (mcp_xxx) or name. + */ + mcp_config: string; + + /** + * The secret containing the MCP server credential. Can be a secret ID or name. + */ + secret: string; + } + /** * (Optional) Configuration for creating a V2 tunnel at Devbox launch time. When * specified, a tunnel will be automatically provisioned and the tunnel details diff --git a/src/resources/index.ts b/src/resources/index.ts index c015661df..5ff244289 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -113,6 +113,18 @@ export { type GatewayConfigListParams, type GatewayConfigDeleteParams, } from './gateway-configs'; +export { + McpConfigViewsMcpConfigsCursorIDPage, + McpConfigs, + type McpConfigCreateParameters, + type McpConfigListView, + type McpConfigUpdateParameters, + type McpConfigView, + type McpConfigCreateParams, + type McpConfigUpdateParams, + type McpConfigListParams, + type McpConfigDeleteParams, +} from './mcp-configs'; export { NetworkPolicyViewsNetworkPoliciesCursorIDPage, NetworkPolicies, diff --git a/src/resources/mcp-configs.ts b/src/resources/mcp-configs.ts new file mode 100644 index 000000000..21a9e8939 --- /dev/null +++ b/src/resources/mcp-configs.ts @@ -0,0 +1,269 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../resource'; +import { isRequestOptions } from '../core'; +import * as Core from '../core'; +import { McpConfigsCursorIDPage, type McpConfigsCursorIDPageParams } from '../pagination'; + +export class McpConfigs extends APIResource { + /** + * [Beta] Create a new McpConfig to connect to an upstream MCP (Model Context + * Protocol) server. The config specifies the target endpoint and which tools are + * allowed. + */ + create(body: McpConfigCreateParams, options?: Core.RequestOptions): Core.APIPromise { + return this._client.post('/v1/mcp-configs', { body, ...options }); + } + + /** + * [Beta] Get a specific McpConfig by its unique identifier. + */ + retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { + return this._client.get(`/v1/mcp-configs/${id}`, options); + } + + /** + * [Beta] Update an existing McpConfig. All fields are optional. + */ + update( + id: string, + body?: McpConfigUpdateParams, + options?: Core.RequestOptions, + ): Core.APIPromise; + update(id: string, options?: Core.RequestOptions): Core.APIPromise; + update( + id: string, + body: McpConfigUpdateParams | Core.RequestOptions = {}, + options?: Core.RequestOptions, + ): Core.APIPromise { + if (isRequestOptions(body)) { + return this.update(id, {}, body); + } + return this._client.post(`/v1/mcp-configs/${id}`, { body, ...options }); + } + + /** + * [Beta] List all McpConfigs for the authenticated account. + */ + list( + query?: McpConfigListParams, + options?: Core.RequestOptions, + ): Core.PagePromise; + list(options?: Core.RequestOptions): Core.PagePromise; + list( + query: McpConfigListParams | Core.RequestOptions = {}, + options?: Core.RequestOptions, + ): Core.PagePromise { + if (isRequestOptions(query)) { + return this.list({}, query); + } + return this._client.getAPIList('/v1/mcp-configs', McpConfigViewsMcpConfigsCursorIDPage, { + query, + ...options, + }); + } + + /** + * [Beta] Delete an existing McpConfig. This action is irreversible. + */ + delete( + id: string, + body?: McpConfigDeleteParams | null | undefined, + options?: Core.RequestOptions, + ): Core.APIPromise { + return this._client.post(`/v1/mcp-configs/${id}/delete`, { body, ...options }); + } +} + +export class McpConfigViewsMcpConfigsCursorIDPage extends McpConfigsCursorIDPage {} + +/** + * Parameters required to create a new McpConfig. + */ +export interface McpConfigCreateParameters { + /** + * Glob patterns specifying which tools are allowed from this MCP server. Examples: + * ['*'] for all tools, ['github.search_*', 'github.get_*'] for specific patterns. + */ + allowed_tools: Array; + + /** + * The target MCP server endpoint URL (e.g., 'https://mcp.example.com'). + */ + endpoint: string; + + /** + * The human-readable name for the McpConfig. Must be unique within your account. + * The first segment before '-' is used as the service name for tool routing (e.g., + * 'github-readonly' uses 'github' as the service name). + */ + name: string; + + /** + * Optional description for this MCP configuration. + */ + description?: string | null; +} + +/** + * A paginated list of McpConfigs. + */ +export interface McpConfigListView { + /** + * Whether there are more results available beyond this page. + */ + has_more: boolean; + + /** + * The list of McpConfigs. + */ + mcp_configs: Array; + + /** + * Total count of McpConfigs that match the query. + */ + total_count: number; +} + +/** + * Parameters for updating an existing McpConfig. All fields are optional - only + * specified fields will be updated. + */ +export interface McpConfigUpdateParameters { + /** + * New glob patterns specifying which tools are allowed. Examples: ['*'] for all + * tools, ['github.search_*'] for specific patterns. + */ + allowed_tools?: Array | null; + + /** + * New description for this MCP configuration. + */ + description?: string | null; + + /** + * New target MCP server endpoint URL. + */ + endpoint?: string | null; + + /** + * New name for the McpConfig. Must be unique within your account. + */ + name?: string | null; +} + +/** + * An McpConfig defines a configuration for connecting to an upstream MCP (Model + * Context Protocol) server. It specifies the target endpoint and which tools are + * allowed. + */ +export interface McpConfigView { + /** + * The unique identifier of the McpConfig. + */ + id: string; + + /** + * Glob patterns specifying which tools are allowed from this MCP server (e.g., + * ['github.search_*', 'github.get_*'] or ['*'] for all tools). + */ + allowed_tools: Array; + + /** + * Creation time of the McpConfig (Unix timestamp in milliseconds). + */ + create_time_ms: number; + + /** + * The target MCP server endpoint URL (e.g., 'https://mcp.example.com'). + */ + endpoint: string; + + /** + * The human-readable name of the McpConfig. Unique per account. + */ + name: string; + + /** + * Optional description for this MCP configuration. + */ + description?: string | null; +} + +export interface McpConfigCreateParams { + /** + * Glob patterns specifying which tools are allowed from this MCP server. Examples: + * ['*'] for all tools, ['github.search_*', 'github.get_*'] for specific patterns. + */ + allowed_tools: Array; + + /** + * The target MCP server endpoint URL (e.g., 'https://mcp.example.com'). + */ + endpoint: string; + + /** + * The human-readable name for the McpConfig. Must be unique within your account. + * The first segment before '-' is used as the service name for tool routing (e.g., + * 'github-readonly' uses 'github' as the service name). + */ + name: string; + + /** + * Optional description for this MCP configuration. + */ + description?: string | null; +} + +export interface McpConfigUpdateParams { + /** + * New glob patterns specifying which tools are allowed. Examples: ['*'] for all + * tools, ['github.search_*'] for specific patterns. + */ + allowed_tools?: Array | null; + + /** + * New description for this MCP configuration. + */ + description?: string | null; + + /** + * New target MCP server endpoint URL. + */ + endpoint?: string | null; + + /** + * New name for the McpConfig. Must be unique within your account. + */ + name?: string | null; +} + +export interface McpConfigListParams extends McpConfigsCursorIDPageParams { + /** + * Filter by ID. + */ + id?: string; + + /** + * Filter by name (prefix match supported). + */ + name?: string; +} + +export interface McpConfigDeleteParams {} + +McpConfigs.McpConfigViewsMcpConfigsCursorIDPage = McpConfigViewsMcpConfigsCursorIDPage; + +export declare namespace McpConfigs { + export { + type McpConfigCreateParameters as McpConfigCreateParameters, + type McpConfigListView as McpConfigListView, + type McpConfigUpdateParameters as McpConfigUpdateParameters, + type McpConfigView as McpConfigView, + McpConfigViewsMcpConfigsCursorIDPage as McpConfigViewsMcpConfigsCursorIDPage, + type McpConfigCreateParams as McpConfigCreateParams, + type McpConfigUpdateParams as McpConfigUpdateParams, + type McpConfigListParams as McpConfigListParams, + type McpConfigDeleteParams as McpConfigDeleteParams, + }; +} diff --git a/src/resources/scenarios/index.ts b/src/resources/scenarios/index.ts index bd2b01cc8..ae4589143 100644 --- a/src/resources/scenarios/index.ts +++ b/src/resources/scenarios/index.ts @@ -32,9 +32,7 @@ export { type ScorerRetrieveResponse, type ScorerUpdateResponse, type ScorerListResponse, - type ScorerValidateResponse, type ScorerCreateParams, type ScorerUpdateParams, type ScorerListParams, - type ScorerValidateParams, } from './scorers'; diff --git a/src/resources/scenarios/scenarios.ts b/src/resources/scenarios/scenarios.ts index 90d67878c..f0c127c7d 100644 --- a/src/resources/scenarios/scenarios.ts +++ b/src/resources/scenarios/scenarios.ts @@ -16,8 +16,6 @@ import { ScorerRetrieveResponse, ScorerUpdateParams, ScorerUpdateResponse, - ScorerValidateParams, - ScorerValidateResponse, Scorers, } from './scorers'; import { @@ -882,11 +880,9 @@ export declare namespace Scenarios { type ScorerRetrieveResponse as ScorerRetrieveResponse, type ScorerUpdateResponse as ScorerUpdateResponse, type ScorerListResponse as ScorerListResponse, - type ScorerValidateResponse as ScorerValidateResponse, ScorerListResponsesScenarioScorersCursorIDPage as ScorerListResponsesScenarioScorersCursorIDPage, type ScorerCreateParams as ScorerCreateParams, type ScorerUpdateParams as ScorerUpdateParams, type ScorerListParams as ScorerListParams, - type ScorerValidateParams as ScorerValidateParams, }; } diff --git a/src/resources/scenarios/scorers.ts b/src/resources/scenarios/scorers.ts index 5e5d0f892..86fbac8d8 100644 --- a/src/resources/scenarios/scorers.ts +++ b/src/resources/scenarios/scorers.ts @@ -3,7 +3,6 @@ import { APIResource } from '../../resource'; import { isRequestOptions } from '../../core'; import * as Core from '../../core'; -import * as ScenariosAPI from './scenarios'; import { ScenarioScorersCursorIDPage, type ScenarioScorersCursorIDPageParams } from '../../pagination'; export class Scorers extends APIResource { @@ -54,17 +53,6 @@ export class Scorers extends APIResource { ...options, }); } - - /** - * Validate a scenario scorer. - */ - validate( - id: string, - body: ScorerValidateParams, - options?: Core.RequestOptions, - ): Core.APIPromise { - return this._client.post(`/v1/scenarios/scorers/${id}/validate`, { body, ...options }); - } } export class ScorerListResponsesScenarioScorersCursorIDPage extends ScenarioScorersCursorIDPage {} @@ -149,28 +137,6 @@ export interface ScorerListResponse { type: string; } -export interface ScorerValidateResponse { - /** - * Name of the custom scorer. - */ - name: string; - - /** - * Json context that gets passed to the custom scorer - */ - scoring_context: unknown; - - /** - * Result of the scoring function. - */ - scoring_result: ScenariosAPI.ScoringFunctionResultView; - - /** - * The Environment in which the Scenario will run. - */ - environment_parameters?: ScenariosAPI.ScenarioEnvironment; -} - export interface ScorerCreateParams { /** * Bash script for the custom scorer taking context as a json object @@ -199,18 +165,6 @@ export interface ScorerUpdateParams { export interface ScorerListParams extends ScenarioScorersCursorIDPageParams {} -export interface ScorerValidateParams { - /** - * Json context that gets passed to the custom scorer - */ - scoring_context: unknown; - - /** - * The Environment in which the Scenario will run. - */ - environment_parameters?: ScenariosAPI.ScenarioEnvironment; -} - Scorers.ScorerListResponsesScenarioScorersCursorIDPage = ScorerListResponsesScenarioScorersCursorIDPage; export declare namespace Scorers { @@ -219,11 +173,9 @@ export declare namespace Scorers { type ScorerRetrieveResponse as ScorerRetrieveResponse, type ScorerUpdateResponse as ScorerUpdateResponse, type ScorerListResponse as ScorerListResponse, - type ScorerValidateResponse as ScorerValidateResponse, ScorerListResponsesScenarioScorersCursorIDPage as ScorerListResponsesScenarioScorersCursorIDPage, type ScorerCreateParams as ScorerCreateParams, type ScorerUpdateParams as ScorerUpdateParams, type ScorerListParams as ScorerListParams, - type ScorerValidateParams as ScorerValidateParams, }; } diff --git a/src/sdk/scorer.ts b/src/sdk/scorer.ts index 00241fca0..f7821c51b 100644 --- a/src/sdk/scorer.ts +++ b/src/sdk/scorer.ts @@ -6,8 +6,6 @@ import type { ScorerRetrieveResponse, ScorerUpdateResponse, ScorerUpdateParams, - ScorerValidateParams, - ScorerValidateResponse, } from '../resources/scenarios/scorers'; /** @@ -32,8 +30,8 @@ import type { * bash_script: 'echo "1.0"', * }); * - * const result = await scorer.validate({ scoring_context: { output: 'test' } }); - * console.log(`Score: ${result.scoring_result.score}`); + * const info = await scorer.getInfo(); + * console.log(`Scorer type: ${info.type}`); * ``` */ export class Scorer { @@ -176,27 +174,4 @@ export class Scorer { async update(params: ScorerUpdateParams, options?: Core.RequestOptions): Promise { return this.client.scenarios.scorers.update(this._id, params, options); } - - /** - * Run the scorer against the provided context and return the result. - * - * @example - * ```typescript - * const result = await scorer.validate({ - * scoring_context: { output: 'test output', expected: 'test output' } - * }); - * console.log(`Validation score: ${result.scoring_result.score}`); - * console.log(`Output: ${result.scoring_result.output}`); - * ``` - * - * @param {ScorerValidateParams} params - Validation parameters - * @param {Core.RequestOptions} [options] - Request options - * @returns {Promise} Validation result with score - */ - async validate( - params: ScorerValidateParams, - options?: Core.RequestOptions, - ): Promise { - return this.client.scenarios.scorers.validate(this._id, params, options); - } } diff --git a/src/version.ts b/src/version.ts index 8fe4c2e5a..1c2e26105 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '1.6.0'; // x-release-please-version +export const VERSION = '1.7.0'; // x-release-please-version diff --git a/tests/api-resources/devboxes/devboxes.test.ts b/tests/api-resources/devboxes/devboxes.test.ts index 87be10290..06d942371 100644 --- a/tests/api-resources/devboxes/devboxes.test.ts +++ b/tests/api-resources/devboxes/devboxes.test.ts @@ -61,6 +61,7 @@ describe('resource devboxes', () => { resource_size_request: 'X_SMALL', user_parameters: { uid: 0, username: 'username' }, }, + mcp: [{ mcp_config: 'mcp_config', secret: 'secret' }], metadata: { foo: 'string' }, mounts: [ { diff --git a/tests/api-resources/mcp-configs.test.ts b/tests/api-resources/mcp-configs.test.ts new file mode 100644 index 000000000..78a8f38bb --- /dev/null +++ b/tests/api-resources/mcp-configs.test.ts @@ -0,0 +1,138 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Runloop from '@runloop/api-client'; +import { Response } from 'node-fetch'; + +const client = new Runloop({ + bearerToken: 'My Bearer Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource mcpConfigs', () => { + test('create: only required params', async () => { + const responsePromise = client.mcpConfigs.create({ + allowed_tools: ['string'], + endpoint: 'endpoint', + name: 'name', + }); + 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('create: required and optional params', async () => { + const response = await client.mcpConfigs.create({ + allowed_tools: ['string'], + endpoint: 'endpoint', + name: 'name', + description: 'description', + }); + }); + + test('retrieve', async () => { + const responsePromise = client.mcpConfigs.retrieve('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('retrieve: 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.mcpConfigs.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( + Runloop.NotFoundError, + ); + }); + + test('update', async () => { + const responsePromise = client.mcpConfigs.update('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('update: 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.mcpConfigs.update('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( + Runloop.NotFoundError, + ); + }); + + test('update: 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.mcpConfigs.update( + 'id', + { + allowed_tools: ['string'], + description: 'description', + endpoint: 'endpoint', + name: 'name', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Runloop.NotFoundError); + }); + + test('list', async () => { + const responsePromise = client.mcpConfigs.list(); + 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('list: 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.mcpConfigs.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( + Runloop.NotFoundError, + ); + }); + + test('list: 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.mcpConfigs.list( + { + id: 'id', + limit: 0, + name: 'name', + starting_after: 'starting_after', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Runloop.NotFoundError); + }); + + test('delete', async () => { + const responsePromise = client.mcpConfigs.delete('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('delete: 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.mcpConfigs.delete('id', {}, { path: '/_stainless_unknown_path' })).rejects.toThrow( + Runloop.NotFoundError, + ); + }); +}); diff --git a/tests/api-resources/scenarios/scorers.test.ts b/tests/api-resources/scenarios/scorers.test.ts index a5c36efe7..b78ab2bb0 100644 --- a/tests/api-resources/scenarios/scorers.test.ts +++ b/tests/api-resources/scenarios/scorers.test.ts @@ -90,40 +90,4 @@ describe('resource scorers', () => { ), ).rejects.toThrow(Runloop.NotFoundError); }); - - test('validate: only required params', async () => { - const responsePromise = client.scenarios.scorers.validate('id', { scoring_context: {} }); - 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('validate: required and optional params', async () => { - const response = await client.scenarios.scorers.validate('id', { - scoring_context: {}, - environment_parameters: { - blueprint_id: 'blueprint_id', - launch_parameters: { - after_idle: { idle_time_seconds: 0, on_idle: 'shutdown' }, - architecture: 'x86_64', - available_ports: [0], - custom_cpu_cores: 0, - custom_disk_size: 0, - custom_gb_memory: 0, - keep_alive_time_seconds: 0, - launch_commands: ['string'], - network_policy_id: 'network_policy_id', - required_services: ['string'], - resource_size_request: 'X_SMALL', - user_parameters: { uid: 0, username: 'username' }, - }, - snapshot_id: 'snapshot_id', - working_directory: 'working_directory', - }, - }); - }); }); diff --git a/tests/objects/scorer.test.ts b/tests/objects/scorer.test.ts index 337555a1b..6cfbdfda1 100644 --- a/tests/objects/scorer.test.ts +++ b/tests/objects/scorer.test.ts @@ -2,7 +2,6 @@ import { Scorer } from '../../src/sdk/scorer'; import type { ScorerRetrieveResponse, ScorerUpdateResponse, - ScorerValidateResponse, } from '../../src/resources/scenarios/scorers'; // Mock the Runloop client @@ -11,7 +10,6 @@ jest.mock('../../src/index'); describe('Scorer', () => { let mockClient: any; let mockScorerData: ScorerRetrieveResponse; - let mockValidateResult: ScorerValidateResponse; beforeEach(() => { mockClient = { @@ -20,7 +18,6 @@ describe('Scorer', () => { create: jest.fn(), retrieve: jest.fn(), update: jest.fn(), - validate: jest.fn(), list: jest.fn(), }, }, @@ -32,16 +29,6 @@ describe('Scorer', () => { bash_script: 'echo "1.0"', }; - mockValidateResult = { - name: 'my_custom_scorer', - scoring_context: { output: 'test' }, - scoring_result: { - output: '1.0', - score: 1.0, - state: 'complete', - scoring_function_name: 'test-scorer', - }, - }; }); describe('fromId', () => { @@ -188,38 +175,6 @@ describe('Scorer', () => { }); }); - describe('validate', () => { - it('should validate scorer with scoring context', async () => { - mockClient.scenarios.scorers.validate.mockResolvedValue(mockValidateResult); - - const scorer = Scorer.fromId(mockClient, 'scs_123'); - const result = await scorer.validate({ - scoring_context: { output: 'test output', expected: 'expected output' }, - }); - - expect(mockClient.scenarios.scorers.validate).toHaveBeenCalledWith( - 'scs_123', - { scoring_context: { output: 'test output', expected: 'expected output' } }, - undefined, - ); - expect(result.scoring_result.score).toBe(1.0); - expect(result.scoring_result.output).toBe('1.0'); - }); - - it('should pass options to the API client', async () => { - mockClient.scenarios.scorers.validate.mockResolvedValue(mockValidateResult); - - const scorer = Scorer.fromId(mockClient, 'scs_123'); - await scorer.validate({ scoring_context: {} }, { timeout: 30000 }); - - expect(mockClient.scenarios.scorers.validate).toHaveBeenCalledWith( - 'scs_123', - { scoring_context: {} }, - { timeout: 30000 }, - ); - }); - }); - describe('error handling', () => { it('should handle API errors on getInfo', async () => { const error = new Error('Scorer not found'); @@ -241,13 +196,5 @@ describe('Scorer', () => { ); }); - it('should handle API errors on validate', async () => { - const error = new Error('Validation timeout'); - mockClient.scenarios.scorers.validate.mockRejectedValue(error); - - const scorer = Scorer.fromId(mockClient, 'scs_123'); - - await expect(scorer.validate({ scoring_context: {} })).rejects.toThrow('Validation timeout'); - }); }); });