diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 8ea34be..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM debian:bookworm-slim AS stainless - -RUN apt-get update && apt-get install -y \ - nodejs \ - npm \ - yarnpkg \ - && apt-get clean autoclean - -# Ensure UTF-8 encoding -ENV LANG=C.UTF-8 -ENV LC_ALL=C.UTF-8 - -# Yarn -RUN ln -sf /usr/bin/yarnpkg /usr/bin/yarn - -WORKDIR /workspace - -COPY package.json yarn.lock /workspace/ - -RUN yarn install - -COPY . /workspace diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d55fc4d..763462f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,17 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/debian { - "name": "Debian", - "build": { - "dockerfile": "Dockerfile" + "name": "Development", + "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", + "features": { + "ghcr.io/devcontainers/features/node:1": {} + }, + "postCreateCommand": "yarn install", + "customizations": { + "vscode": { + "extensions": [ + "esbenp.prettier-vscode" + ] + } } - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Configure tool-specific properties. - // "customizations": {}, - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ddb531a..d8b41c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,19 +1,18 @@ name: CI on: push: - branches: - - main - pull_request: - branches: - - main - - next + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' jobs: lint: + timeout-minutes: 10 name: lint - runs-on: ubuntu-latest - - + runs-on: ${{ github.repository == 'stainless-sdks/openlayer-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@v4 @@ -29,10 +28,12 @@ jobs: run: ./scripts/lint build: + timeout-minutes: 5 name: build - runs-on: ubuntu-latest - - + runs-on: ${{ github.repository == 'stainless-sdks/openlayer-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v4 @@ -46,3 +47,18 @@ jobs: - name: Check build run: ./scripts/build + + - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/openlayer-node' + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Upload tarball + if: github.repository == 'stainless-sdks/openlayer-node' + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + run: ./scripts/utils/upload-artifact.sh diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8032c17..ed21d28 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.12.0" + ".": "0.13.0" } diff --git a/.stats.yml b/.stats.yml index c254947..2b09528 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1,3 @@ -configured_endpoints: 15 +configured_endpoints: 18 +openapi_spec_hash: 20f058101a252f7500803d66aff58eb3 +config_hash: 30422a4611d93ca69e4f1aff60b9ddb5 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b97fbb..085307a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,59 @@ # Changelog +## 0.13.0 (2025-05-01) + +Full Changelog: [v0.12.0...v0.13.0](https://github.com/openlayer-ai/openlayer-ts/compare/v0.12.0...v0.13.0) + +### Features + +* **api:** add test creation endpoint ([b7cc1b1](https://github.com/openlayer-ai/openlayer-ts/commit/b7cc1b1ee12af1275addac7057d735fb02a43af1)) +* **api:** api update ([372b228](https://github.com/openlayer-ai/openlayer-ts/commit/372b228b95947b7ccb8d6acc9a35eb7a20a31ef6)) +* **api:** api update ([8e2a339](https://github.com/openlayer-ai/openlayer-ts/commit/8e2a33931654d6802087b6435a4beb2c6ed6d7e1)) +* **api:** api update ([2e0a6e1](https://github.com/openlayer-ai/openlayer-ts/commit/2e0a6e1b6a5b3296a3ec905dfa11b5a8501e4583)) +* **api:** api update ([821a692](https://github.com/openlayer-ai/openlayer-ts/commit/821a6926192dad0532029ea9c2b22a4d24f5e1c6)) +* **api:** api update ([28f4085](https://github.com/openlayer-ai/openlayer-ts/commit/28f40851950cfa354930fc8dfab69b4a39f3d13e)) +* **api:** api update ([3345b62](https://github.com/openlayer-ai/openlayer-ts/commit/3345b629c1904bfb2c2f9e05c86312c6c7b88b48)) +* **api:** expose test retrieval endpoint ([da2b9fb](https://github.com/openlayer-ai/openlayer-ts/commit/da2b9fb62bd0eeaebe1325abaee6e4854d2f987f)) +* **api:** expose test retrieval endpoint ([f3fd3fc](https://github.com/openlayer-ai/openlayer-ts/commit/f3fd3fc296af8982eeb965c3427b89abdb7a4a6f)) +* **api:** expose test update endpoint ([785d3b4](https://github.com/openlayer-ai/openlayer-ts/commit/785d3b4ba67f487b49c190d546ae4a7dc7eb333b)) +* **client:** send `X-Stainless-Timeout` header ([333edef](https://github.com/openlayer-ai/openlayer-ts/commit/333edef002f95acecdb29d3e6a698343c3361937)) + + +### Bug Fixes + +* **api:** improve type resolution when importing as a package ([#119](https://github.com/openlayer-ai/openlayer-ts/issues/119)) ([669c259](https://github.com/openlayer-ai/openlayer-ts/commit/669c259b9fa3ba40ace9901ba24fa80dbc205105)) +* avoid type error in certain environments ([#115](https://github.com/openlayer-ai/openlayer-ts/issues/115)) ([701091f](https://github.com/openlayer-ai/openlayer-ts/commit/701091ff829ca7b7f6ee3bf66af961b660eb3371)) +* **client:** fix export map for index exports ([ac3dffc](https://github.com/openlayer-ai/openlayer-ts/commit/ac3dffce4624d350d5cf73e3020067cb2f71ab59)) +* **client:** send `X-Stainless-Timeout` in seconds ([#117](https://github.com/openlayer-ai/openlayer-ts/issues/117)) ([b8469f3](https://github.com/openlayer-ai/openlayer-ts/commit/b8469f3c2fc46916d994fb20b6ff4550a1c2bed3)) +* **internal:** work around https://github.com/vercel/next.js/issues/76881 ([#116](https://github.com/openlayer-ai/openlayer-ts/issues/116)) ([2349019](https://github.com/openlayer-ai/openlayer-ts/commit/2349019081867529df94ff1143716ce865a30007)) +* **mcp:** remove unused tools.ts ([#120](https://github.com/openlayer-ai/openlayer-ts/issues/120)) ([9d9ab9b](https://github.com/openlayer-ai/openlayer-ts/commit/9d9ab9bd791a42fc4269ad0fcd1dbb57f8616e67)) + + +### Chores + +* **ci:** add timeout thresholds for CI jobs ([64632ad](https://github.com/openlayer-ai/openlayer-ts/commit/64632ad55c30e27a0ca063c28b410d6b83b245b4)) +* **ci:** only use depot for staging repos ([9c8f4b9](https://github.com/openlayer-ai/openlayer-ts/commit/9c8f4b9181f636898c5ff8365596b47c591575f1)) +* **client:** minor internal fixes ([344120f](https://github.com/openlayer-ai/openlayer-ts/commit/344120f8eb82ea1e374aafadf6c7e90edec2cbce)) +* **exports:** cleaner resource index imports ([#113](https://github.com/openlayer-ai/openlayer-ts/issues/113)) ([9ac3180](https://github.com/openlayer-ai/openlayer-ts/commit/9ac318013fd2128e7f0a98db699534569c8e18a3)) +* **exports:** stop using path fallbacks ([#114](https://github.com/openlayer-ai/openlayer-ts/issues/114)) ([fdcd6e2](https://github.com/openlayer-ai/openlayer-ts/commit/fdcd6e2effcd89201604c545e0c3b8f0f0800032)) +* **internal:** add aliases for Record and Array ([#118](https://github.com/openlayer-ai/openlayer-ts/issues/118)) ([da4702c](https://github.com/openlayer-ai/openlayer-ts/commit/da4702cab36298cc7278a3f0a797742c5e23a002)) +* **internal:** codegen related update ([1128c8f](https://github.com/openlayer-ai/openlayer-ts/commit/1128c8f19942ebfecc014626f859dfdadc5725d1)) +* **internal:** codegen related update ([1016df6](https://github.com/openlayer-ai/openlayer-ts/commit/1016df6f549fd3312c26f6ecfd15b3aac58c5d65)) +* **internal:** codegen related update ([ca17307](https://github.com/openlayer-ai/openlayer-ts/commit/ca173073bc522424d9d6a35b5a2af14ccd7b8c88)) +* **internal:** codegen related update ([fd5d0a9](https://github.com/openlayer-ai/openlayer-ts/commit/fd5d0a9808b2abf8d1b88d3becf2350d9b25887e)) +* **internal:** fix devcontainers setup ([6a459de](https://github.com/openlayer-ai/openlayer-ts/commit/6a459de24ebec36ba38b751b6ab7143b3b9e16fd)) +* **internal:** fix workflows ([59a7cb4](https://github.com/openlayer-ai/openlayer-ts/commit/59a7cb4439a344c0ed6b4adb9e6b113dbed0f940)) +* **internal:** reduce CI branch coverage ([71998ef](https://github.com/openlayer-ai/openlayer-ts/commit/71998ef9132f29569e40aa1310cf2b3611096865)) +* **internal:** upload builds and expand CI branch coverage ([5d8ec66](https://github.com/openlayer-ai/openlayer-ts/commit/5d8ec66ad5ca7ba34da7b56b5f2aa1e9638107cd)) +* **internal:** version bump ([3a31790](https://github.com/openlayer-ai/openlayer-ts/commit/3a317902d8bf523f3f54398cdb077a11a18d9995)) +* **tests:** improve enum examples ([#121](https://github.com/openlayer-ai/openlayer-ts/issues/121)) ([f3a00ab](https://github.com/openlayer-ai/openlayer-ts/commit/f3a00ab15a42239fc71459feb324bd835f5d79e9)) + + +### Documentation + +* **readme:** fix typo ([3461fd6](https://github.com/openlayer-ai/openlayer-ts/commit/3461fd6e7a989064ef94b9e1d0c8d26374116aa4)) +* update URLs from stainlessapi.com to stainless.com ([e56ef04](https://github.com/openlayer-ai/openlayer-ts/commit/e56ef04346aa002b8481a8018ad540c678a9a21e)) + ## 0.12.0 (2025-03-14) Full Changelog: [v0.11.0...v0.12.0](https://github.com/openlayer-ai/openlayer-ts/compare/v0.11.0...v0.12.0) diff --git a/README.md b/README.md index c0a8352..f6b1ed4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This library provides convenient access to the Openlayer REST API from server-si The REST API documentation can be found on [openlayer.com](https://openlayer.com/docs/api-reference/rest/overview). The full API of this library can be found in [api.md](api.md). -It is generated with [Stainless](https://www.stainlessapi.com/). +It is generated with [Stainless](https://www.stainless.com/). ## Installation @@ -134,7 +134,7 @@ async function main() { main(); ``` -Error codes are as followed: +Error codes are as follows: | Status Code | Error Type | | ----------- | -------------------------- | @@ -380,7 +380,7 @@ await client.inferencePipelines.data.stream( This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: 1. Changes that only affect static types, without breaking runtime behavior. -2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals)_. +2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ 3. Changes that we do not expect to impact the vast majority of users in practice. We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. diff --git a/SECURITY.md b/SECURITY.md index 6dfa13e..8614b05 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,9 +2,9 @@ ## Reporting Security Issues -This SDK is generated by [Stainless Software Inc](http://stainlessapi.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. -To report a security issue, please contact the Stainless team at security@stainlessapi.com. +To report a security issue, please contact the Stainless team at security@stainless.com. ## Responsible Disclosure diff --git a/api.md b/api.md index 93b4252..6de15d2 100644 --- a/api.md +++ b/api.md @@ -34,6 +34,20 @@ Methods: - client.projects.inferencePipelines.create(projectId, { ...params }) -> InferencePipelineCreateResponse - client.projects.inferencePipelines.list(projectId, { ...params }) -> InferencePipelineListResponse +## Tests + +Types: + +- TestCreateResponse +- TestUpdateResponse +- TestListResponse + +Methods: + +- client.projects.tests.create(projectId, { ...params }) -> TestCreateResponse +- client.projects.tests.update(projectId, { ...params }) -> TestUpdateResponse +- client.projects.tests.list(projectId, { ...params }) -> TestListResponse + # Commits Types: diff --git a/bin/check-release-environment b/bin/check-release-environment index 0f4fafe..5da9dd7 100644 --- a/bin/check-release-environment +++ b/bin/check-release-environment @@ -2,6 +2,10 @@ errors=() +if [ -z "${STAINLESS_API_KEY}" ]; then + errors+=("The STAINLESS_API_KEY secret has not been set. Please contact Stainless for an API key & set it in your organization secrets on GitHub.") +fi + if [ -z "${NPM_TOKEN}" ]; then errors+=("The OPENLAYER_NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") fi diff --git a/package.json b/package.json index 13eefa3..b6df9a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openlayer", - "version": "0.12.0", + "version": "0.13.0", "description": "The official TypeScript library for the Openlayer API", "author": "Openlayer ", "types": "dist/index.d.ts", diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh new file mode 100755 index 0000000..380c00e --- /dev/null +++ b/scripts/utils/upload-artifact.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -exuo pipefail + +RESPONSE=$(curl -X POST "$URL" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + +SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') + +if [[ "$SIGNED_URL" == "null" ]]; then + echo -e "\033[31mFailed to get signed URL.\033[0m" + exit 1 +fi + +UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \ + -H "Content-Type: application/gzip" \ + --data-binary @- "$SIGNED_URL" 2>&1) + +if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then + echo -e "\033[32mUploaded build to Stainless storage.\033[0m" + echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/openlayer-node/$SHA'\033[0m" +else + echo -e "\033[31mFailed to upload artifact.\033[0m" + exit 1 +fi diff --git a/src/_shims/index-deno.ts b/src/_shims/index-deno.ts index f98dad2..e755878 100644 --- a/src/_shims/index-deno.ts +++ b/src/_shims/index-deno.ts @@ -108,3 +108,5 @@ export declare class FsReadStream extends Readable { const _ReadableStream = ReadableStream; type _ReadableStream = ReadableStream; export { _ReadableStream as ReadableStream }; + +export const init = () => {}; diff --git a/src/_shims/index.d.ts b/src/_shims/index.d.ts index 63ce99a..e3d9fc4 100644 --- a/src/_shims/index.d.ts +++ b/src/_shims/index.d.ts @@ -79,3 +79,5 @@ export function fileFromPath(path: string, options?: FileFromPathOptions): Promi export function fileFromPath(path: string, filename?: string, options?: FileFromPathOptions): Promise; export function isFsReadStream(value: any): value is FsReadStream; + +export const init: () => void; diff --git a/src/_shims/index.js b/src/_shims/index.js index 6b777dd..639ea48 100644 --- a/src/_shims/index.js +++ b/src/_shims/index.js @@ -3,7 +3,9 @@ */ const shims = require('./registry'); const auto = require('openlayer/_shims/auto/runtime'); -if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); +exports.init = () => { + if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); +}; for (const property of Object.keys(shims)) { Object.defineProperty(exports, property, { get() { @@ -11,3 +13,5 @@ for (const property of Object.keys(shims)) { }, }); } + +exports.init(); diff --git a/src/_shims/index.mjs b/src/_shims/index.mjs index 624fd3d..159fb36 100644 --- a/src/_shims/index.mjs +++ b/src/_shims/index.mjs @@ -3,5 +3,9 @@ */ import * as shims from './registry.mjs'; import * as auto from 'openlayer/_shims/auto/runtime'; -if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); +export const init = () => { + if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); +}; export * from './registry.mjs'; + +init(); diff --git a/src/core.ts b/src/core.ts index 5981ff8..27031d0 100644 --- a/src/core.ts +++ b/src/core.ts @@ -16,7 +16,12 @@ import { type RequestInit, type Response, type HeadersInit, + init, } from './_shims/index'; + +// try running side effects outside of _shims/index to workaround https://github.com/vercel/next.js/issues/76881 +init(); + export { type Response }; import { BlobLike, isBlobLike, isMultipartBody } from './uploads'; export { @@ -28,6 +33,20 @@ export { export type Fetch = (url: RequestInfo, init?: RequestInit) => Promise; +/** + * An alias to the builtin `Array` type so we can + * easily alias it in import statements if there are name clashes. + */ +type _Array = Array; + +/** + * An alias to the builtin `Record` type so we can + * easily alias it in import statements if there are name clashes. + */ +type _Record = Record; + +export type { _Array as Array, _Record as Record }; + type PromiseOrValue = T | Promise; type APIResponseProps = { @@ -277,9 +296,10 @@ export abstract class APIClient { } buildRequest( - options: FinalRequestOptions, + inputOptions: FinalRequestOptions, { retryCount = 0 }: { retryCount?: number } = {}, ): { req: RequestInit; url: string; timeout: number } { + const options = { ...inputOptions }; const { method, path, query, headers: headers = {} } = options; const body = @@ -292,9 +312,9 @@ export abstract class APIClient { const url = this.buildURL(path!, query); if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); - const timeout = options.timeout ?? this.timeout; + options.timeout = options.timeout ?? this.timeout; const httpAgent = options.httpAgent ?? this.httpAgent ?? getDefaultAgent(url); - const minAgentTimeout = timeout + 1000; + const minAgentTimeout = options.timeout + 1000; if ( typeof (httpAgent as any)?.options?.timeout === 'number' && minAgentTimeout > ((httpAgent as any).options.timeout ?? 0) @@ -307,8 +327,8 @@ export abstract class APIClient { } if (this.idempotencyHeader && method !== 'get') { - if (!options.idempotencyKey) options.idempotencyKey = this.defaultIdempotencyKey(); - headers[this.idempotencyHeader] = options.idempotencyKey; + if (!inputOptions.idempotencyKey) inputOptions.idempotencyKey = this.defaultIdempotencyKey(); + headers[this.idempotencyHeader] = inputOptions.idempotencyKey; } const reqHeaders = this.buildHeaders({ options, headers, contentLength, retryCount }); @@ -323,7 +343,7 @@ export abstract class APIClient { signal: options.signal ?? null, }; - return { req, url, timeout }; + return { req, url, timeout: options.timeout }; } private buildHeaders({ @@ -351,15 +371,22 @@ export abstract class APIClient { delete reqHeaders['content-type']; } - // Don't set the retry count header if it was already set or removed through default headers or by the - // caller. We check `defaultHeaders` and `headers`, which can contain nulls, instead of `reqHeaders` to - // account for the removal case. + // Don't set theses headers if they were already set or removed through default headers or by the caller. + // We check `defaultHeaders` and `headers`, which can contain nulls, instead of `reqHeaders` to account + // for the removal case. if ( getHeader(defaultHeaders, 'x-stainless-retry-count') === undefined && getHeader(headers, 'x-stainless-retry-count') === undefined ) { reqHeaders['x-stainless-retry-count'] = String(retryCount); } + if ( + getHeader(defaultHeaders, 'x-stainless-timeout') === undefined && + getHeader(headers, 'x-stainless-timeout') === undefined && + options.timeout + ) { + reqHeaders['x-stainless-timeout'] = String(Math.trunc(options.timeout / 1000)); + } this.validateHeaders(reqHeaders, headers); @@ -387,7 +414,7 @@ export abstract class APIClient { !headers ? {} : Symbol.iterator in headers ? Object.fromEntries(Array.from(headers as Iterable).map((header) => [...header])) - : { ...headers } + : { ...(headers as any as Record) } ); } diff --git a/src/index.ts b/src/index.ts index e2cc2f8..96767aa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,7 +43,7 @@ export interface ClientOptions { * Note that request timeouts are retried by default, so in a worst-case scenario you may wait * much longer than this timeout before the promise succeeds or fails. */ - timeout?: number; + timeout?: number | undefined; /** * An HTTP agent used to manage HTTP(S) connections. @@ -51,7 +51,7 @@ export interface ClientOptions { * If not provided, an agent will be constructed by default in the Node.js environment, * otherwise no agent is used. */ - httpAgent?: Agent; + httpAgent?: Agent | undefined; /** * Specify a custom `fetch` function implementation. @@ -67,7 +67,7 @@ export interface ClientOptions { * * @default 2 */ - maxRetries?: number; + maxRetries?: number | undefined; /** * Default headers to include with every request to the API. @@ -75,7 +75,7 @@ export interface ClientOptions { * These can be removed in individual requests by explicitly setting the * header to `undefined` or `null` in request options. */ - defaultHeaders?: Core.Headers; + defaultHeaders?: Core.Headers | undefined; /** * Default query parameters to include with every request to the API. @@ -83,7 +83,7 @@ export interface ClientOptions { * These can be removed in individual requests by explicitly setting the * param to `undefined` in request options. */ - defaultQuery?: Core.DefaultQuery; + defaultQuery?: Core.DefaultQuery | undefined; } /** diff --git a/src/resources.ts b/src/resources.ts new file mode 100644 index 0000000..b283d57 --- /dev/null +++ b/src/resources.ts @@ -0,0 +1 @@ +export * from './resources/index'; diff --git a/src/resources/commits/test-results.ts b/src/resources/commits/test-results.ts index ab1b977..e8a5d7a 100644 --- a/src/resources/commits/test-results.ts +++ b/src/resources/commits/test-results.ts @@ -140,7 +140,48 @@ export namespace TestResultListResponse { /** * The test subtype. */ - subtype: string; + subtype: + | 'anomalousColumnCount' + | 'characterLength' + | 'classImbalanceRatio' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnStatistic' + | 'columnValuesMatch' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatureCount' + | 'customMetricThreshold' + | 'duplicateRowCount' + | 'emptyFeature' + | 'emptyFeatureCount' + | 'driftedFeatureCount' + | 'featureMissingValues' + | 'featureValueValidation' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricThresholdV2' + | 'labelDrift' + | 'metricThreshold' + | 'newCategoryCount' + | 'newLabelCount' + | 'nullRowCount' + | 'rowCount' + | 'ppScoreValueValidation' + | 'quasiConstantFeature' + | 'quasiConstantFeatureCount' + | 'sqlQuery' + | 'dtypeValidation' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharactersRatio' + | 'stringValidation' + | 'trainValLeakageRowCount'; /** * Whether the test is suggested or user-created. @@ -152,7 +193,7 @@ export namespace TestResultListResponse { /** * The test type. */ - type: string; + type: 'integrity' | 'consistency' | 'performance'; /** * Whether the test is archived. @@ -201,9 +242,48 @@ export namespace TestResultListResponse { /** * The insight name to be evaluated. */ - insightName?: string; + insightName?: + | 'characterLength' + | 'classImbalance' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnValuesMatch' + | 'confidenceDistribution' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatures' + | 'customMetric' + | 'duplicateRowCount' + | 'emptyFeatures' + | 'featureDrift' + | 'featureProfile' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricV2' + | 'labelDrift' + | 'metrics' + | 'newCategories' + | 'newLabels' + | 'nullRowCount' + | 'ppScore' + | 'quasiConstantFeatures' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharacters' + | 'stringValidation' + | 'trainValLeakageRowCount'; - insightParameters?: Array; + /** + * The insight parameters. Required only for some test subtypes. For example, for + * tests that require a column name, the insight parameters will be [{'name': + * 'column_name', 'value': 'Age'}] + */ + insightParameters?: Array | null; /** * The measurement to be evaluated. @@ -213,20 +293,36 @@ export namespace TestResultListResponse { /** * The operator to be used for the evaluation. */ - operator?: string; + operator?: 'is' | '>' | '>=' | '<' | '<=' | '!='; + + /** + * Whether to use automatic anomaly detection or manual thresholds + */ + thresholdMode?: 'automatic' | 'manual'; /** * The value to be compared. */ value?: number | boolean | string | Array; } + + export namespace Threshold { + export interface InsightParameter { + /** + * The name of the insight filter. + */ + name: string; + + value: unknown; + } + } } } } export interface TestResultListParams { /** - * Include archived goals. + * Filter for archived tests. */ includeArchived?: boolean; diff --git a/src/resources/inference-pipelines/inference-pipelines.ts b/src/resources/inference-pipelines/inference-pipelines.ts index efdb59b..4e5b1c8 100644 --- a/src/resources/inference-pipelines/inference-pipelines.ts +++ b/src/resources/inference-pipelines/inference-pipelines.ts @@ -275,26 +275,59 @@ export namespace InferencePipelineRetrieveResponse { } export interface Workspace { + /** + * The workspace id. + */ id: string; + /** + * The workspace creator id. + */ creatorId: string | null; + /** + * The workspace creation date. + */ dateCreated: string; + /** + * The workspace last updated date. + */ dateUpdated: string; + /** + * The number of invites in the workspace. + */ inviteCount: number; + /** + * The number of members in the workspace. + */ memberCount: number; + /** + * The workspace name. + */ name: string; + /** + * The end date of the current billing period. + */ periodEndDate: string | null; + /** + * The start date of the current billing period. + */ periodStartDate: string | null; + /** + * The number of projects in the workspace. + */ projectCount: number; + /** + * The workspace slug. + */ slug: string; status: @@ -309,6 +342,9 @@ export namespace InferencePipelineRetrieveResponse { monthlyUsage?: Array; + /** + * Whether the workspace only allows SAML authentication. + */ samlOnlyAccess?: boolean; wildcardDomains?: Array; @@ -528,26 +564,59 @@ export namespace InferencePipelineUpdateResponse { } export interface Workspace { + /** + * The workspace id. + */ id: string; + /** + * The workspace creator id. + */ creatorId: string | null; + /** + * The workspace creation date. + */ dateCreated: string; + /** + * The workspace last updated date. + */ dateUpdated: string; + /** + * The number of invites in the workspace. + */ inviteCount: number; + /** + * The number of members in the workspace. + */ memberCount: number; + /** + * The workspace name. + */ name: string; + /** + * The end date of the current billing period. + */ periodEndDate: string | null; + /** + * The start date of the current billing period. + */ periodStartDate: string | null; + /** + * The number of projects in the workspace. + */ projectCount: number; + /** + * The workspace slug. + */ slug: string; status: @@ -562,6 +631,9 @@ export namespace InferencePipelineUpdateResponse { monthlyUsage?: Array; + /** + * Whether the workspace only allows SAML authentication. + */ samlOnlyAccess?: boolean; wildcardDomains?: Array; diff --git a/src/resources/inference-pipelines/test-results.ts b/src/resources/inference-pipelines/test-results.ts index 17a72f9..2e852c6 100644 --- a/src/resources/inference-pipelines/test-results.ts +++ b/src/resources/inference-pipelines/test-results.ts @@ -140,7 +140,48 @@ export namespace TestResultListResponse { /** * The test subtype. */ - subtype: string; + subtype: + | 'anomalousColumnCount' + | 'characterLength' + | 'classImbalanceRatio' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnStatistic' + | 'columnValuesMatch' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatureCount' + | 'customMetricThreshold' + | 'duplicateRowCount' + | 'emptyFeature' + | 'emptyFeatureCount' + | 'driftedFeatureCount' + | 'featureMissingValues' + | 'featureValueValidation' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricThresholdV2' + | 'labelDrift' + | 'metricThreshold' + | 'newCategoryCount' + | 'newLabelCount' + | 'nullRowCount' + | 'rowCount' + | 'ppScoreValueValidation' + | 'quasiConstantFeature' + | 'quasiConstantFeatureCount' + | 'sqlQuery' + | 'dtypeValidation' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharactersRatio' + | 'stringValidation' + | 'trainValLeakageRowCount'; /** * Whether the test is suggested or user-created. @@ -152,7 +193,7 @@ export namespace TestResultListResponse { /** * The test type. */ - type: string; + type: 'integrity' | 'consistency' | 'performance'; /** * Whether the test is archived. @@ -201,9 +242,48 @@ export namespace TestResultListResponse { /** * The insight name to be evaluated. */ - insightName?: string; + insightName?: + | 'characterLength' + | 'classImbalance' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnValuesMatch' + | 'confidenceDistribution' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatures' + | 'customMetric' + | 'duplicateRowCount' + | 'emptyFeatures' + | 'featureDrift' + | 'featureProfile' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricV2' + | 'labelDrift' + | 'metrics' + | 'newCategories' + | 'newLabels' + | 'nullRowCount' + | 'ppScore' + | 'quasiConstantFeatures' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharacters' + | 'stringValidation' + | 'trainValLeakageRowCount'; - insightParameters?: Array; + /** + * The insight parameters. Required only for some test subtypes. For example, for + * tests that require a column name, the insight parameters will be [{'name': + * 'column_name', 'value': 'Age'}] + */ + insightParameters?: Array | null; /** * The measurement to be evaluated. @@ -213,13 +293,29 @@ export namespace TestResultListResponse { /** * The operator to be used for the evaluation. */ - operator?: string; + operator?: 'is' | '>' | '>=' | '<' | '<=' | '!='; + + /** + * Whether to use automatic anomaly detection or manual thresholds + */ + thresholdMode?: 'automatic' | 'manual'; /** * The value to be compared. */ value?: number | boolean | string | Array; } + + export namespace Threshold { + export interface InsightParameter { + /** + * The name of the insight filter. + */ + name: string; + + value: unknown; + } + } } } } diff --git a/src/resources/projects/index.ts b/src/resources/projects/index.ts index de97190..c53d21e 100644 --- a/src/resources/projects/index.ts +++ b/src/resources/projects/index.ts @@ -21,3 +21,12 @@ export { type ProjectCreateParams, type ProjectListParams, } from './projects'; +export { + Tests, + type TestCreateResponse, + type TestUpdateResponse, + type TestListResponse, + type TestCreateParams, + type TestUpdateParams, + type TestListParams, +} from './tests'; diff --git a/src/resources/projects/inference-pipelines.ts b/src/resources/projects/inference-pipelines.ts index 7f91d92..eed6c61 100644 --- a/src/resources/projects/inference-pipelines.ts +++ b/src/resources/projects/inference-pipelines.ts @@ -240,26 +240,59 @@ export namespace InferencePipelineCreateResponse { } export interface Workspace { + /** + * The workspace id. + */ id: string; + /** + * The workspace creator id. + */ creatorId: string | null; + /** + * The workspace creation date. + */ dateCreated: string; + /** + * The workspace last updated date. + */ dateUpdated: string; + /** + * The number of invites in the workspace. + */ inviteCount: number; + /** + * The number of members in the workspace. + */ memberCount: number; + /** + * The workspace name. + */ name: string; + /** + * The end date of the current billing period. + */ periodEndDate: string | null; + /** + * The start date of the current billing period. + */ periodStartDate: string | null; + /** + * The number of projects in the workspace. + */ projectCount: number; + /** + * The workspace slug. + */ slug: string; status: @@ -274,6 +307,9 @@ export namespace InferencePipelineCreateResponse { monthlyUsage?: Array; + /** + * Whether the workspace only allows SAML authentication. + */ samlOnlyAccess?: boolean; wildcardDomains?: Array; @@ -498,26 +534,59 @@ export namespace InferencePipelineListResponse { } export interface Workspace { + /** + * The workspace id. + */ id: string; + /** + * The workspace creator id. + */ creatorId: string | null; + /** + * The workspace creation date. + */ dateCreated: string; + /** + * The workspace last updated date. + */ dateUpdated: string; + /** + * The number of invites in the workspace. + */ inviteCount: number; + /** + * The number of members in the workspace. + */ memberCount: number; + /** + * The workspace name. + */ name: string; + /** + * The end date of the current billing period. + */ periodEndDate: string | null; + /** + * The start date of the current billing period. + */ periodStartDate: string | null; + /** + * The number of projects in the workspace. + */ projectCount: number; + /** + * The workspace slug. + */ slug: string; status: @@ -532,6 +601,9 @@ export namespace InferencePipelineListResponse { monthlyUsage?: Array; + /** + * Whether the workspace only allows SAML authentication. + */ samlOnlyAccess?: boolean; wildcardDomains?: Array; @@ -584,12 +656,24 @@ export namespace InferencePipelineCreateParams { } export interface Workspace { + /** + * The workspace name. + */ name: string; + /** + * The workspace slug. + */ slug: string; + /** + * The workspace invite code. + */ inviteCode?: string; + /** + * Whether the workspace only allows SAML authentication. + */ samlOnlyAccess?: boolean; wildcardDomains?: Array; diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index dbf39e5..8591b63 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -19,12 +19,23 @@ import { InferencePipelineListResponse, InferencePipelines, } from './inference-pipelines'; +import * as TestsAPI from './tests'; +import { + TestCreateParams, + TestCreateResponse, + TestListParams, + TestListResponse, + TestUpdateParams, + TestUpdateResponse, + Tests, +} from './tests'; export class Projects extends APIResource { commits: CommitsAPI.Commits = new CommitsAPI.Commits(this._client); inferencePipelines: InferencePipelinesAPI.InferencePipelines = new InferencePipelinesAPI.InferencePipelines( this._client, ); + tests: TestsAPI.Tests = new TestsAPI.Tests(this._client); /** * Create a project in your workspace. @@ -324,6 +335,7 @@ export interface ProjectListParams { Projects.Commits = Commits; Projects.InferencePipelines = InferencePipelines; +Projects.Tests = Tests; export declare namespace Projects { export { @@ -348,4 +360,14 @@ export declare namespace Projects { type InferencePipelineCreateParams as InferencePipelineCreateParams, type InferencePipelineListParams as InferencePipelineListParams, }; + + export { + Tests as Tests, + type TestCreateResponse as TestCreateResponse, + type TestUpdateResponse as TestUpdateResponse, + type TestListResponse as TestListResponse, + type TestCreateParams as TestCreateParams, + type TestUpdateParams as TestUpdateParams, + type TestListParams as TestListParams, + }; } diff --git a/src/resources/projects/tests.ts b/src/resources/projects/tests.ts new file mode 100644 index 0000000..c2caa83 --- /dev/null +++ b/src/resources/projects/tests.ts @@ -0,0 +1,871 @@ +// 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'; + +export class Tests extends APIResource { + /** + * Create a test. + */ + create( + projectId: string, + body: TestCreateParams, + options?: Core.RequestOptions, + ): Core.APIPromise { + return this._client.post(`/projects/${projectId}/tests`, { body, ...options }); + } + + /** + * Update tests. + */ + update( + projectId: string, + body: TestUpdateParams, + options?: Core.RequestOptions, + ): Core.APIPromise { + return this._client.put(`/projects/${projectId}/tests`, { body, ...options }); + } + + /** + * List tests under a project. + */ + list( + projectId: string, + query?: TestListParams, + options?: Core.RequestOptions, + ): Core.APIPromise; + list(projectId: string, options?: Core.RequestOptions): Core.APIPromise; + list( + projectId: string, + query: TestListParams | Core.RequestOptions = {}, + options?: Core.RequestOptions, + ): Core.APIPromise { + if (isRequestOptions(query)) { + return this.list(projectId, {}, query); + } + return this._client.get(`/projects/${projectId}/tests`, { query, ...options }); + } +} + +export interface TestCreateResponse { + /** + * The test id. + */ + id: string; + + /** + * The number of comments on the test. + */ + commentCount: number; + + /** + * The test creator id. + */ + creatorId: string | null; + + /** + * The date the test was archived. + */ + dateArchived: string | null; + + /** + * The creation date. + */ + dateCreated: string; + + /** + * The last updated date. + */ + dateUpdated: string; + + /** + * The test description. + */ + description: unknown | null; + + /** + * The test name. + */ + name: string; + + /** + * The test number. + */ + number: number; + + /** + * The project version (commit) id where the test was created. + */ + originProjectVersionId: string | null; + + /** + * The test subtype. + */ + subtype: + | 'anomalousColumnCount' + | 'characterLength' + | 'classImbalanceRatio' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnStatistic' + | 'columnValuesMatch' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatureCount' + | 'customMetricThreshold' + | 'duplicateRowCount' + | 'emptyFeature' + | 'emptyFeatureCount' + | 'driftedFeatureCount' + | 'featureMissingValues' + | 'featureValueValidation' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricThresholdV2' + | 'labelDrift' + | 'metricThreshold' + | 'newCategoryCount' + | 'newLabelCount' + | 'nullRowCount' + | 'rowCount' + | 'ppScoreValueValidation' + | 'quasiConstantFeature' + | 'quasiConstantFeatureCount' + | 'sqlQuery' + | 'dtypeValidation' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharactersRatio' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + /** + * Whether the test is suggested or user-created. + */ + suggested: boolean; + + thresholds: Array; + + /** + * The test type. + */ + type: 'integrity' | 'consistency' | 'performance'; + + /** + * Whether the test is archived. + */ + archived?: boolean; + + /** + * The delay window in seconds. Only applies to tests that use production data. + */ + delayWindow?: number | null; + + /** + * The evaluation window in seconds. Only applies to tests that use production + * data. + */ + evaluationWindow?: number | null; + + /** + * Whether the test uses an ML model. + */ + usesMlModel?: boolean; + + /** + * Whether the test uses production data (monitoring mode only). + */ + usesProductionData?: boolean; + + /** + * Whether the test uses a reference dataset (monitoring mode only). + */ + usesReferenceDataset?: boolean; + + /** + * Whether the test uses a training dataset. + */ + usesTrainingDataset?: boolean; + + /** + * Whether the test uses a validation dataset. + */ + usesValidationDataset?: boolean; +} + +export namespace TestCreateResponse { + export interface Threshold { + /** + * The insight name to be evaluated. + */ + insightName?: + | 'characterLength' + | 'classImbalance' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnValuesMatch' + | 'confidenceDistribution' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatures' + | 'customMetric' + | 'duplicateRowCount' + | 'emptyFeatures' + | 'featureDrift' + | 'featureProfile' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricV2' + | 'labelDrift' + | 'metrics' + | 'newCategories' + | 'newLabels' + | 'nullRowCount' + | 'ppScore' + | 'quasiConstantFeatures' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharacters' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + /** + * The insight parameters. Required only for some test subtypes. For example, for + * tests that require a column name, the insight parameters will be [{'name': + * 'column_name', 'value': 'Age'}] + */ + insightParameters?: Array | null; + + /** + * The measurement to be evaluated. + */ + measurement?: string; + + /** + * The operator to be used for the evaluation. + */ + operator?: 'is' | '>' | '>=' | '<' | '<=' | '!='; + + /** + * Whether to use automatic anomaly detection or manual thresholds + */ + thresholdMode?: 'automatic' | 'manual'; + + /** + * The value to be compared. + */ + value?: number | boolean | string | Array; + } + + export namespace Threshold { + export interface InsightParameter { + /** + * The name of the insight filter. + */ + name: string; + + value: unknown; + } + } +} + +export interface TestUpdateResponse { + taskResultId?: string; + + taskResultUrl?: string; +} + +export interface TestListResponse { + items: Array; +} + +export namespace TestListResponse { + export interface Item { + /** + * The test id. + */ + id: string; + + /** + * The number of comments on the test. + */ + commentCount: number; + + /** + * The test creator id. + */ + creatorId: string | null; + + /** + * The date the test was archived. + */ + dateArchived: string | null; + + /** + * The creation date. + */ + dateCreated: string; + + /** + * The last updated date. + */ + dateUpdated: string; + + /** + * The test description. + */ + description: unknown | null; + + /** + * The test name. + */ + name: string; + + /** + * The test number. + */ + number: number; + + /** + * The project version (commit) id where the test was created. + */ + originProjectVersionId: string | null; + + /** + * The test subtype. + */ + subtype: + | 'anomalousColumnCount' + | 'characterLength' + | 'classImbalanceRatio' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnStatistic' + | 'columnValuesMatch' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatureCount' + | 'customMetricThreshold' + | 'duplicateRowCount' + | 'emptyFeature' + | 'emptyFeatureCount' + | 'driftedFeatureCount' + | 'featureMissingValues' + | 'featureValueValidation' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricThresholdV2' + | 'labelDrift' + | 'metricThreshold' + | 'newCategoryCount' + | 'newLabelCount' + | 'nullRowCount' + | 'rowCount' + | 'ppScoreValueValidation' + | 'quasiConstantFeature' + | 'quasiConstantFeatureCount' + | 'sqlQuery' + | 'dtypeValidation' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharactersRatio' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + /** + * Whether the test is suggested or user-created. + */ + suggested: boolean; + + thresholds: Array; + + /** + * The test type. + */ + type: 'integrity' | 'consistency' | 'performance'; + + /** + * Whether the test is archived. + */ + archived?: boolean; + + /** + * The delay window in seconds. Only applies to tests that use production data. + */ + delayWindow?: number | null; + + /** + * The evaluation window in seconds. Only applies to tests that use production + * data. + */ + evaluationWindow?: number | null; + + /** + * Whether the test uses an ML model. + */ + usesMlModel?: boolean; + + /** + * Whether the test uses production data (monitoring mode only). + */ + usesProductionData?: boolean; + + /** + * Whether the test uses a reference dataset (monitoring mode only). + */ + usesReferenceDataset?: boolean; + + /** + * Whether the test uses a training dataset. + */ + usesTrainingDataset?: boolean; + + /** + * Whether the test uses a validation dataset. + */ + usesValidationDataset?: boolean; + } + + export namespace Item { + export interface Threshold { + /** + * The insight name to be evaluated. + */ + insightName?: + | 'characterLength' + | 'classImbalance' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnValuesMatch' + | 'confidenceDistribution' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatures' + | 'customMetric' + | 'duplicateRowCount' + | 'emptyFeatures' + | 'featureDrift' + | 'featureProfile' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricV2' + | 'labelDrift' + | 'metrics' + | 'newCategories' + | 'newLabels' + | 'nullRowCount' + | 'ppScore' + | 'quasiConstantFeatures' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharacters' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + /** + * The insight parameters. Required only for some test subtypes. For example, for + * tests that require a column name, the insight parameters will be [{'name': + * 'column_name', 'value': 'Age'}] + */ + insightParameters?: Array | null; + + /** + * The measurement to be evaluated. + */ + measurement?: string; + + /** + * The operator to be used for the evaluation. + */ + operator?: 'is' | '>' | '>=' | '<' | '<=' | '!='; + + /** + * Whether to use automatic anomaly detection or manual thresholds + */ + thresholdMode?: 'automatic' | 'manual'; + + /** + * The value to be compared. + */ + value?: number | boolean | string | Array; + } + + export namespace Threshold { + export interface InsightParameter { + /** + * The name of the insight filter. + */ + name: string; + + value: unknown; + } + } + } +} + +export interface TestCreateParams { + /** + * The test description. + */ + description: unknown | null; + + /** + * The test name. + */ + name: string; + + /** + * The test subtype. + */ + subtype: + | 'anomalousColumnCount' + | 'characterLength' + | 'classImbalanceRatio' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnStatistic' + | 'columnValuesMatch' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatureCount' + | 'customMetricThreshold' + | 'duplicateRowCount' + | 'emptyFeature' + | 'emptyFeatureCount' + | 'driftedFeatureCount' + | 'featureMissingValues' + | 'featureValueValidation' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricThresholdV2' + | 'labelDrift' + | 'metricThreshold' + | 'newCategoryCount' + | 'newLabelCount' + | 'nullRowCount' + | 'rowCount' + | 'ppScoreValueValidation' + | 'quasiConstantFeature' + | 'quasiConstantFeatureCount' + | 'sqlQuery' + | 'dtypeValidation' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharactersRatio' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + thresholds: Array; + + /** + * The test type. + */ + type: 'integrity' | 'consistency' | 'performance'; + + /** + * Whether the test is archived. + */ + archived?: boolean; + + /** + * The delay window in seconds. Only applies to tests that use production data. + */ + delayWindow?: number | null; + + /** + * The evaluation window in seconds. Only applies to tests that use production + * data. + */ + evaluationWindow?: number | null; + + /** + * Whether the test uses an ML model. + */ + usesMlModel?: boolean; + + /** + * Whether the test uses production data (monitoring mode only). + */ + usesProductionData?: boolean; + + /** + * Whether the test uses a reference dataset (monitoring mode only). + */ + usesReferenceDataset?: boolean; + + /** + * Whether the test uses a training dataset. + */ + usesTrainingDataset?: boolean; + + /** + * Whether the test uses a validation dataset. + */ + usesValidationDataset?: boolean; +} + +export namespace TestCreateParams { + export interface Threshold { + /** + * The insight name to be evaluated. + */ + insightName?: + | 'characterLength' + | 'classImbalance' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnValuesMatch' + | 'confidenceDistribution' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatures' + | 'customMetric' + | 'duplicateRowCount' + | 'emptyFeatures' + | 'featureDrift' + | 'featureProfile' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricV2' + | 'labelDrift' + | 'metrics' + | 'newCategories' + | 'newLabels' + | 'nullRowCount' + | 'ppScore' + | 'quasiConstantFeatures' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharacters' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + /** + * The insight parameters. Required only for some test subtypes. For example, for + * tests that require a column name, the insight parameters will be [{'name': + * 'column_name', 'value': 'Age'}] + */ + insightParameters?: Array | null; + + /** + * The measurement to be evaluated. + */ + measurement?: string; + + /** + * The operator to be used for the evaluation. + */ + operator?: 'is' | '>' | '>=' | '<' | '<=' | '!='; + + /** + * Whether to use automatic anomaly detection or manual thresholds + */ + thresholdMode?: 'automatic' | 'manual'; + + /** + * The value to be compared. + */ + value?: number | boolean | string | Array; + } + + export namespace Threshold { + export interface InsightParameter { + /** + * The name of the insight filter. + */ + name: string; + + value: unknown; + } + } +} + +export interface TestUpdateParams { + payloads: Array; +} + +export namespace TestUpdateParams { + export interface Payload { + id: string; + + /** + * Whether the test is archived. + */ + archived?: boolean; + + /** + * The test description. + */ + description?: unknown | null; + + /** + * The test name. + */ + name?: string; + + suggested?: false; + + thresholds?: Array; + } + + export namespace Payload { + export interface Threshold { + /** + * The insight name to be evaluated. + */ + insightName?: + | 'characterLength' + | 'classImbalance' + | 'expectColumnAToBeInColumnB' + | 'columnAverage' + | 'columnDrift' + | 'columnValuesMatch' + | 'confidenceDistribution' + | 'conflictingLabelRowCount' + | 'containsPii' + | 'containsValidUrl' + | 'correlatedFeatures' + | 'customMetric' + | 'duplicateRowCount' + | 'emptyFeatures' + | 'featureDrift' + | 'featureProfile' + | 'greatExpectations' + | 'groupByColumnStatsCheck' + | 'illFormedRowCount' + | 'isCode' + | 'isJson' + | 'llmRubricV2' + | 'labelDrift' + | 'metrics' + | 'newCategories' + | 'newLabels' + | 'nullRowCount' + | 'ppScore' + | 'quasiConstantFeatures' + | 'sentenceLength' + | 'sizeRatio' + | 'specialCharacters' + | 'stringValidation' + | 'trainValLeakageRowCount'; + + /** + * The insight parameters. Required only for some test subtypes. For example, for + * tests that require a column name, the insight parameters will be [{'name': + * 'column_name', 'value': 'Age'}] + */ + insightParameters?: Array | null; + + /** + * The measurement to be evaluated. + */ + measurement?: string; + + /** + * The operator to be used for the evaluation. + */ + operator?: 'is' | '>' | '>=' | '<' | '<=' | '!='; + + /** + * Whether to use automatic anomaly detection or manual thresholds + */ + thresholdMode?: 'automatic' | 'manual'; + + /** + * The value to be compared. + */ + value?: number | boolean | string | Array; + } + + export namespace Threshold { + export interface InsightParameter { + /** + * The name of the insight filter. + */ + name: string; + + value: unknown; + } + } + } +} + +export interface TestListParams { + /** + * Filter for archived tests. + */ + includeArchived?: boolean; + + /** + * Retrive tests created by a specific project version. + */ + originVersionId?: string | null; + + /** + * The page to return in a paginated query. + */ + page?: number; + + /** + * Maximum number of items to return per page. + */ + perPage?: number; + + /** + * Filter for suggested tests. + */ + suggested?: boolean; + + /** + * Filter objects by test type. Available types are `integrity`, `consistency`, + * `performance`, `fairness`, and `robustness`. + */ + type?: 'integrity' | 'consistency' | 'performance' | 'fairness' | 'robustness'; + + /** + * Retrive tests with usesProductionData (monitoring). + */ + usesProductionData?: boolean | null; +} + +export declare namespace Tests { + export { + type TestCreateResponse as TestCreateResponse, + type TestUpdateResponse as TestUpdateResponse, + type TestListResponse as TestListResponse, + type TestCreateParams as TestCreateParams, + type TestUpdateParams as TestUpdateParams, + type TestListParams as TestListParams, + }; +} diff --git a/src/version.ts b/src/version.ts index ce6b899..9d013cc 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.12.0'; // x-release-please-version +export const VERSION = '0.13.0'; // x-release-please-version diff --git a/tests/api-resources/commits/test-results.test.ts b/tests/api-resources/commits/test-results.test.ts index 49a096a..9be61d7 100644 --- a/tests/api-resources/commits/test-results.test.ts +++ b/tests/api-resources/commits/test-results.test.ts @@ -34,7 +34,7 @@ describe('resource testResults', () => { await expect( client.commits.testResults.list( '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - { includeArchived: true, page: 1, perPage: 1, status: 'running', type: 'integrity' }, + { includeArchived: true, page: 1, perPage: 1, status: 'passing', type: 'integrity' }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Openlayer.NotFoundError); diff --git a/tests/api-resources/inference-pipelines/test-results.test.ts b/tests/api-resources/inference-pipelines/test-results.test.ts index 5b55a92..0bf1ad4 100644 --- a/tests/api-resources/inference-pipelines/test-results.test.ts +++ b/tests/api-resources/inference-pipelines/test-results.test.ts @@ -36,7 +36,7 @@ describe('resource testResults', () => { await expect( client.inferencePipelines.testResults.list( '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - { page: 1, perPage: 1, status: 'running', type: 'integrity' }, + { page: 1, perPage: 1, status: 'passing', type: 'integrity' }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(Openlayer.NotFoundError); diff --git a/tests/api-resources/projects/tests.test.ts b/tests/api-resources/projects/tests.test.ts new file mode 100644 index 0000000..9a6c452 --- /dev/null +++ b/tests/api-resources/projects/tests.test.ts @@ -0,0 +1,131 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Openlayer from 'openlayer'; +import { Response } from 'node-fetch'; + +const client = new Openlayer({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource tests', () => { + test('create: only required params', async () => { + const responsePromise = client.projects.tests.create('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + description: 'This test checks for duplicate rows in the dataset.', + name: 'No duplicate rows', + subtype: 'duplicateRowCount', + thresholds: [{}], + type: 'integrity', + }); + 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.projects.tests.create('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + description: 'This test checks for duplicate rows in the dataset.', + name: 'No duplicate rows', + subtype: 'duplicateRowCount', + thresholds: [ + { + insightName: 'duplicateRowCount', + insightParameters: [{ name: 'column_name', value: 'Age' }], + measurement: 'duplicateRowCount', + operator: '<=', + thresholdMode: 'automatic', + value: 0, + }, + ], + type: 'integrity', + archived: false, + delayWindow: 0, + evaluationWindow: 3600, + usesMlModel: false, + usesProductionData: false, + usesReferenceDataset: false, + usesTrainingDataset: false, + usesValidationDataset: true, + }); + }); + + test('update: only required params', async () => { + const responsePromise = client.projects.tests.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + payloads: [{ id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e' }], + }); + 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: required and optional params', async () => { + const response = await client.projects.tests.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + payloads: [ + { + id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + archived: false, + description: 'This test checks for duplicate rows in the dataset.', + name: 'No duplicate rows', + suggested: false, + thresholds: [ + { + insightName: 'duplicateRowCount', + insightParameters: [{ name: 'column_name', value: 'Age' }], + measurement: 'duplicateRowCount', + operator: '<=', + thresholdMode: 'automatic', + value: 0, + }, + ], + }, + ], + }); + }); + + test('list', async () => { + const responsePromise = client.projects.tests.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + 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.projects.tests.list('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + path: '/_stainless_unknown_path', + }), + ).rejects.toThrow(Openlayer.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.projects.tests.list( + '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + { + includeArchived: true, + originVersionId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', + page: 1, + perPage: 1, + suggested: true, + type: 'integrity', + usesProductionData: true, + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Openlayer.NotFoundError); + }); +}); diff --git a/tests/index.test.ts b/tests/index.test.ts index f45c1b0..86dc23a 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -96,6 +96,15 @@ describe('instantiate client', () => { expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true }); }); + test('explicit global fetch', async () => { + // make sure the global fetch type is assignable to our Fetch type + const client = new Openlayer({ + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: defaultFetch, + }); + }); + test('custom signal', async () => { const client = new Openlayer({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',