From c32e68ee007146374b83abb0901fde46731f0e3d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 13:55:34 +0000 Subject: [PATCH 01/12] chore(internal): more robust bootstrap script --- scripts/bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bootstrap b/scripts/bootstrap index a8b69ff..2e315f5 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response From e5b3c0095da82ac41791343a1ba5333ca011fb7f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:52:19 +0000 Subject: [PATCH 02/12] chore(formatter): run prettier and eslint separately --- eslint.config.mjs | 3 - package.json | 1 - scripts/fast-format | 6 +- scripts/format | 3 +- scripts/lint | 3 + src/api-promise.ts | 2 +- src/client.ts | 309 ++++------- src/core/api-promise.ts | 9 +- src/core/error.ts | 46 +- src/core/streaming.ts | 26 +- src/error.ts | 2 +- src/index.ts | 16 +- src/internal/builtin-types.ts | 23 +- src/internal/detect-platform.ts | 6 +- src/internal/errors.ts | 14 +- src/internal/headers.ts | 4 +- src/internal/parse.ts | 11 +- src/internal/request-options.ts | 7 +- src/internal/shim-types.ts | 4 +- src/internal/shims.ts | 4 +- src/internal/to-file.ts | 14 +- src/internal/types.ts | 50 +- src/internal/utils/log.ts | 37 +- src/internal/utils/uuid.ts | 8 +- src/resource.ts | 2 +- src/resources/async/async.ts | 4 +- src/resources/async/chat/chat.ts | 11 +- src/resources/async/chat/completions.ts | 42 +- src/resources/async/chat/index.ts | 11 +- src/resources/async/index.ts | 4 +- src/resources/browser/browser.ts | 5 +- src/resources/browser/index.ts | 4 +- src/resources/browser/sessions.ts | 17 +- src/resources/chat/chat.ts | 13 +- src/resources/chat/completions.ts | 35 +- src/resources/chat/index.ts | 9 +- src/resources/contextualized-embeddings.ts | 7 +- src/resources/embeddings.ts | 2 +- src/resources/index.ts | 36 +- src/resources/responses.ts | 279 +--------- src/resources/search.ts | 5 +- src/resources/shared.ts | 22 +- src/streaming.ts | 2 +- src/uploads.ts | 2 +- src/version.ts | 2 +- .../async/chat/completions.test.ts | 286 +++++----- tests/api-resources/browser/sessions.test.ts | 11 +- tests/api-resources/chat/completions.test.ts | 255 ++++----- .../contextualized-embeddings.test.ts | 20 +- tests/api-resources/embeddings.test.ts | 15 +- tests/api-resources/responses.test.ts | 87 ++- tests/api-resources/search.test.ts | 35 +- tests/buildHeaders.test.ts | 6 +- tests/index.test.ts | 498 +++++++++--------- tests/streaming.test.ts | 2 +- tests/stringifyQuery.test.ts | 42 +- yarn.lock | 32 -- 57 files changed, 897 insertions(+), 1514 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 230d8df..6642dab 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,6 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; -import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -14,11 +13,9 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, - prettier, }, rules: { 'no-unused-vars': 'off', - 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 17bd582..70a8daa 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", - "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/scripts/fast-format b/scripts/fast-format index 53721ac..e172313 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,10 +31,8 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -# format things eslint didn't -PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" +PRETTIER_FILES="$(grep '\.\([mc]?tsx?\|[mc]?jsx?\|json\)$' "$FILE_LIST" || true)" if ! [ -z "$PRETTIER_FILES" ]; then echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ - '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern fi diff --git a/scripts/format b/scripts/format index 7a75640..b1b2c17 100755 --- a/scripts/format +++ b/scripts/format @@ -8,5 +8,4 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -# format things eslint didn't -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . diff --git a/scripts/lint b/scripts/lint index 3ffb78a..1f53254 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,6 +4,9 @@ set -e cd "$(dirname "$0")/.." +echo "==> Running prettier --check" +./node_modules/.bin/prettier --check . + echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/src/api-promise.ts b/src/api-promise.ts index 8c775ee..4e70128 100644 --- a/src/api-promise.ts +++ b/src/api-promise.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/api-promise instead */ -export * from './core/api-promise'; +export * from "./core/api-promise" \ No newline at end of file diff --git a/src/client.ts b/src/client.ts index 20f90f3..9a9e4bf 100644 --- a/src/client.ts +++ b/src/client.ts @@ -17,29 +17,9 @@ import * as Errors from './core/error'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { - ContextualizedEmbeddingCreateParams, - ContextualizedEmbeddingCreateResponse, - ContextualizedEmbeddings, -} from './resources/contextualized-embeddings'; +import { ContextualizedEmbeddingCreateParams, ContextualizedEmbeddingCreateResponse, ContextualizedEmbeddings } from './resources/contextualized-embeddings'; import { EmbeddingCreateParams, EmbeddingCreateResponse, Embeddings } from './resources/embeddings'; -import { - Annotation, - ContentPart, - ErrorInfo, - FunctionCallOutputItem, - FunctionTool, - InputItem, - OutputItem, - ResponseCreateParams, - ResponseCreateParamsNonStreaming, - ResponseCreateParamsStreaming, - ResponseCreateResponse, - ResponseStreamChunk, - Responses, - ResponsesCreateParams, - ResponsesUsage, -} from './resources/responses'; +import { Annotation, ContentPart, ErrorInfo, FunctionCallOutputItem, FunctionTool, InputItem, OutputItem, ResponseCreateParams, ResponseCreateParamsNonStreaming, ResponseCreateParamsStreaming, ResponseCreateResponse, ResponseStreamChunk, Responses, ResponsesCreateParams, ResponsesUsage } from './resources/responses'; import { Search, SearchCreateParams, SearchCreateResponse } from './resources/search'; import { Async } from './resources/async/async'; import { Browser } from './resources/browser/browser'; @@ -48,13 +28,7 @@ import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { readEnv } from './internal/utils/env'; -import { - type LogLevel, - type Logger, - formatRequestDetails, - loggerFor, - parseLogLevel, -} from './internal/utils/log'; +import { type LogLevel, type Logger, formatRequestDetails, loggerFor, parseLogLevel } from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; export interface ClientOptions { @@ -133,7 +107,7 @@ export interface ClientOptions { } /** - * API Client for interfacing with the Perplexity API. + * API Client for interfacing with the Perplexity API. */ export class Perplexity { apiKey: string; @@ -169,7 +143,7 @@ export class Perplexity { }: ClientOptions = {}) { if (apiKey === undefined) { throw new Errors.PerplexityError( - "The PERPLEXITY_API_KEY environment variable is missing or empty; either provide it, or instantiate the Perplexity client with an apiKey option, like new Perplexity({ apiKey: 'My API Key' }).", + 'The PERPLEXITY_API_KEY environment variable is missing or empty; either provide it, or instantiate the Perplexity client with an apiKey option, like new Perplexity({ apiKey: \'My API Key\' }).' ); } @@ -185,10 +159,7 @@ export class Perplexity { const defaultLogLevel = 'warn'; // Set default logLevel early so that we can log a warning in parseLogLevel. this.logLevel = defaultLogLevel; - this.logLevel = - parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ?? - parseLogLevel(readEnv('PERPLEXITY_LOG'), "process.env['PERPLEXITY_LOG']", this) ?? - defaultLogLevel; + this.logLevel = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ?? parseLogLevel(readEnv('PERPLEXITY_LOG'), 'process.env[\'PERPLEXITY_LOG\']', this) ?? defaultLogLevel; this.fetchOptions = options.fetchOptions; this.maxRetries = options.maxRetries ?? 2; this.fetch = options.fetch ?? Shims.getDefaultFetch(); @@ -213,7 +184,7 @@ export class Perplexity { fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, - ...options, + ...options }); return client; } @@ -226,7 +197,7 @@ export class Perplexity { } protected defaultQuery(): Record | undefined { - return this._options.defaultQuery; + return this._options.defaultQuery } protected validateHeaders({ values, nulls }: NullableHeaders) { @@ -261,11 +232,7 @@ export class Perplexity { return Errors.APIError.generate(status, error, message, headers); } - buildURL( - path: string, - query: Record | null | undefined, - defaultBaseURL?: string | undefined, - ): string { + buildURL(path: string, query: Record | null | undefined, defaultBaseURL?: string | undefined): string { const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL; const url = isAbsoluteURL(path) ? @@ -353,9 +320,7 @@ export class Perplexity { await this.prepareOptions(options); - const { req, url, timeout } = await this.buildRequest(options, { - retryCount: maxRetries - retriesRemaining, - }); + const { req, url, timeout } = await this.buildRequest(options, { retryCount: maxRetries - retriesRemaining }); await this.prepareRequest(req, { url, options }); @@ -364,16 +329,7 @@ export class Perplexity { const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; const startTime = Date.now(); - loggerFor(this).debug( - `[${requestLogID}] sending request`, - formatRequestDetails({ - retryOfRequestLogID, - method: options.method, - url, - options, - headers: req.headers, - }), - ); + loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ retryOfRequestLogID, method: options.method, url, options, headers: req.headers })); if (options.signal?.aborted) { throw new Errors.APIUserAbortError(); @@ -392,45 +348,21 @@ export class Perplexity { // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" // others do not provide enough information to distinguish timeouts from other connection errors - const isTimeout = - isAbortError(response) || - /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); + const isTimeout = isAbortError(response) || /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')) if (retriesRemaining) { - loggerFor(this).info( - `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`, - ); - loggerFor(this).debug( - `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, - formatRequestDetails({ - retryOfRequestLogID, - url, - durationMs: headersTime - startTime, - message: response.message, - }), - ); + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`) + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ retryOfRequestLogID, url, durationMs: headersTime - startTime, message: response.message })); return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID); } - loggerFor(this).info( - `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`, - ); - loggerFor(this).debug( - `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, - formatRequestDetails({ - retryOfRequestLogID, - url, - durationMs: headersTime - startTime, - message: response.message, - }), - ); + loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`) + loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ retryOfRequestLogID, url, durationMs: headersTime - startTime, message: response.message })); if (isTimeout) { throw new Errors.APIConnectionTimeoutError(); } throw new Errors.APIConnectionError({ cause: response }); } - const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${ - response.ok ? 'succeeded' : 'failed' - } with status ${response.status} in ${headersTime - startTime}ms`; + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; if (!response.ok) { const shouldRetry = await this.shouldRetry(response); @@ -439,60 +371,27 @@ export class Perplexity { // We don't need the body of this response. await Shims.CancelReadableStream(response.body); - loggerFor(this).info(`${responseInfo} - ${retryMessage}`); - loggerFor(this).debug( - `[${requestLogID}] response error (${retryMessage})`, - formatRequestDetails({ - retryOfRequestLogID, - url: response.url, - status: response.status, - headers: response.headers, - durationMs: headersTime - startTime, - }), - ); - return this.retryRequest( - options, - retriesRemaining, - retryOfRequestLogID ?? requestLogID, - response.headers, - ); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`) + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, headers: response.headers, durationMs: headersTime - startTime })); + return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers); } const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; - loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`) const errText = await response.text().catch((err: any) => castToError(err).message); const errJSON = safeJSON(errText) as any; const errMessage = errJSON ? undefined : errText; - loggerFor(this).debug( - `[${requestLogID}] response error (${retryMessage})`, - formatRequestDetails({ - retryOfRequestLogID, - url: response.url, - status: response.status, - headers: response.headers, - message: errMessage, - durationMs: Date.now() - startTime, - }), - ); + loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, headers: response.headers, message: errMessage, durationMs: Date.now() - startTime })); const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); throw err; } - loggerFor(this).info(responseInfo); - loggerFor(this).debug( - `[${requestLogID}] response start`, - formatRequestDetails({ - retryOfRequestLogID, - url: response.url, - status: response.status, - headers: response.headers, - durationMs: headersTime - startTime, - }), - ); + loggerFor(this).info(responseInfo) + loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, headers: response.headers, durationMs: headersTime - startTime })); return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; } @@ -509,9 +408,7 @@ export class Perplexity { const timeout = setTimeout(abort, ms); - const isReadableBody = - ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || - (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); + const isReadableBody = ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || (typeof options.body === "object" && options.body !== null && Symbol.asyncIterator in options.body); const fetchOptions: RequestInit = { signal: controller.signal as any, @@ -526,6 +423,7 @@ export class Perplexity { } try { + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare return await this.fetch.call(undefined, url, fetchOptions); } finally { @@ -626,12 +524,11 @@ export class Perplexity { const req: FinalizedRequestInit = { method, headers: reqHeaders, - ...(options.signal && { signal: options.signal }), - ...((globalThis as any).ReadableStream && - body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }), + ...(options.signal && { signal: options.signal}), + ...((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream && { duplex: "half" }), ...(body && { body }), - ...((this.fetchOptions as any) ?? {}), - ...((options.fetchOptions as any) ?? {}), + ...(this.fetchOptions as any ?? {}), + ...(options.fetchOptions as any ?? {}), }; return { req, url, timeout: options.timeout }; @@ -656,19 +553,18 @@ export class Perplexity { const headers = buildHeaders([ idempotencyHeaders, - { - Accept: 'application/json', - 'User-Agent': this.getUserAgent(), - 'X-Stainless-Retry-Count': String(retryCount), - ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), - ...getPlatformHeaders(), + {Accept: 'application/json', + 'User-Agent': this.getUserAgent(), + 'X-Stainless-Retry-Count': String(retryCount), + ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), + ...getPlatformHeaders(), 'X-Source': 'perplexity-node', 'X-Title': 'Perplexity Node SDK', }, await this.authHeaders(options), this._options.defaultHeaders, bodyHeaders, - options.headers, + options.headers ]); this.validateHeaders(headers); @@ -695,9 +591,11 @@ export class Perplexity { ArrayBuffer.isView(body) || body instanceof ArrayBuffer || body instanceof DataView || - (typeof body === 'string' && + ( + typeof body === 'string' && // Preserve legacy string encoding behavior for now - headers.values.has('content-type')) || + headers.values.has('content-type') + ) || // `Blob` is superset of `File` ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) || // `FormData` -> `multipart/form-data` @@ -728,7 +626,7 @@ export class Perplexity { } static Perplexity = this; - static DEFAULT_TIMEOUT = 900000; // 15 minutes + static DEFAULT_TIMEOUT = 900000 // 15 minutes static PerplexityError = Errors.PerplexityError; static APIError = Errors.APIError; @@ -764,62 +662,69 @@ Perplexity.Browser = Browser; Perplexity.Async = Async; export declare namespace Perplexity { - export type RequestOptions = Opts.RequestOptions; - - export { Chat as Chat, type StreamChunk as StreamChunk }; - - export { - Search as Search, - type SearchCreateResponse as SearchCreateResponse, - type SearchCreateParams as SearchCreateParams, - }; - - export { - Responses as Responses, - type Annotation as Annotation, - type ContentPart as ContentPart, - type ErrorInfo as ErrorInfo, - type FunctionCallOutputItem as FunctionCallOutputItem, - type FunctionTool as FunctionTool, - type InputItem as InputItem, - type OutputItem as OutputItem, - type ResponseStreamChunk as ResponseStreamChunk, - type ResponsesCreateParams as ResponsesCreateParams, - type ResponsesUsage as ResponsesUsage, - type ResponseCreateResponse as ResponseCreateResponse, - type ResponseCreateParams as ResponseCreateParams, - type ResponseCreateParamsNonStreaming as ResponseCreateParamsNonStreaming, - type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming, - }; - - export { - Embeddings as Embeddings, - type EmbeddingCreateResponse as EmbeddingCreateResponse, - type EmbeddingCreateParams as EmbeddingCreateParams, - }; - - export { - ContextualizedEmbeddings as ContextualizedEmbeddings, - type ContextualizedEmbeddingCreateResponse as ContextualizedEmbeddingCreateResponse, - type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams, - }; - - export { Browser as Browser }; - - export { Async as Async }; - - export type APIPublicSearchResult = API.APIPublicSearchResult; - export type BrowserSessionResponse = API.BrowserSessionResponse; - export type ChatMessageInput = API.ChatMessageInput; - export type ChatMessageOutput = API.ChatMessageOutput; - export type Choice = API.Choice; - export type ContextualizedEmbeddingObject = API.ContextualizedEmbeddingObject; - export type EmbeddingObject = API.EmbeddingObject; - export type EmbeddingsUsage = API.EmbeddingsUsage; - export type JsonSchemaFormat = API.JsonSchemaFormat; - export type ResponseFormat = API.ResponseFormat; - export type SearchResult = API.SearchResult; - export type UsageInfo = API.UsageInfo; - export type UserLocation = API.UserLocation; - export type WebSearchOptions = API.WebSearchOptions; -} + export type RequestOptions = Opts.RequestOptions; + + export { + Chat as Chat, + type StreamChunk as StreamChunk +}; + +export { + Search as Search, + type SearchCreateResponse as SearchCreateResponse, + type SearchCreateParams as SearchCreateParams +}; + +export { + Responses as Responses, + type Annotation as Annotation, + type ContentPart as ContentPart, + type ErrorInfo as ErrorInfo, + type FunctionCallOutputItem as FunctionCallOutputItem, + type FunctionTool as FunctionTool, + type InputItem as InputItem, + type OutputItem as OutputItem, + type ResponseStreamChunk as ResponseStreamChunk, + type ResponsesCreateParams as ResponsesCreateParams, + type ResponsesUsage as ResponsesUsage, + type ResponseCreateResponse as ResponseCreateResponse, + type ResponseCreateParams as ResponseCreateParams, + type ResponseCreateParamsNonStreaming as ResponseCreateParamsNonStreaming, + type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming +}; + +export { + Embeddings as Embeddings, + type EmbeddingCreateResponse as EmbeddingCreateResponse, + type EmbeddingCreateParams as EmbeddingCreateParams +}; + +export { + ContextualizedEmbeddings as ContextualizedEmbeddings, + type ContextualizedEmbeddingCreateResponse as ContextualizedEmbeddingCreateResponse, + type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams +}; + +export { + Browser as Browser +}; + +export { + Async as Async +}; + +export type APIPublicSearchResult = API.APIPublicSearchResult; +export type BrowserSessionResponse = API.BrowserSessionResponse; +export type ChatMessageInput = API.ChatMessageInput; +export type ChatMessageOutput = API.ChatMessageOutput; +export type Choice = API.Choice; +export type ContextualizedEmbeddingObject = API.ContextualizedEmbeddingObject; +export type EmbeddingObject = API.EmbeddingObject; +export type EmbeddingsUsage = API.EmbeddingsUsage; +export type JsonSchemaFormat = API.JsonSchemaFormat; +export type ResponseFormat = API.ResponseFormat; +export type SearchResult = API.SearchResult; +export type UsageInfo = API.UsageInfo; +export type UserLocation = API.UserLocation; +export type WebSearchOptions = API.WebSearchOptions; + } diff --git a/src/core/api-promise.ts b/src/core/api-promise.ts index 83c9de6..3cd5415 100644 --- a/src/core/api-promise.ts +++ b/src/core/api-promise.ts @@ -16,10 +16,7 @@ export class APIPromise extends Promise { constructor( client: Perplexity, private responsePromise: Promise, - private parseResponse: ( - client: Perplexity, - props: APIResponseProps, - ) => PromiseOrValue = defaultParseResponse, + private parseResponse: (client: Perplexity, props: APIResponseProps) => PromiseOrValue = defaultParseResponse, ) { super((resolve) => { // this is maybe a bit weird but this has to be a no-op to not implicitly @@ -31,9 +28,7 @@ export class APIPromise extends Promise { } _thenUnwrap(transform: (data: T, props: APIResponseProps) => U): APIPromise { - return new APIPromise(this.#client, this.responsePromise, async (client, props) => - transform(await this.parseResponse(client, props), props), - ); + return new APIPromise(this.#client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); } /** diff --git a/src/core/error.ts b/src/core/error.ts index 8932028..218a66d 100644 --- a/src/core/error.ts +++ b/src/core/error.ts @@ -2,13 +2,10 @@ import { castToError } from '../internal/errors'; -export class PerplexityError extends Error {} +export class PerplexityError extends Error { +} -export class APIError< - TStatus extends number | undefined = number | undefined, - THeaders extends Headers | undefined = Headers | undefined, - TError extends Object | undefined = Object | undefined, -> extends PerplexityError { +export class APIError extends PerplexityError { /** HTTP status for the response that caused the error */ readonly status: TStatus; /** HTTP headers for the response that caused the error */ @@ -16,6 +13,9 @@ export class APIError< /** JSON body of the response that caused the error */ readonly error: TError; + + ; + constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) { super(`${APIError.makeMessage(status, error, message)}`); this.status = status; @@ -26,8 +26,7 @@ export class APIError< private static makeMessage(status: number | undefined, error: any, message: string | undefined) { const msg = error?.message ? - typeof error.message === 'string' ? - error.message + typeof error.message === 'string' ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : message; @@ -44,12 +43,7 @@ export class APIError< return '(no status code or body)'; } - static generate( - status: number | undefined, - errorResponse: Object | undefined, - message: string | undefined, - headers: Headers | undefined, - ): APIError { + static generate(status: number | undefined, errorResponse: Object | undefined, message: string | undefined, headers: Headers | undefined): APIError { if (!status || !headers) { return new APIConnectionError({ message, cause: castToError(errorResponse) }); } @@ -113,18 +107,26 @@ export class APIConnectionTimeoutError extends APIConnectionError { } } -export class BadRequestError extends APIError<400, Headers> {} +export class BadRequestError extends APIError<400, Headers> { +} -export class AuthenticationError extends APIError<401, Headers> {} +export class AuthenticationError extends APIError<401, Headers> { +} -export class PermissionDeniedError extends APIError<403, Headers> {} +export class PermissionDeniedError extends APIError<403, Headers> { +} -export class NotFoundError extends APIError<404, Headers> {} +export class NotFoundError extends APIError<404, Headers> { +} -export class ConflictError extends APIError<409, Headers> {} +export class ConflictError extends APIError<409, Headers> { +} -export class UnprocessableEntityError extends APIError<422, Headers> {} +export class UnprocessableEntityError extends APIError<422, Headers> { +} -export class RateLimitError extends APIError<429, Headers> {} +export class RateLimitError extends APIError<429, Headers> { +} -export class InternalServerError extends APIError {} +export class InternalServerError extends APIError { +} diff --git a/src/core/streaming.ts b/src/core/streaming.ts index c7092c0..3f335ee 100644 --- a/src/core/streaming.ts +++ b/src/core/streaming.ts @@ -9,7 +9,7 @@ import { encodeUTF8 } from '../internal/utils/bytes'; import { loggerFor } from '../internal/utils/log'; import type { Perplexity } from '../client'; -import { APIError } from './error'; +import { APIError } from './error';; type Bytes = string | ArrayBuffer | Uint8Array | null | undefined; @@ -32,33 +32,33 @@ export class Stream implements AsyncIterable { this.#client = client; } - static fromSSEResponse( - response: Response, - controller: AbortController, - client?: Perplexity, - ): Stream { + static fromSSEResponse(response: Response, +controller: AbortController, +client?: Perplexity,): Stream { let consumed = false; const logger = client ? loggerFor(client) : console; async function* iterator(): AsyncIterator { if (consumed) { - throw new PerplexityError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + throw new PerplexityError( + 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.', + ); } consumed = true; let done = false; try { for await (const sse of _iterSSEMessages(response, controller)) { if (done) continue; - + if (sse.data.startsWith('[DONE]')) { done = true; continue; } - + if (sse.event === 'error') { throw new APIError(undefined, safeJSON(sse.data) ?? sse.data, undefined, response.headers); } - + if (sse.event === null) { try { yield JSON.parse(sse.data) as Item; @@ -67,7 +67,7 @@ export class Stream implements AsyncIterable { logger.error(`From chunk:`, sse.raw); throw e; } - } + }; } done = true; } catch (e) { @@ -111,7 +111,9 @@ export class Stream implements AsyncIterable { async function* iterator(): AsyncIterator { if (consumed) { - throw new PerplexityError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + throw new PerplexityError( + 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.', + ); } consumed = true; let done = false; diff --git a/src/error.ts b/src/error.ts index fc55f46..d0832d3 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/error instead */ -export * from './core/error'; +export * from "./core/error" \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index edad4bf..c397ccc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,18 +5,4 @@ export { Perplexity as default } from './client'; export { type Uploadable, toFile } from './core/uploads'; export { APIPromise } from './core/api-promise'; export { Perplexity, type ClientOptions } from './client'; -export { - PerplexityError, - APIError, - APIConnectionError, - APIConnectionTimeoutError, - APIUserAbortError, - NotFoundError, - ConflictError, - RateLimitError, - BadRequestError, - AuthenticationError, - InternalServerError, - PermissionDeniedError, - UnprocessableEntityError, -} from './core/error'; +export { PerplexityError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError } from './core/error'; diff --git a/src/internal/builtin-types.ts b/src/internal/builtin-types.ts index c23d3bd..6059d5d 100644 --- a/src/internal/builtin-types.ts +++ b/src/internal/builtin-types.ts @@ -1,20 +1,23 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise; +export type Fetch = ( + input: string | URL | Request, + init?: RequestInit, +) => Promise /** * An alias to the builtin `RequestInit` type so we can * easily alias it in import statements if there are name clashes. - * - * https://developer.mozilla.org/docs/Web/API/RequestInit + * + * https://developer.mozilla.org/docs/Web/API/RequestInit */ type _RequestInit = RequestInit; /** * An alias to the builtin `Response` type so we can * easily alias it in import statements if there are name clashes. - * - * https://developer.mozilla.org/docs/Web/API/Response + * + * https://developer.mozilla.org/docs/Web/API/Response */ type _Response = Response; @@ -51,15 +54,7 @@ type _Array = Array; */ type _Record = Record; -export type { - _Array as Array, - _BodyInit as BodyInit, - _HeadersInit as HeadersInit, - _Record as Record, - _RequestInfo as RequestInfo, - _RequestInit as RequestInit, - _Response as Response, -}; +export type { _Array as Array, _BodyInit as BodyInit, _HeadersInit as HeadersInit, _Record as Record, _RequestInfo as RequestInfo, _RequestInit as RequestInit, _Response as Response }; /** * A copy of the builtin `EndingType` type as it isn't fully supported in certain diff --git a/src/internal/detect-platform.ts b/src/internal/detect-platform.ts index e82d95c..394ede8 100644 --- a/src/internal/detect-platform.ts +++ b/src/internal/detect-platform.ts @@ -25,11 +25,7 @@ function getDetectedPlatform(): DetectedPlatform { if (typeof EdgeRuntime !== 'undefined') { return 'edge'; } - if ( - Object.prototype.toString.call( - typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0, - ) === '[object process]' - ) { + if (Object.prototype.toString.call(typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0) === '[object process]') { return 'node'; } return 'unknown'; diff --git a/src/internal/errors.ts b/src/internal/errors.ts index 82c7b14..c14a742 100644 --- a/src/internal/errors.ts +++ b/src/internal/errors.ts @@ -2,12 +2,12 @@ export function isAbortError(err: unknown) { return ( - typeof err === 'object' && - err !== null && - // Spec-compliant fetch implementations - (('name' in err && (err as any).name === 'AbortError') || + typeof err === 'object' && err !== null && ( + // Spec-compliant fetch implementations + ('name' in err && (err as any).name === 'AbortError') || // Expo fetch - ('message' in err && String((err as any).message).includes('FetchRequestCanceledException'))) + ('message' in err && String((err as any).message).includes('FetchRequestCanceledException')) + ) ); } @@ -24,10 +24,10 @@ export const castToError = (err: any): Error => { if (err.name) error.name = err.name; return error; } - } catch {} + } catch { } try { return new Error(JSON.stringify(err)); - } catch {} + } catch { } } return new Error(err); }; diff --git a/src/internal/headers.ts b/src/internal/headers.ts index c724a9d..fa2ea2b 100644 --- a/src/internal/headers.ts +++ b/src/internal/headers.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { isReadonlyArray } from './utils/values'; +import { isReadonlyArray } from "./utils/values"; type HeaderValue = string | undefined | null; export type HeadersLike = @@ -51,7 +51,7 @@ function* iterateHeaders(headers: HeadersLike): IterableIterator(client: Perplexity, props: APIResp const text = await response.text(); return text as unknown as T; })(); - loggerFor(client).debug( - `[${requestLogID}] response parsed`, - formatRequestDetails({ - retryOfRequestLogID, - url: response.url, - status: response.status, - body, - durationMs: Date.now() - startTime, - }), - ); + loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, body, durationMs: Date.now() - startTime })); return body; } diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts index 56765e5..0a02e61 100644 --- a/src/internal/request-options.ts +++ b/src/internal/request-options.ts @@ -77,11 +77,14 @@ export type RequestOptions = { defaultBaseURL?: string | undefined; __binaryResponse?: boolean | undefined; - __streamClass?: typeof Stream; + __streamClass?: typeof Stream }; export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit }; -export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent; +export type RequestEncoder = (request: { + headers: NullableHeaders; + body: unknown; +}) => EncodedContent; export const FallbackEncoder: RequestEncoder = ({ headers, body }) => { return { diff --git a/src/internal/shim-types.ts b/src/internal/shim-types.ts index 8ddf7b0..accbf57 100644 --- a/src/internal/shim-types.ts +++ b/src/internal/shim-types.ts @@ -19,8 +19,8 @@ type _ConditionalNodeReadableStream = typeof globalThis extends { ReadableStream: any } ? never : _NodeReadableStream; type _ReadableStream = NeverToAny< - | ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) - | ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) + ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) | + ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) >; export type { _ReadableStream as ReadableStream }; diff --git a/src/internal/shims.ts b/src/internal/shims.ts index ba237db..94c7086 100644 --- a/src/internal/shims.ts +++ b/src/internal/shims.ts @@ -27,9 +27,7 @@ export function makeReadableStream(...args: ReadableStreamArgs): ReadableStream if (typeof ReadableStream === 'undefined') { // Note: All of the platforms / runtimes we officially support already define // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. - throw new Error( - '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`', - ); + throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); } return new ReadableStream(...args); diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts index 30eada3..c72a2b4 100644 --- a/src/internal/to-file.ts +++ b/src/internal/to-file.ts @@ -1,4 +1,4 @@ -import { BlobPart, getName, makeFile, isAsyncIterable } from './uploads'; +import { BlobPart, getName, makeFile, isAsyncIterable } from "./uploads"; import type { FilePropertyBag } from './builtin-types'; import { checkFileSupport } from './uploads'; @@ -65,11 +65,8 @@ const isResponseLike = (value: any): value is ResponseLike => typeof value.url === 'string' && typeof value.blob === 'function'; -export type ToFileInput = - | FileLike - | ResponseLike - | Exclude - | AsyncIterable; +export type ToFileInput = FileLike | ResponseLike | Exclude | AsyncIterable; + /** * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats @@ -119,7 +116,9 @@ export async function toFile( return makeFile(parts, name, options); } -async function getBytes(value: BlobLikePart | AsyncIterable): Promise> { +async function getBytes( + value: BlobLikePart | AsyncIterable, +): Promise> { let parts: Array = []; if ( typeof value === 'string' || @@ -152,3 +151,4 @@ function propsForError(value: unknown): string { const props = Object.getOwnPropertyNames(value); return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; } + diff --git a/src/internal/types.ts b/src/internal/types.ts index b668dfc..c45fee3 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -7,40 +7,34 @@ export type KeysEnum = { [P in keyof Required]: true }; export type FinalizedRequestInit = RequestInit & { headers: Headers }; -type NotAny = [0] extends [1 & T] ? never : T; +type NotAny = [0] extends [(1 & T)] ? never : T; /** * Some environments overload the global fetch function, and Parameters only gets the last signature. */ -type OverloadedParameters = - T extends ( - { +type OverloadedParameters = T extends { + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + (...args: infer D): unknown; +} + ? A | B | C | D + : T extends { (...args: infer A): unknown; (...args: infer B): unknown; (...args: infer C): unknown; - (...args: infer D): unknown; } - ) ? - A | B | C | D - : T extends ( - { - (...args: infer A): unknown; - (...args: infer B): unknown; - (...args: infer C): unknown; - } - ) ? - A | B | C - : T extends ( - { + ? A | B | C + : T extends { (...args: infer A): unknown; (...args: infer B): unknown; } - ) ? - A | B - : T extends (...args: infer A) => unknown ? A + ? A | B + : T extends (...args: infer A) => unknown + ? A : never; -/* eslint-disable */ + /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -63,19 +57,19 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ +/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ +/** @ts-ignore For users with undici */ /* prettier-ignore */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ +/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ +/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ +/** @ts-ignore For users who use Deno */ /* prettier-ignore */ type FetchRequestInit = NonNullable[1]>; -/* eslint-enable */ + type RequestInits = | NotAny diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index c8062b7..4739f95 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -4,7 +4,7 @@ import { hasOwn } from './values'; import { type Perplexity } from '../../client'; import { RequestOptions } from '../request-options'; -type LogFn = (message: string, ...rest: unknown[]) => void; +type LogFn = (message: string, ...rest: unknown[]) => void export type Logger = { error: LogFn; warn: LogFn; @@ -21,22 +21,14 @@ const levelNumbers = { debug: 500, }; -export const parseLogLevel = ( - maybeLevel: string | undefined, - sourceName: string, - client: Perplexity, -): LogLevel | undefined => { +export const parseLogLevel = (maybeLevel: string | undefined, sourceName: string, client: Perplexity): LogLevel | undefined => { if (!maybeLevel) { return undefined; } if (hasOwn(levelNumbers, maybeLevel)) { return maybeLevel; - } - loggerFor(client).warn( - `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify( - Object.keys(levelNumbers), - )}`, - ); + }; + loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); return undefined; }; @@ -97,24 +89,11 @@ export const formatRequestDetails = (details: { body?: unknown; }) => { if (details.options) { - details.options = { ...details.options }; + details.options = {...details.options}; delete details.options['headers']; // redundant + leaks internals } if (details.headers) { - details.headers = Object.fromEntries( - (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map( - ([name, value]) => [ - name, - ( - name.toLowerCase() === 'authorization' || - name.toLowerCase() === 'cookie' || - name.toLowerCase() === 'set-cookie' - ) ? - '***' - : value, - ], - ), - ); + details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [name, name.toLowerCase() === 'authorization' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ? '***' : value])) } if ('retryOfRequestLogID' in details) { if (details.retryOfRequestLogID) { @@ -122,5 +101,5 @@ export const formatRequestDetails = (details: { } delete details.retryOfRequestLogID; } - return details; -}; + return details +} diff --git a/src/internal/utils/uuid.ts b/src/internal/utils/uuid.ts index b0e53aa..53708ba 100644 --- a/src/internal/utils/uuid.ts +++ b/src/internal/utils/uuid.ts @@ -10,8 +10,10 @@ export let uuid4 = function () { return crypto.randomUUID(); } const u8 = new Uint8Array(1); - const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff; - return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => + const randomByte = crypto + ? () => crypto.getRandomValues(u8)[0]! + : () => (Math.random() * 0xff) & 0xff; + return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16), ); -}; +} diff --git a/src/resource.ts b/src/resource.ts index 363e351..57a27a9 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/resource instead */ -export * from './core/resource'; +export * from "./core/resource" \ No newline at end of file diff --git a/src/resources/async/async.ts b/src/resources/async/async.ts index 00208d2..d2c011c 100644 --- a/src/resources/async/async.ts +++ b/src/resources/async/async.ts @@ -11,5 +11,7 @@ export class Async extends APIResource { Async.Chat = Chat; export declare namespace Async { - export { Chat as Chat }; + export { + Chat as Chat + }; } diff --git a/src/resources/async/chat/chat.ts b/src/resources/async/chat/chat.ts index f593341..9da82d5 100644 --- a/src/resources/async/chat/chat.ts +++ b/src/resources/async/chat/chat.ts @@ -2,14 +2,7 @@ import { APIResource } from '../../../core/resource'; import * as CompletionsAPI from './completions'; -import { - CompletionCreateParams, - CompletionCreateResponse, - CompletionGetParams, - CompletionGetResponse, - CompletionListResponse, - Completions, -} from './completions'; +import { CompletionCreateParams, CompletionCreateResponse, CompletionGetParams, CompletionGetResponse, CompletionListResponse, Completions } from './completions'; export class Chat extends APIResource { completions: CompletionsAPI.Completions = new CompletionsAPI.Completions(this._client); @@ -24,6 +17,6 @@ export declare namespace Chat { type CompletionListResponse as CompletionListResponse, type CompletionGetResponse as CompletionGetResponse, type CompletionCreateParams as CompletionCreateParams, - type CompletionGetParams as CompletionGetParams, + type CompletionGetParams as CompletionGetParams }; } diff --git a/src/resources/async/chat/completions.ts b/src/resources/async/chat/completions.ts index 787240a..5b4fbd5 100644 --- a/src/resources/async/chat/completions.ts +++ b/src/resources/async/chat/completions.ts @@ -26,37 +26,9 @@ export class Completions extends APIResource { /** * Retrieve the response for a given asynchronous chat completion request. */ - get( - apiRequest: string, - params: CompletionGetParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - const { - 'x-client-env': xClientEnv, - 'x-client-name': xClientName, - 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds, - 'x-request-time': xRequestTime, - 'x-usage-tier': xUsageTier, - 'x-user-id': xUserID, - ...query - } = params ?? {}; - return this._client.get(path`/async/chat/completions/${apiRequest}`, { - query, - ...options, - headers: buildHeaders([ - { - ...(xClientEnv != null ? { 'x-client-env': xClientEnv } : undefined), - ...(xClientName != null ? { 'x-client-name': xClientName } : undefined), - ...(xCreatedAtEpochSeconds != null ? - { 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds } - : undefined), - ...(xRequestTime != null ? { 'x-request-time': xRequestTime } : undefined), - ...(xUsageTier != null ? { 'x-usage-tier': xUsageTier } : undefined), - ...(xUserID != null ? { 'x-user-id': xUserID } : undefined), - }, - options?.headers, - ]), - }); + get(apiRequest: string, params: CompletionGetParams | null | undefined = {}, options?: RequestOptions): APIPromise { + const { 'x-client-env': xClientEnv, 'x-client-name': xClientName, 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds, 'x-request-time': xRequestTime, 'x-usage-tier': xUsageTier, 'x-user-id': xUserID, ...query } = params ?? {} + return this._client.get(path`/async/chat/completions/${apiRequest}`, { query, ...options, headers: buildHeaders([{...(xClientEnv != null ? { 'x-client-env': xClientEnv } : undefined), ...(xClientName != null ? { 'x-client-name': xClientName } : undefined), ...(xCreatedAtEpochSeconds != null ? { 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds } : undefined), ...(xRequestTime != null ? { 'x-request-time': xRequestTime } : undefined), ...(xUsageTier != null ? { 'x-usage-tier': xUsageTier } : undefined), ...(xUserID != null ? { 'x-user-id': xUserID } : undefined)}, options?.headers]) }); } } @@ -203,11 +175,7 @@ export namespace CompletionCreateParams { reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high' | null; - response_format?: - | Request.ResponseFormatText - | Request.ResponseFormatJsonSchema - | Request.ResponseFormatRegex - | null; + response_format?: Request.ResponseFormatText | Request.ResponseFormatJsonSchema | Request.ResponseFormatRegex | null; response_metadata?: { [key: string]: unknown } | null; @@ -380,6 +348,6 @@ export declare namespace Completions { type CompletionListResponse as CompletionListResponse, type CompletionGetResponse as CompletionGetResponse, type CompletionCreateParams as CompletionCreateParams, - type CompletionGetParams as CompletionGetParams, + type CompletionGetParams as CompletionGetParams }; } diff --git a/src/resources/async/chat/index.ts b/src/resources/async/chat/index.ts index 0f5e81e..102fc9c 100644 --- a/src/resources/async/chat/index.ts +++ b/src/resources/async/chat/index.ts @@ -1,11 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Chat } from './chat'; -export { - Completions, - type CompletionCreateResponse, - type CompletionListResponse, - type CompletionGetResponse, - type CompletionCreateParams, - type CompletionGetParams, -} from './completions'; +export { Chat } from './chat';; +export { Completions, type CompletionCreateResponse, type CompletionListResponse, type CompletionGetResponse, type CompletionCreateParams, type CompletionGetParams } from './completions';; diff --git a/src/resources/async/index.ts b/src/resources/async/index.ts index 628a398..f6ff95a 100644 --- a/src/resources/async/index.ts +++ b/src/resources/async/index.ts @@ -1,4 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Async } from './async'; -export { Chat } from './chat/index'; +export { Async } from './async';; +export { Chat } from './chat/index';; diff --git a/src/resources/browser/browser.ts b/src/resources/browser/browser.ts index f854818..a5c90ce 100644 --- a/src/resources/browser/browser.ts +++ b/src/resources/browser/browser.ts @@ -11,5 +11,8 @@ export class Browser extends APIResource { Browser.Sessions = Sessions; export declare namespace Browser { - export { Sessions as Sessions, type SessionCreateParams as SessionCreateParams }; + export { + Sessions as Sessions, + type SessionCreateParams as SessionCreateParams + }; } diff --git a/src/resources/browser/index.ts b/src/resources/browser/index.ts index 6084119..a617b4d 100644 --- a/src/resources/browser/index.ts +++ b/src/resources/browser/index.ts @@ -1,4 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Browser } from './browser'; -export { Sessions, type SessionCreateParams } from './sessions'; +export { Browser } from './browser';; +export { Sessions, type SessionCreateParams } from './sessions';; diff --git a/src/resources/browser/sessions.ts b/src/resources/browser/sessions.ts index 14c551f..5828dba 100644 --- a/src/resources/browser/sessions.ts +++ b/src/resources/browser/sessions.ts @@ -11,10 +11,7 @@ export class Sessions extends APIResource { /** * Create a new remote browser session for CDP-based automation. */ - create( - body?: SessionCreateParams | null | undefined, - options?: RequestOptions, - ): APIPromise { + create(body?: SessionCreateParams | null | undefined, options?: RequestOptions): APIPromise { return this._client.post('/v1/browser/sessions', { body, ...options }); } @@ -22,15 +19,15 @@ export class Sessions extends APIResource { * Stop and clean up a remote browser session. */ delete(sessionID: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/v1/browser/sessions/${sessionID}`, { - ...options, - headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), - }); + return this._client.delete(path`/v1/browser/sessions/${sessionID}`, { ...options, headers: buildHeaders([{Accept: '*/*'}, options?.headers]) }); } } -export interface SessionCreateParams {} +export interface SessionCreateParams { +} export declare namespace Sessions { - export { type SessionCreateParams as SessionCreateParams }; + export { + type SessionCreateParams as SessionCreateParams + }; } diff --git a/src/resources/chat/chat.ts b/src/resources/chat/chat.ts index 952dc2e..b03d9ac 100644 --- a/src/resources/chat/chat.ts +++ b/src/resources/chat/chat.ts @@ -3,12 +3,7 @@ import { APIResource } from '../../core/resource'; import * as Shared from '../shared'; import * as CompletionsAPI from './completions'; -import { - CompletionCreateParams, - CompletionCreateParamsNonStreaming, - CompletionCreateParamsStreaming, - Completions, -} from './completions'; +import { CompletionCreateParams, CompletionCreateParamsNonStreaming, CompletionCreateParamsStreaming, Completions } from './completions'; export class Chat extends APIResource { completions: CompletionsAPI.Completions = new CompletionsAPI.Completions(this._client); @@ -39,12 +34,14 @@ export interface StreamChunk { Chat.Completions = Completions; export declare namespace Chat { - export { type StreamChunk as StreamChunk }; + export { + type StreamChunk as StreamChunk + }; export { Completions as Completions, type CompletionCreateParams as CompletionCreateParams, type CompletionCreateParamsNonStreaming as CompletionCreateParamsNonStreaming, - type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming, + type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming }; } diff --git a/src/resources/chat/completions.ts b/src/resources/chat/completions.ts index 225d8fd..25bc1f7 100644 --- a/src/resources/chat/completions.ts +++ b/src/resources/chat/completions.ts @@ -12,26 +12,15 @@ export class Completions extends APIResource { /** * Generate a chat completion response for the given conversation. */ - create(body: CompletionCreateParamsNonStreaming, options?: RequestOptions): APIPromise; - create( - body: CompletionCreateParamsStreaming, - options?: RequestOptions, - ): APIPromise>; - create( - body: CompletionCreateParamsBase, - options?: RequestOptions, - ): APIPromise | ChatAPI.StreamChunk>; - create( - body: CompletionCreateParams, - options?: RequestOptions, - ): APIPromise | APIPromise> { - return this._client.post('/chat/completions', { body, ...options, stream: body.stream ?? false }) as - | APIPromise - | APIPromise>; + create(body: CompletionCreateParamsNonStreaming, options?: RequestOptions): APIPromise + create(body: CompletionCreateParamsStreaming, options?: RequestOptions): APIPromise> + create(body: CompletionCreateParamsBase, options?: RequestOptions): APIPromise | ChatAPI.StreamChunk> + create(body: CompletionCreateParams, options?: RequestOptions): APIPromise | APIPromise> { + return this._client.post('/chat/completions', { body, ...options, stream: body.stream ?? false }) as APIPromise | APIPromise>; } } -export type CompletionCreateParams = CompletionCreateParamsNonStreaming | CompletionCreateParamsStreaming; +export type CompletionCreateParams = CompletionCreateParamsNonStreaming | CompletionCreateParamsStreaming export interface CompletionCreateParamsBase { messages: Array; @@ -96,11 +85,7 @@ export interface CompletionCreateParamsBase { reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high' | null; - response_format?: - | CompletionCreateParams.ResponseFormatText - | CompletionCreateParams.ResponseFormatJsonSchema - | CompletionCreateParams.ResponseFormatRegex - | null; + response_format?: CompletionCreateParams.ResponseFormatText | CompletionCreateParams.ResponseFormatJsonSchema | CompletionCreateParams.ResponseFormatRegex | null; response_metadata?: { [key: string]: unknown } | null; @@ -228,8 +213,8 @@ export namespace CompletionCreateParams { } } - export type CompletionCreateParamsNonStreaming = CompletionsAPI.CompletionCreateParamsNonStreaming; - export type CompletionCreateParamsStreaming = CompletionsAPI.CompletionCreateParamsStreaming; + export type CompletionCreateParamsNonStreaming = CompletionsAPI.CompletionCreateParamsNonStreaming + export type CompletionCreateParamsStreaming = CompletionsAPI.CompletionCreateParamsStreaming } export interface CompletionCreateParamsNonStreaming extends CompletionCreateParamsBase { @@ -244,6 +229,6 @@ export declare namespace Completions { export { type CompletionCreateParams as CompletionCreateParams, type CompletionCreateParamsNonStreaming as CompletionCreateParamsNonStreaming, - type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming, + type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming }; } diff --git a/src/resources/chat/index.ts b/src/resources/chat/index.ts index 1a4bddc..8fd7656 100644 --- a/src/resources/chat/index.ts +++ b/src/resources/chat/index.ts @@ -1,9 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Chat, type StreamChunk } from './chat'; -export { - Completions, - type CompletionCreateParams, - type CompletionCreateParamsNonStreaming, - type CompletionCreateParamsStreaming, -} from './completions'; +export { Chat, type StreamChunk } from './chat';; +export { Completions, type CompletionCreateParams, type CompletionCreateParamsNonStreaming, type CompletionCreateParamsStreaming } from './completions';; diff --git a/src/resources/contextualized-embeddings.ts b/src/resources/contextualized-embeddings.ts index 231f25a..f386c53 100644 --- a/src/resources/contextualized-embeddings.ts +++ b/src/resources/contextualized-embeddings.ts @@ -11,10 +11,7 @@ export class ContextualizedEmbeddings extends APIResource { * document share context awareness, improving retrieval quality for document-based * applications. */ - create( - body: ContextualizedEmbeddingCreateParams, - options?: RequestOptions, - ): APIPromise { + create(body: ContextualizedEmbeddingCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/v1/contextualizedembeddings', { body, ...options }); } } @@ -78,6 +75,6 @@ export interface ContextualizedEmbeddingCreateParams { export declare namespace ContextualizedEmbeddings { export { type ContextualizedEmbeddingCreateResponse as ContextualizedEmbeddingCreateResponse, - type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams, + type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams }; } diff --git a/src/resources/embeddings.ts b/src/resources/embeddings.ts index 73abb51..c1c0a42 100644 --- a/src/resources/embeddings.ts +++ b/src/resources/embeddings.ts @@ -71,6 +71,6 @@ export interface EmbeddingCreateParams { export declare namespace Embeddings { export { type EmbeddingCreateResponse as EmbeddingCreateResponse, - type EmbeddingCreateParams as EmbeddingCreateParams, + type EmbeddingCreateParams as EmbeddingCreateParams }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 29654c9..93dc8fb 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,30 +1,10 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './shared'; -export { Async } from './async/async'; -export { Browser } from './browser/browser'; -export { Chat, type StreamChunk } from './chat/chat'; -export { - ContextualizedEmbeddings, - type ContextualizedEmbeddingCreateResponse, - type ContextualizedEmbeddingCreateParams, -} from './contextualized-embeddings'; -export { Embeddings, type EmbeddingCreateResponse, type EmbeddingCreateParams } from './embeddings'; -export { - Responses, - type Annotation, - type ContentPart, - type ErrorInfo, - type FunctionCallOutputItem, - type FunctionTool, - type InputItem, - type OutputItem, - type ResponseStreamChunk, - type ResponsesCreateParams, - type ResponsesUsage, - type ResponseCreateResponse, - type ResponseCreateParams, - type ResponseCreateParamsNonStreaming, - type ResponseCreateParamsStreaming, -} from './responses'; -export { Search, type SearchCreateResponse, type SearchCreateParams } from './search'; +export * from './shared';; +export { Async } from './async/async';; +export { Browser } from './browser/browser';; +export { Chat, type StreamChunk } from './chat/chat';; +export { ContextualizedEmbeddings, type ContextualizedEmbeddingCreateResponse, type ContextualizedEmbeddingCreateParams } from './contextualized-embeddings';; +export { Embeddings, type EmbeddingCreateResponse, type EmbeddingCreateParams } from './embeddings';; +export { Responses, type Annotation, type ContentPart, type ErrorInfo, type FunctionCallOutputItem, type FunctionTool, type InputItem, type OutputItem, type ResponseStreamChunk, type ResponsesCreateParams, type ResponsesUsage, type ResponseCreateResponse, type ResponseCreateParams, type ResponseCreateParamsNonStreaming, type ResponseCreateParamsStreaming } from './responses';; +export { Search, type SearchCreateResponse, type SearchCreateParams } from './search';; diff --git a/src/resources/responses.ts b/src/resources/responses.ts index 5b7c45c..42d4f10 100644 --- a/src/resources/responses.ts +++ b/src/resources/responses.ts @@ -13,22 +13,10 @@ export class Responses extends APIResource { * Generate a response for the provided input with optional web search and * reasoning. */ - create( - body: ResponseCreateParamsNonStreaming, - options?: RequestOptions, - ): APIPromise; - create( - body: ResponseCreateParamsStreaming, - options?: RequestOptions, - ): APIPromise>; - create( - body: ResponseCreateParamsBase, - options?: RequestOptions, - ): APIPromise | ResponseCreateResponse>; - create( - body: ResponseCreateParams, - options?: RequestOptions, - ): APIPromise | APIPromise> { + create(body: ResponseCreateParamsNonStreaming, options?: RequestOptions): APIPromise + create(body: ResponseCreateParamsStreaming, options?: RequestOptions): APIPromise> + create(body: ResponseCreateParamsBase, options?: RequestOptions): APIPromise | ResponseCreateResponse> + create(body: ResponseCreateParams, options?: RequestOptions): APIPromise | APIPromise> { const promise = this._client.post('/v1/responses', { body, ...options, stream: body.stream ?? false }); // For non-streaming responses, automatically add output_text property @@ -131,10 +119,7 @@ export interface FunctionTool { strict?: boolean; } -export type InputItem = - | InputItem.InputMessage - | InputItem.FunctionCallOutputInput - | InputItem.FunctionCallInput; +export type InputItem = InputItem.InputMessage | InputItem.FunctionCallOutputInput | InputItem.FunctionCallInput export namespace InputItem { export interface InputMessage { @@ -207,11 +192,7 @@ export namespace InputItem { } } -export type OutputItem = - | OutputItem.MessageOutputItem - | OutputItem.SearchResultsOutputItem - | OutputItem.FetchURLResultsOutputItem - | FunctionCallOutputItem; +export type OutputItem = OutputItem.MessageOutputItem | OutputItem.SearchResultsOutputItem | OutputItem.FetchURLResultsOutputItem | FunctionCallOutputItem export namespace OutputItem { export interface MessageOutputItem { @@ -287,21 +268,7 @@ export namespace OutputItem { * - `response.reasoning.fetch_url_results`: URL fetch results received * - `response.reasoning.stopped`: Reasoning phase complete */ -export type ResponseStreamChunk = - | ResponseStreamChunk.ResponseCreatedEvent - | ResponseStreamChunk.ResponseInProgressEvent - | ResponseStreamChunk.ResponseCompletedEvent - | ResponseStreamChunk.ResponseFailedEvent - | ResponseStreamChunk.OutputItemAddedEvent - | ResponseStreamChunk.OutputItemDoneEvent - | ResponseStreamChunk.TextDeltaEvent - | ResponseStreamChunk.TextDoneEvent - | ResponseStreamChunk.ReasoningStartedEvent - | ResponseStreamChunk.SearchQueriesEvent - | ResponseStreamChunk.SearchResultsEvent - | ResponseStreamChunk.FetchURLQueriesEvent - | ResponseStreamChunk.FetchURLResultsEvent - | ResponseStreamChunk.ReasoningStoppedEvent; +export type ResponseStreamChunk = ResponseStreamChunk.ResponseCreatedEvent | ResponseStreamChunk.ResponseInProgressEvent | ResponseStreamChunk.ResponseCompletedEvent | ResponseStreamChunk.ResponseFailedEvent | ResponseStreamChunk.OutputItemAddedEvent | ResponseStreamChunk.OutputItemDoneEvent | ResponseStreamChunk.TextDeltaEvent | ResponseStreamChunk.TextDoneEvent | ResponseStreamChunk.ReasoningStartedEvent | ResponseStreamChunk.SearchQueriesEvent | ResponseStreamChunk.SearchResultsEvent | ResponseStreamChunk.FetchURLQueriesEvent | ResponseStreamChunk.FetchURLResultsEvent | ResponseStreamChunk.ReasoningStoppedEvent export namespace ResponseStreamChunk { /** @@ -317,21 +284,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; /** * Non-streaming response returned when stream is false @@ -381,21 +334,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; /** * Non-streaming response returned when stream is false @@ -444,21 +383,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; /** * Non-streaming response returned when stream is false @@ -510,21 +435,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; } /** @@ -544,21 +455,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; } /** @@ -578,21 +475,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; } /** @@ -616,21 +499,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; } /** @@ -654,21 +523,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; } /** @@ -684,21 +539,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; thought?: string; } @@ -718,21 +559,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; thought?: string; } @@ -752,21 +579,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; thought?: string; @@ -786,21 +599,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; urls: Array; @@ -822,21 +621,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; thought?: string; } @@ -876,21 +661,7 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: - | 'response.created' - | 'response.in_progress' - | 'response.completed' - | 'response.failed' - | 'response.output_item.added' - | 'response.output_item.done' - | 'response.output_text.delta' - | 'response.output_text.done' - | 'response.reasoning.started' - | 'response.reasoning.search_queries' - | 'response.reasoning.search_results' - | 'response.reasoning.fetch_url_queries' - | 'response.reasoning.fetch_url_results' - | 'response.reasoning.stopped'; + type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; thought?: string; } @@ -1123,7 +894,7 @@ export interface ResponseCreateResponse { output_text?: string; } -export type ResponseCreateParams = ResponseCreateParamsNonStreaming | ResponseCreateParamsStreaming; +export type ResponseCreateParams = ResponseCreateParamsNonStreaming | ResponseCreateParamsStreaming export interface ResponseCreateParamsBase { /** @@ -1270,8 +1041,8 @@ export namespace ResponseCreateParams { max_urls?: number; } - export type ResponseCreateParamsNonStreaming = ResponsesAPI.ResponseCreateParamsNonStreaming; - export type ResponseCreateParamsStreaming = ResponsesAPI.ResponseCreateParamsStreaming; + export type ResponseCreateParamsNonStreaming = ResponsesAPI.ResponseCreateParamsNonStreaming + export type ResponseCreateParamsStreaming = ResponsesAPI.ResponseCreateParamsStreaming } export interface ResponseCreateParamsNonStreaming extends ResponseCreateParamsBase { @@ -1303,6 +1074,6 @@ export declare namespace Responses { type ResponseCreateResponse as ResponseCreateResponse, type ResponseCreateParams as ResponseCreateParams, type ResponseCreateParamsNonStreaming as ResponseCreateParamsNonStreaming, - type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming, + type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming }; } diff --git a/src/resources/search.ts b/src/resources/search.ts index 3465db6..0385cbf 100644 --- a/src/resources/search.ts +++ b/src/resources/search.ts @@ -66,5 +66,8 @@ export interface SearchCreateParams { } export declare namespace Search { - export { type SearchCreateResponse as SearchCreateResponse, type SearchCreateParams as SearchCreateParams }; + export { + type SearchCreateResponse as SearchCreateResponse, + type SearchCreateParams as SearchCreateParams + }; } diff --git a/src/resources/shared.ts b/src/resources/shared.ts index ee49414..6868e0e 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -32,16 +32,7 @@ export interface BrowserSessionResponse { } export interface ChatMessageInput { - content: - | string - | Array< - | ChatMessageInput.ChatMessageContentTextChunk - | ChatMessageInput.ChatMessageContentImageChunk - | ChatMessageInput.ChatMessageContentFileChunk - | ChatMessageInput.ChatMessageContentPdfChunk - | ChatMessageInput.ChatMessageContentVideoChunk - > - | null; + content: string | Array | null; /** * Chat roles enum @@ -183,16 +174,7 @@ export namespace ChatMessageInput { } export interface ChatMessageOutput { - content: - | string - | Array< - | ChatMessageOutput.ChatMessageContentTextChunk - | ChatMessageOutput.ChatMessageContentImageChunk - | ChatMessageOutput.ChatMessageContentFileChunk - | ChatMessageOutput.ChatMessageContentPdfChunk - | ChatMessageOutput.ChatMessageContentVideoChunk - > - | null; + content: string | Array | null; /** * Chat roles enum diff --git a/src/streaming.ts b/src/streaming.ts index 9e6da10..1708536 100644 --- a/src/streaming.ts +++ b/src/streaming.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/streaming instead */ -export * from './core/streaming'; +export * from "./core/streaming" \ No newline at end of file diff --git a/src/uploads.ts b/src/uploads.ts index b2ef647..d543708 100644 --- a/src/uploads.ts +++ b/src/uploads.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/uploads instead */ -export * from './core/uploads'; +export * from "./core/uploads" \ No newline at end of file diff --git a/src/version.ts b/src/version.ts index 288031c..da70f84 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.27.0'; // x-release-please-version +export const VERSION = '0.27.0';// x-release-please-version diff --git a/tests/api-resources/async/chat/completions.test.ts b/tests/api-resources/async/chat/completions.test.ts index 429241a..07b0415 100644 --- a/tests/api-resources/async/chat/completions.test.ts +++ b/tests/api-resources/async/chat/completions.test.ts @@ -2,17 +2,12 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource completions', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.async.chat.completions.create({ - request: { messages: [{ content: 'string', role: 'system' }], model: 'model' }, - }); + const responsePromise = client.async.chat.completions.create({ request: { messages: [{ content: 'string', role: 'system' }], model: 'model' } }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -25,140 +20,123 @@ describe('resource completions', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.async.chat.completions.create({ - request: { - messages: [ - { - content: 'string', - role: 'system', - reasoning_steps: [ - { - thought: 'thought', - execute_python: { code: 'code', result: 'result' }, - fetch_url_content: { - contents: [ - { - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }, - ], - }, - type: 'type', - web_search: { - search_keywords: ['string'], - search_results: [ - { - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }, - ], - }, - }, - ], - tool_call_id: 'tool_call_id', - tool_calls: [ - { - id: 'id', - function: { arguments: 'arguments', name: 'name' }, - type: 'function', - }, - ], - }, - ], - model: 'model', - _debug_pro_search: true, - _force_new_agent: true, - _inputs: [0], - _prompt_token_length: 0, - best_of: 0, - country: 'country', - cum_logprobs: true, - disable_search: true, - diverse_first_token: true, - enable_search_classifier: true, - file_workspace_id: 'file_workspace_id', - frequency_penalty: -2, - has_image_url: true, - image_domain_filter: ['string'], - image_format_filter: ['string'], - language_preference: 'language_preference', - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - latitude: 0, - logprobs: true, - longitude: 0, - max_tokens: 1, - n: 1, - num_images: 0, - num_search_results: 0, - parallel_tool_calls: true, - presence_penalty: -2, - ranking_model: 'ranking_model', - reasoning_effort: 'minimal', - response_format: { type: 'text' }, - response_metadata: { foo: 'bar' }, - return_images: true, - return_related_questions: true, - safe_search: true, - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_internal_properties: { foo: 'bar' }, - search_language_filter: ['string'], - search_mode: 'web', - search_recency_filter: 'hour', - search_tenant: 'search_tenant', - stop: 'string', - stream: true, - stream_mode: 'full', - temperature: 0, - thread_id: 'thread_id', - tool_choice: 'none', - tools: [ - { - function: { - description: 'description', - name: 'name', - parameters: { - properties: { foo: 'bar' }, - type: 'type', - additional_properties: true, - required: ['string'], - }, - strict: true, - }, - type: 'function', - }, - ], - top_k: 0, - top_logprobs: 0, - top_p: 0, - updated_after_timestamp: 0, - updated_before_timestamp: 0, - use_threads: true, - user_original_query: 'user_original_query', - web_search_options: { - image_results_enhanced_relevance: true, - search_context_size: 'low', - search_type: 'fast', - user_location: { - city: 'city', - country: 'country', - latitude: 0, - longitude: 0, - region: 'region', - }, - }, - }, - idempotency_key: 'idempotency_key', - }); + request: { + messages: [{ + content: 'string', + role: 'system', + reasoning_steps: [{ + thought: 'thought', + execute_python: { code: 'code', result: 'result' }, + fetch_url_content: { contents: [{ + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }] }, + type: 'type', + web_search: { search_keywords: ['string'], search_results: [{ + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }] }, + }], + tool_call_id: 'tool_call_id', + tool_calls: [{ + id: 'id', + function: { arguments: 'arguments', name: 'name' }, + type: 'function', + }], + }], + model: 'model', + _debug_pro_search: true, + _force_new_agent: true, + _inputs: [0], + _prompt_token_length: 0, + best_of: 0, + country: 'country', + cum_logprobs: true, + disable_search: true, + diverse_first_token: true, + enable_search_classifier: true, + file_workspace_id: 'file_workspace_id', + frequency_penalty: -2, + has_image_url: true, + image_domain_filter: ['string'], + image_format_filter: ['string'], + language_preference: 'language_preference', + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + latitude: 0, + logprobs: true, + longitude: 0, + max_tokens: 1, + n: 1, + num_images: 0, + num_search_results: 0, + parallel_tool_calls: true, + presence_penalty: -2, + ranking_model: 'ranking_model', + reasoning_effort: 'minimal', + response_format: { type: 'text' }, + response_metadata: { foo: 'bar' }, + return_images: true, + return_related_questions: true, + safe_search: true, + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_internal_properties: { foo: 'bar' }, + search_language_filter: ['string'], + search_mode: 'web', + search_recency_filter: 'hour', + search_tenant: 'search_tenant', + stop: 'string', + stream: true, + stream_mode: 'full', + temperature: 0, + thread_id: 'thread_id', + tool_choice: 'none', + tools: [{ + function: { + description: 'description', + name: 'name', + parameters: { + properties: { foo: 'bar' }, + type: 'type', + additional_properties: true, + required: ['string'], + }, + strict: true, + }, + type: 'function', + }], + top_k: 0, + top_logprobs: 0, + top_p: 0, + updated_after_timestamp: 0, + updated_before_timestamp: 0, + use_threads: true, + user_original_query: 'user_original_query', + web_search_options: { + image_results_enhanced_relevance: true, + search_context_size: 'low', + search_type: 'fast', + user_location: { + city: 'city', + country: 'country', + latitude: 0, + longitude: 0, + region: 'region', + }, + }, + }, + idempotency_key: 'idempotency_key', + }); }); // Mock server tests are disabled @@ -188,20 +166,16 @@ describe('resource completions', () => { // Mock server tests are disabled test.skip('get: 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.async.chat.completions.get( - 'api_request', - { - local_mode: true, - 'x-client-env': 'x-client-env', - 'x-client-name': 'x-client-name', - 'x-created-at-epoch-seconds': 'x-created-at-epoch-seconds', - 'x-request-time': 'x-request-time', - 'x-usage-tier': 'x-usage-tier', - 'x-user-id': 'x-user-id', - }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(Perplexity.NotFoundError); + await expect(client.async.chat.completions.get('api_request', { + local_mode: true, + 'x-client-env': 'x-client-env', + 'x-client-name': 'x-client-name', + 'x-created-at-epoch-seconds': 'x-created-at-epoch-seconds', + 'x-request-time': 'x-request-time', + 'x-usage-tier': 'x-usage-tier', + 'x-user-id': 'x-user-id', + }, { path: '/_stainless_unknown_path' })) + .rejects + .toThrow(Perplexity.NotFoundError); }); }); diff --git a/tests/api-resources/browser/sessions.test.ts b/tests/api-resources/browser/sessions.test.ts index 1095635..aa7a74f 100644 --- a/tests/api-resources/browser/sessions.test.ts +++ b/tests/api-resources/browser/sessions.test.ts @@ -2,10 +2,7 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource sessions', () => { // Mock server tests are disabled @@ -23,9 +20,9 @@ describe('resource sessions', () => { // Mock server tests are disabled test.skip('create: 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.browser.sessions.create({}, { path: '/_stainless_unknown_path' })).rejects.toThrow( - Perplexity.NotFoundError, - ); + await expect(client.browser.sessions.create({}, { path: '/_stainless_unknown_path' })) + .rejects + .toThrow(Perplexity.NotFoundError); }); // Mock server tests are disabled diff --git a/tests/api-resources/chat/completions.test.ts b/tests/api-resources/chat/completions.test.ts index aede87d..8393533 100644 --- a/tests/api-resources/chat/completions.test.ts +++ b/tests/api-resources/chat/completions.test.ts @@ -2,18 +2,12 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource completions', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.chat.completions.create({ - messages: [{ content: 'string', role: 'system' }], - model: 'model', - }); + const responsePromise = client.chat.completions.create({ messages: [{ content: 'string', role: 'system' }], model: 'model' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -26,136 +20,119 @@ describe('resource completions', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.chat.completions.create({ - messages: [ - { - content: 'string', - role: 'system', - reasoning_steps: [ - { - thought: 'thought', - execute_python: { code: 'code', result: 'result' }, - fetch_url_content: { - contents: [ - { - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }, - ], - }, - type: 'type', - web_search: { - search_keywords: ['string'], - search_results: [ - { - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }, - ], - }, - }, - ], - tool_call_id: 'tool_call_id', - tool_calls: [ - { - id: 'id', - function: { arguments: 'arguments', name: 'name' }, - type: 'function', - }, - ], - }, - ], - model: 'model', - _debug_pro_search: true, - _force_new_agent: true, - _inputs: [0], - _prompt_token_length: 0, - best_of: 0, - country: 'country', - cum_logprobs: true, - disable_search: true, - diverse_first_token: true, - enable_search_classifier: true, - file_workspace_id: 'file_workspace_id', - frequency_penalty: -2, - has_image_url: true, - image_domain_filter: ['string'], - image_format_filter: ['string'], - language_preference: 'language_preference', - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - latitude: 0, - logprobs: true, - longitude: 0, - max_tokens: 1, - n: 1, - num_images: 0, - num_search_results: 0, - parallel_tool_calls: true, - presence_penalty: -2, - ranking_model: 'ranking_model', - reasoning_effort: 'minimal', - response_format: { type: 'text' }, - response_metadata: { foo: 'bar' }, - return_images: true, - return_related_questions: true, - safe_search: true, - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_internal_properties: { foo: 'bar' }, - search_language_filter: ['string'], - search_mode: 'web', - search_recency_filter: 'hour', - search_tenant: 'search_tenant', - stop: 'string', - stream: false, - stream_mode: 'full', - temperature: 0, - thread_id: 'thread_id', - tool_choice: 'none', - tools: [ - { - function: { - description: 'description', - name: 'name', - parameters: { - properties: { foo: 'bar' }, - type: 'type', - additional_properties: true, - required: ['string'], - }, - strict: true, - }, - type: 'function', - }, - ], - top_k: 0, - top_logprobs: 0, - top_p: 0, - updated_after_timestamp: 0, - updated_before_timestamp: 0, - use_threads: true, - user_original_query: 'user_original_query', - web_search_options: { - image_results_enhanced_relevance: true, - search_context_size: 'low', - search_type: 'fast', - user_location: { - city: 'city', - country: 'country', - latitude: 0, - longitude: 0, - region: 'region', - }, - }, - }); + messages: [{ + content: 'string', + role: 'system', + reasoning_steps: [{ + thought: 'thought', + execute_python: { code: 'code', result: 'result' }, + fetch_url_content: { contents: [{ + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }] }, + type: 'type', + web_search: { search_keywords: ['string'], search_results: [{ + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }] }, + }], + tool_call_id: 'tool_call_id', + tool_calls: [{ + id: 'id', + function: { arguments: 'arguments', name: 'name' }, + type: 'function', + }], + }], + model: 'model', + _debug_pro_search: true, + _force_new_agent: true, + _inputs: [0], + _prompt_token_length: 0, + best_of: 0, + country: 'country', + cum_logprobs: true, + disable_search: true, + diverse_first_token: true, + enable_search_classifier: true, + file_workspace_id: 'file_workspace_id', + frequency_penalty: -2, + has_image_url: true, + image_domain_filter: ['string'], + image_format_filter: ['string'], + language_preference: 'language_preference', + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + latitude: 0, + logprobs: true, + longitude: 0, + max_tokens: 1, + n: 1, + num_images: 0, + num_search_results: 0, + parallel_tool_calls: true, + presence_penalty: -2, + ranking_model: 'ranking_model', + reasoning_effort: 'minimal', + response_format: { type: 'text' }, + response_metadata: { foo: 'bar' }, + return_images: true, + return_related_questions: true, + safe_search: true, + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_internal_properties: { foo: 'bar' }, + search_language_filter: ['string'], + search_mode: 'web', + search_recency_filter: 'hour', + search_tenant: 'search_tenant', + stop: 'string', + stream: false, + stream_mode: 'full', + temperature: 0, + thread_id: 'thread_id', + tool_choice: 'none', + tools: [{ + function: { + description: 'description', + name: 'name', + parameters: { + properties: { foo: 'bar' }, + type: 'type', + additional_properties: true, + required: ['string'], + }, + strict: true, + }, + type: 'function', + }], + top_k: 0, + top_logprobs: 0, + top_p: 0, + updated_after_timestamp: 0, + updated_before_timestamp: 0, + use_threads: true, + user_original_query: 'user_original_query', + web_search_options: { + image_results_enhanced_relevance: true, + search_context_size: 'low', + search_type: 'fast', + user_location: { + city: 'city', + country: 'country', + latitude: 0, + longitude: 0, + region: 'region', + }, + }, + }); }); }); diff --git a/tests/api-resources/contextualized-embeddings.test.ts b/tests/api-resources/contextualized-embeddings.test.ts index 05f97a5..1443b98 100644 --- a/tests/api-resources/contextualized-embeddings.test.ts +++ b/tests/api-resources/contextualized-embeddings.test.ts @@ -2,18 +2,12 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource contextualizedEmbeddings', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.contextualizedEmbeddings.create({ - input: [['x']], - model: 'pplx-embed-context-v1-0.6b', - }); + const responsePromise = client.contextualizedEmbeddings.create({ input: [['x']], model: 'pplx-embed-context-v1-0.6b' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -26,10 +20,10 @@ describe('resource contextualizedEmbeddings', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.contextualizedEmbeddings.create({ - input: [['x']], - model: 'pplx-embed-context-v1-0.6b', - dimensions: 128, - encoding_format: 'base64_int8', - }); + input: [['x']], + model: 'pplx-embed-context-v1-0.6b', + dimensions: 128, + encoding_format: 'base64_int8', + }); }); }); diff --git a/tests/api-resources/embeddings.test.ts b/tests/api-resources/embeddings.test.ts index 07bb0c8..1fc540c 100644 --- a/tests/api-resources/embeddings.test.ts +++ b/tests/api-resources/embeddings.test.ts @@ -2,10 +2,7 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource embeddings', () => { // Mock server tests are disabled @@ -23,10 +20,10 @@ describe('resource embeddings', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.embeddings.create({ - input: 'x', - model: 'pplx-embed-v1-0.6b', - dimensions: 128, - encoding_format: 'base64_int8', - }); + input: 'x', + model: 'pplx-embed-v1-0.6b', + dimensions: 128, + encoding_format: 'base64_int8', + }); }); }); diff --git a/tests/api-resources/responses.test.ts b/tests/api-resources/responses.test.ts index cf715c9..929f123 100644 --- a/tests/api-resources/responses.test.ts +++ b/tests/api-resources/responses.test.ts @@ -2,10 +2,7 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource responses', () => { // Mock server tests are disabled @@ -23,47 +20,45 @@ describe('resource responses', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.responses.create({ - input: 'string', - instructions: 'instructions', - language_preference: 'language_preference', - max_output_tokens: 1, - max_steps: 1, - model: 'model', - models: ['string'], - preset: 'preset', - reasoning: { effort: 'low' }, - response_format: { - type: 'json_schema', - json_schema: { - name: 'x', - schema: { foo: 'bar' }, - description: 'description', - strict: true, - }, - }, - stream: false, - tools: [ - { - type: 'web_search', - filters: { - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_recency_filter: 'hour', - }, - max_tokens: 0, - max_tokens_per_page: 0, - user_location: { - city: 'city', - country: 'country', - latitude: 0, - longitude: 0, - region: 'region', - }, - }, - ], - }); + input: 'string', + instructions: 'instructions', + language_preference: 'language_preference', + max_output_tokens: 1, + max_steps: 1, + model: 'model', + models: ['string'], + preset: 'preset', + reasoning: { effort: 'low' }, + response_format: { + type: 'json_schema', + json_schema: { + name: 'x', + schema: { foo: 'bar' }, + description: 'description', + strict: true, + }, + }, + stream: false, + tools: [{ + type: 'web_search', + filters: { + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_recency_filter: 'hour', + }, + max_tokens: 0, + max_tokens_per_page: 0, + user_location: { + city: 'city', + country: 'country', + latitude: 0, + longitude: 0, + region: 'region', + }, + }], + }); }); }); diff --git a/tests/api-resources/search.test.ts b/tests/api-resources/search.test.ts index 4ecb303..8bdb96a 100644 --- a/tests/api-resources/search.test.ts +++ b/tests/api-resources/search.test.ts @@ -2,10 +2,7 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); describe('resource search', () => { // Mock server tests are disabled @@ -23,20 +20,20 @@ describe('resource search', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.search.create({ - query: 'string', - country: 'country', - display_server_time: true, - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - max_results: 0, - max_tokens: 0, - max_tokens_per_page: 0, - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_language_filter: ['string'], - search_mode: 'web', - search_recency_filter: 'hour', - }); + query: 'string', + country: 'country', + display_server_time: true, + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + max_results: 0, + max_tokens: 0, + max_tokens_per_page: 0, + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_language_filter: ['string'], + search_mode: 'web', + search_recency_filter: 'hour', + }); }); }); diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index 4cbe1e7..b3db93a 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,9 +1,5 @@ import { inspect } from 'node:util'; -import { - buildHeaders, - type HeadersLike, - type NullableHeaders, -} from '@perplexity-ai/perplexity_ai/internal/headers'; +import { buildHeaders, type HeadersLike, type NullableHeaders } from '@perplexity-ai/perplexity_ai/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/index.test.ts b/tests/index.test.ts index 704454e..bf861e3 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -21,10 +21,10 @@ describe('instantiate client', () => { describe('defaultHeaders', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultHeaders: { 'X-My-Default-Header': '2' }, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-My-Default-Header': '2' }, + apiKey: 'My API Key', +}) test('they are used in the request', async () => { const { req } = await client.buildRequest({ path: '/foo', method: 'post' }); @@ -49,193 +49,191 @@ describe('instantiate client', () => { expect(req.headers.has('x-my-default-header')).toBe(false); }); }); - describe('logging', () => { - const env = process.env; +describe('logging', () => { + const env = process.env; - beforeEach(() => { - process.env = { ...env }; - process.env['PERPLEXITY_LOG'] = undefined; - }); + beforeEach(() => { + process.env = { ...env }; + process.env['PERPLEXITY_LOG'] = undefined; + }); - afterEach(() => { - process.env = env; - }); + afterEach(() => { + process.env = env; + }); - const forceAPIResponseForClient = async (client: Perplexity) => { - await new APIPromise( - client, - Promise.resolve({ - response: new Response(), - controller: new AbortController(), - requestLogID: 'log_000000', - retryOfRequestLogID: undefined, - startTime: Date.now(), - options: { - method: 'get', - path: '/', - }, - }), - ); + const forceAPIResponseForClient = async (client: Perplexity) => { + await new APIPromise( + client, + Promise.resolve({ + response: new Response(), + controller: new AbortController(), + requestLogID: 'log_000000', + retryOfRequestLogID: undefined, + startTime: Date.now(), + options: { + method: 'get', + path: '/', + }, + }), + ); + }; + + test('debug logs when log level is debug', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), }; - test('debug logs when log level is debug', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; - - const client = new Perplexity({ - logger: logger, - logLevel: 'debug', - apiKey: 'My API Key', - }); + const client = new Perplexity({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', +}); - await forceAPIResponseForClient(client); - expect(debugMock).toHaveBeenCalled(); - }); + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); - test('default logLevel is warn', async () => { - const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.logLevel).toBe('warn'); - }); + test('default logLevel is warn', async () => { + const client = new Perplexity({ apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + }); - test('debug logs are skipped when log level is info', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; + test('debug logs are skipped when log level is info', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - const client = new Perplexity({ - logger: logger, - logLevel: 'info', - apiKey: 'My API Key', - }); + const client = new Perplexity({ + logger: logger, + logLevel: 'info', + apiKey: 'My API Key', +}); - await forceAPIResponseForClient(client); - expect(debugMock).not.toHaveBeenCalled(); - }); + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); - test('debug logs happen with debug env var', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; + test('debug logs happen with debug env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - process.env['PERPLEXITY_LOG'] = 'debug'; - const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); - expect(client.logLevel).toBe('debug'); + process.env['PERPLEXITY_LOG'] = 'debug'; + const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('debug'); - await forceAPIResponseForClient(client); - expect(debugMock).toHaveBeenCalled(); - }); + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); - test('warn when env var level is invalid', async () => { - const warnMock = jest.fn(); - const logger = { - debug: jest.fn(), - info: jest.fn(), - warn: warnMock, - error: jest.fn(), - }; + test('warn when env var level is invalid', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; - process.env['PERPLEXITY_LOG'] = 'not a log level'; - const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); - expect(client.logLevel).toBe('warn'); - expect(warnMock).toHaveBeenCalledWith( - 'process.env[\'PERPLEXITY_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', - ); - }); + process.env['PERPLEXITY_LOG'] = 'not a log level'; + const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + expect(warnMock).toHaveBeenCalledWith('process.env[\'PERPLEXITY_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]'); + }); - test('client log level overrides env var', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; + test('client log level overrides env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - process.env['PERPLEXITY_LOG'] = 'debug'; - const client = new Perplexity({ - logger: logger, - logLevel: 'off', - apiKey: 'My API Key', - }); + process.env['PERPLEXITY_LOG'] = 'debug'; + const client = new Perplexity({ + logger: logger, + logLevel: 'off', + apiKey: 'My API Key', +}); - await forceAPIResponseForClient(client); - expect(debugMock).not.toHaveBeenCalled(); - }); + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); - test('no warning logged for invalid env var level + valid client level', async () => { - const warnMock = jest.fn(); - const logger = { - debug: jest.fn(), - info: jest.fn(), - warn: warnMock, - error: jest.fn(), - }; + test('no warning logged for invalid env var level + valid client level', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; - process.env['PERPLEXITY_LOG'] = 'not a log level'; - const client = new Perplexity({ - logger: logger, - logLevel: 'debug', - apiKey: 'My API Key', - }); - expect(client.logLevel).toBe('debug'); - expect(warnMock).not.toHaveBeenCalled(); - }); + process.env['PERPLEXITY_LOG'] = 'not a log level'; + const client = new Perplexity({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', +}); + expect(client.logLevel).toBe('debug'); + expect(warnMock).not.toHaveBeenCalled(); }); +}); describe('defaultQuery', () => { test('with null query params given', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultQuery: { apiVersion: 'foo' }, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo' }, + apiKey: 'My API Key', +}); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); test('multiple default query params', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultQuery: { apiVersion: 'foo', hello: 'world' }, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo', hello: 'world' }, + apiKey: 'My API Key', +}); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); test('overriding with `undefined`', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultQuery: { hello: 'world' }, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + defaultQuery: { hello: 'world' }, + apiKey: 'My API Key', +}) expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); }); test('custom fetch', async () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: (url) => { - return Promise.resolve( - new Response(JSON.stringify({ url, custom: true }), { - headers: { 'Content-Type': 'application/json' }, - }), - ); - }, - }); + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: (url) => { + return Promise.resolve( + new Response(JSON.stringify({ url, custom: true }), { + headers: { 'Content-Type': 'application/json' }, + }), + ); +}, +}); const response = await client.get('/foo'); expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true }); @@ -244,35 +242,37 @@ describe('instantiate client', () => { test('explicit global fetch', async () => { // make sure the global fetch type is assignable to our Fetch type const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: defaultFetch, - }); + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: defaultFetch, +}); }); test('custom signal', async () => { const client = new Perplexity({ - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - apiKey: 'My API Key', - fetch: (...args) => { - return new Promise((resolve, reject) => - setTimeout( - () => - defaultFetch(...args) - .then(resolve) - .catch(reject), - 300, - ), - ); - }, - }); + baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010', + apiKey: 'My API Key', + fetch: (...args) => { + return new Promise((resolve, reject) => + setTimeout( + () => + defaultFetch(...args) + .then(resolve) + .catch(reject), + 300, + ), + ); +}, +}); const controller = new AbortController(); setTimeout(() => controller.abort(), 200); const spy = jest.spyOn(client, 'request'); - await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError(APIUserAbortError); + await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError( + APIUserAbortError, + ); expect(spy).toHaveBeenCalledTimes(1); }); @@ -284,10 +284,10 @@ describe('instantiate client', () => { }; const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: testFetch, - }); + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: testFetch, +}); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -322,35 +322,29 @@ describe('instantiate client', () => { test('empty env variable', () => { process.env['PERPLEXITY_BASE_URL'] = ''; // empty const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.perplexity.ai'); + expect(client.baseURL).toEqual('https://api.perplexity.ai') }); test('blank env variable', () => { process.env['PERPLEXITY_BASE_URL'] = ' '; // blank const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.perplexity.ai'); + expect(client.baseURL).toEqual('https://api.perplexity.ai') }); test('in request options', () => { const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( - 'http://localhost:5000/option/foo', - ); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual('http://localhost:5000/option/foo'); }); test('in request options overridden by client options', () => { const client = new Perplexity({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); - expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( - 'http://localhost:5000/client/foo', - ); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual('http://localhost:5000/client/foo'); }); test('in request options overridden by env variable', () => { process.env['PERPLEXITY_BASE_URL'] = 'http://localhost:5000/env'; const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( - 'http://localhost:5000/env/foo', - ); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual('http://localhost:5000/env/foo'); }); }); @@ -366,10 +360,10 @@ describe('instantiate client', () => { describe('withOptions', () => { test('creates a new client with overridden options', async () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - maxRetries: 3, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + maxRetries: 3, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ maxRetries: 5, @@ -391,11 +385,11 @@ describe('instantiate client', () => { test('inherits options from the parent client', async () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultHeaders: { 'X-Test-Header': 'test-value' }, - defaultQuery: { 'test-param': 'test-value' }, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-Test-Header': 'test-value' }, + defaultQuery: { 'test-param': 'test-value' }, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ baseURL: 'http://localhost:5001/', @@ -410,10 +404,10 @@ describe('instantiate client', () => { test('respects runtime property changes when creating new client', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - timeout: 1000, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + timeout: 1000, + apiKey: 'My API Key', + }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -459,18 +453,13 @@ describe('request building', () => { describe('custom headers', () => { test('handles undefined', async () => { - const { req } = await client.buildRequest({ - path: '/foo', - method: 'post', - body: { value: 'hello' }, - headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null }, - }); + const { req } = await client.buildRequest({ path: '/foo', method: 'post', body: { value: 'hello' }, headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null } }); expect(req.headers.get('x-foo')).toEqual('bar'); expect(req.headers.get('x-Foo')).toEqual('bar'); expect(req.headers.get('X-Foo')).toEqual('bar'); expect(req.headers.get('x-baz')).toEqual(null); }); - }); + }) }); describe('default encoder', () => { @@ -547,40 +536,37 @@ describe('default encoder', () => { describe('retries', () => { test('retry on timeout', async () => { let count = 0; - const testFetch = async ( - url: string | URL | Request, - { signal }: RequestInit = {}, - ): Promise => { - if (count++ === 0) { - return new Promise( - (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))), - ); - } - return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); - }; - - const client = new Perplexity({ - apiKey: 'My API Key', - timeout: 10, - fetch: testFetch, - }); + const testFetch = async (url: string | URL | Request, { signal }: RequestInit = {}): Promise => { + if (count++ === 0) { + return new Promise((resolve, reject) => + signal?.addEventListener('abort', () => reject(new Error('timed out'))), + ); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; - expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); - expect(count).toEqual(2); - expect( - await client - .request({ path: '/foo', method: 'get' }) - .asResponse() - .then((r) => r.text()), - ).toEqual(JSON.stringify({ a: 1 })); - expect(count).toEqual(3); + const client = new Perplexity({ + apiKey: 'My API Key', + timeout: 10, + fetch: testFetch, }); + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + test('retry count header', async () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++; + count++ if (count <= 2) { return new Response(undefined, { status: 429, @@ -594,10 +580,10 @@ describe('retries', () => { }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -609,7 +595,7 @@ describe('retries', () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++; + count++ if (count <= 2) { return new Response(undefined, { status: 429, @@ -622,10 +608,10 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -642,7 +628,7 @@ describe('retries', () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++; + count++ if (count <= 2) { return new Response(undefined, { status: 429, @@ -655,11 +641,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - defaultHeaders: { 'X-Stainless-Retry-Count': null }, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + defaultHeaders: { 'X-Stainless-Retry-Count': null }, + }); expect( await client.request({ @@ -675,7 +661,7 @@ describe('retries', () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++; + count++ if (count <= 2) { return new Response(undefined, { status: 429, @@ -688,10 +674,10 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -706,10 +692,7 @@ describe('retries', () => { test('retry on 429 with retry-after', async () => { let count = 0; - const testFetch = async ( - url: string | URL | Request, - { signal }: RequestInit = {}, - ): Promise => { + const testFetch = async (url: string | URL | Request, { signal }: RequestInit = {}): Promise => { if (count++ === 0) { return new Response(undefined, { status: 429, @@ -736,10 +719,7 @@ describe('retries', () => { test('retry on 429 with retry-after-ms', async () => { let count = 0; - const testFetch = async ( - url: string | URL | Request, - { signal }: RequestInit = {}, - ): Promise => { + const testFetch = async (url: string | URL | Request, { signal }: RequestInit = {}): Promise => { if (count++ === 0) { return new Response(undefined, { status: 429, diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts index 5c1599c..18d682b 100644 --- a/tests/streaming.test.ts +++ b/tests/streaming.test.ts @@ -242,4 +242,4 @@ test('error handling', async () => { `[Error: {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}]`, ); await err.toBeInstanceOf(APIError); -}); +});; diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index 2358ac4..a2fb223 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -2,26 +2,24 @@ import { stringifyQuery } from '@perplexity-ai/perplexity_ai/internal/utils/query'; -describe(stringifyQuery, () => { - for (const [input, expected] of [ - [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], - [{ a: null, b: false, c: undefined }, 'a=&b=false'], - [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], - [ - { 'a/b': 'c/d', 'e=f': 'g&h' }, - `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( - 'e=f', - )}=${encodeURIComponent('g&h')}`, - ], - ] as const) { - it(`${JSON.stringify(input)} -> ${expected}`, () => { - expect(stringifyQuery(input)).toEqual(expected); - }); - } +describe(stringifyQuery, () => { for (const [input, expected] of [ + [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], + [{ a: null, b: false, c: undefined }, 'a=&b=false'], + [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], + [ + { 'a/b': 'c/d', 'e=f': 'g&h' }, + `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( + 'e=f', + )}=${encodeURIComponent('g&h')}`, + ], +] as const) { + it(`${JSON.stringify(input)} -> ${expected}`, () => { + expect(stringifyQuery(input)).toEqual(expected); + }); +} - for (const value of [[], {}, new Date()]) { - it(`${JSON.stringify(value)} -> `, () => { - expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); - }); - } -}); +for (const value of [[], {}, new Date()]) { + it(`${JSON.stringify(value)} -> `, () => { + expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); + }); +} }) diff --git a/yarn.lock b/yarn.lock index f6eae3c..18e7cbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,11 +709,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" - integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1515,14 +1510,6 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" - integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.7" - eslint-plugin-unused-imports@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" @@ -1674,11 +1661,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -2841,13 +2823,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" @@ -3144,13 +3119,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.7: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== - dependencies: - "@pkgr/core" "^0.2.4" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From d99d9e316cf824d4a67cd29cb9ac026d63351aca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 20:26:36 +0000 Subject: [PATCH 03/12] chore(internal): codegen related update --- eslint.config.mjs | 3 + package.json | 1 + scripts/fast-format | 6 +- scripts/format | 3 +- scripts/lint | 3 - scripts/utils/postprocess-files.cjs | 9 +- src/api-promise.ts | 2 +- src/client.ts | 309 +++++++---- src/core/api-promise.ts | 9 +- src/core/error.ts | 46 +- src/core/streaming.ts | 26 +- src/error.ts | 2 +- src/index.ts | 16 +- src/internal/builtin-types.ts | 23 +- src/internal/detect-platform.ts | 6 +- src/internal/errors.ts | 14 +- src/internal/headers.ts | 4 +- src/internal/parse.ts | 11 +- src/internal/request-options.ts | 7 +- src/internal/shim-types.ts | 4 +- src/internal/shims.ts | 4 +- src/internal/to-file.ts | 14 +- src/internal/types.ts | 50 +- src/internal/utils/log.ts | 37 +- src/internal/utils/uuid.ts | 8 +- src/resource.ts | 2 +- src/resources/async/async.ts | 4 +- src/resources/async/chat/chat.ts | 11 +- src/resources/async/chat/completions.ts | 42 +- src/resources/async/chat/index.ts | 11 +- src/resources/async/index.ts | 4 +- src/resources/browser/browser.ts | 5 +- src/resources/browser/index.ts | 4 +- src/resources/browser/sessions.ts | 17 +- src/resources/chat/chat.ts | 13 +- src/resources/chat/completions.ts | 35 +- src/resources/chat/index.ts | 9 +- src/resources/contextualized-embeddings.ts | 7 +- src/resources/embeddings.ts | 2 +- src/resources/index.ts | 36 +- src/resources/responses.ts | 279 +++++++++- src/resources/search.ts | 5 +- src/resources/shared.ts | 22 +- src/streaming.ts | 2 +- src/uploads.ts | 2 +- src/version.ts | 2 +- .../async/chat/completions.test.ts | 286 +++++----- tests/api-resources/browser/sessions.test.ts | 11 +- tests/api-resources/chat/completions.test.ts | 255 +++++---- .../contextualized-embeddings.test.ts | 20 +- tests/api-resources/embeddings.test.ts | 15 +- tests/api-resources/responses.test.ts | 87 +-- tests/api-resources/search.test.ts | 35 +- tests/buildHeaders.test.ts | 6 +- tests/index.test.ts | 498 +++++++++--------- tests/streaming.test.ts | 2 +- tests/stringifyQuery.test.ts | 42 +- yarn.lock | 32 ++ 58 files changed, 1522 insertions(+), 898 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 6642dab..230d8df 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,6 +1,7 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; +import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -13,9 +14,11 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, + prettier, }, rules: { 'no-unused-vars': 'off', + 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 70a8daa..17bd582 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", + "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/scripts/fast-format b/scripts/fast-format index e172313..53721ac 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,8 +31,10 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -PRETTIER_FILES="$(grep '\.\([mc]?tsx?\|[mc]?jsx?\|json\)$' "$FILE_LIST" || true)" +# format things eslint didn't +PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" if ! [ -z "$PRETTIER_FILES" ]; then echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ + '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' fi diff --git a/scripts/format b/scripts/format index b1b2c17..7a75640 100755 --- a/scripts/format +++ b/scripts/format @@ -8,4 +8,5 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . +# format things eslint didn't +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' diff --git a/scripts/lint b/scripts/lint index 1f53254..3ffb78a 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,9 +4,6 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running prettier --check" -./node_modules/.bin/prettier --check . - echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs index deae575..a8cdeb7 100644 --- a/scripts/utils/postprocess-files.cjs +++ b/scripts/utils/postprocess-files.cjs @@ -23,12 +23,19 @@ async function postprocess() { // strip out lib="dom", types="node", and types="react" references; these // are needed at build time, but would pollute the user's TS environment - const transformed = code.replace( + let transformed = code.replace( /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', ); + // TypeScript's declaration emitter collapses /** @ts-ignore */ onto the same + // line as the type declaration, which doesn't work. So we convert to // @ts-ignore + // on its own line to properly suppresses errors. + if (file.endsWith('.d.ts') || file.endsWith('.d.mts') || file.endsWith('.d.cts')) { + transformed = transformed.replace(/\/\*\* @ts-ignore\b[^*]*\*\/ /gm, '// @ts-ignore\n'); + } + if (transformed !== code) { console.error(`wrote ${path.relative(process.cwd(), file)}`); await fs.promises.writeFile(file, transformed, 'utf8'); diff --git a/src/api-promise.ts b/src/api-promise.ts index 4e70128..8c775ee 100644 --- a/src/api-promise.ts +++ b/src/api-promise.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/api-promise instead */ -export * from "./core/api-promise" \ No newline at end of file +export * from './core/api-promise'; diff --git a/src/client.ts b/src/client.ts index 9a9e4bf..20f90f3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -17,9 +17,29 @@ import * as Errors from './core/error'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; -import { ContextualizedEmbeddingCreateParams, ContextualizedEmbeddingCreateResponse, ContextualizedEmbeddings } from './resources/contextualized-embeddings'; +import { + ContextualizedEmbeddingCreateParams, + ContextualizedEmbeddingCreateResponse, + ContextualizedEmbeddings, +} from './resources/contextualized-embeddings'; import { EmbeddingCreateParams, EmbeddingCreateResponse, Embeddings } from './resources/embeddings'; -import { Annotation, ContentPart, ErrorInfo, FunctionCallOutputItem, FunctionTool, InputItem, OutputItem, ResponseCreateParams, ResponseCreateParamsNonStreaming, ResponseCreateParamsStreaming, ResponseCreateResponse, ResponseStreamChunk, Responses, ResponsesCreateParams, ResponsesUsage } from './resources/responses'; +import { + Annotation, + ContentPart, + ErrorInfo, + FunctionCallOutputItem, + FunctionTool, + InputItem, + OutputItem, + ResponseCreateParams, + ResponseCreateParamsNonStreaming, + ResponseCreateParamsStreaming, + ResponseCreateResponse, + ResponseStreamChunk, + Responses, + ResponsesCreateParams, + ResponsesUsage, +} from './resources/responses'; import { Search, SearchCreateParams, SearchCreateResponse } from './resources/search'; import { Async } from './resources/async/async'; import { Browser } from './resources/browser/browser'; @@ -28,7 +48,13 @@ import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { readEnv } from './internal/utils/env'; -import { type LogLevel, type Logger, formatRequestDetails, loggerFor, parseLogLevel } from './internal/utils/log'; +import { + type LogLevel, + type Logger, + formatRequestDetails, + loggerFor, + parseLogLevel, +} from './internal/utils/log'; import { isEmptyObj } from './internal/utils/values'; export interface ClientOptions { @@ -107,7 +133,7 @@ export interface ClientOptions { } /** - * API Client for interfacing with the Perplexity API. + * API Client for interfacing with the Perplexity API. */ export class Perplexity { apiKey: string; @@ -143,7 +169,7 @@ export class Perplexity { }: ClientOptions = {}) { if (apiKey === undefined) { throw new Errors.PerplexityError( - 'The PERPLEXITY_API_KEY environment variable is missing or empty; either provide it, or instantiate the Perplexity client with an apiKey option, like new Perplexity({ apiKey: \'My API Key\' }).' + "The PERPLEXITY_API_KEY environment variable is missing or empty; either provide it, or instantiate the Perplexity client with an apiKey option, like new Perplexity({ apiKey: 'My API Key' }).", ); } @@ -159,7 +185,10 @@ export class Perplexity { const defaultLogLevel = 'warn'; // Set default logLevel early so that we can log a warning in parseLogLevel. this.logLevel = defaultLogLevel; - this.logLevel = parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ?? parseLogLevel(readEnv('PERPLEXITY_LOG'), 'process.env[\'PERPLEXITY_LOG\']', this) ?? defaultLogLevel; + this.logLevel = + parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ?? + parseLogLevel(readEnv('PERPLEXITY_LOG'), "process.env['PERPLEXITY_LOG']", this) ?? + defaultLogLevel; this.fetchOptions = options.fetchOptions; this.maxRetries = options.maxRetries ?? 2; this.fetch = options.fetch ?? Shims.getDefaultFetch(); @@ -184,7 +213,7 @@ export class Perplexity { fetch: this.fetch, fetchOptions: this.fetchOptions, apiKey: this.apiKey, - ...options + ...options, }); return client; } @@ -197,7 +226,7 @@ export class Perplexity { } protected defaultQuery(): Record | undefined { - return this._options.defaultQuery + return this._options.defaultQuery; } protected validateHeaders({ values, nulls }: NullableHeaders) { @@ -232,7 +261,11 @@ export class Perplexity { return Errors.APIError.generate(status, error, message, headers); } - buildURL(path: string, query: Record | null | undefined, defaultBaseURL?: string | undefined): string { + buildURL( + path: string, + query: Record | null | undefined, + defaultBaseURL?: string | undefined, + ): string { const baseURL = (!this.#baseURLOverridden() && defaultBaseURL) || this.baseURL; const url = isAbsoluteURL(path) ? @@ -320,7 +353,9 @@ export class Perplexity { await this.prepareOptions(options); - const { req, url, timeout } = await this.buildRequest(options, { retryCount: maxRetries - retriesRemaining }); + const { req, url, timeout } = await this.buildRequest(options, { + retryCount: maxRetries - retriesRemaining, + }); await this.prepareRequest(req, { url, options }); @@ -329,7 +364,16 @@ export class Perplexity { const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`; const startTime = Date.now(); - loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({ retryOfRequestLogID, method: options.method, url, options, headers: req.headers })); + loggerFor(this).debug( + `[${requestLogID}] sending request`, + formatRequestDetails({ + retryOfRequestLogID, + method: options.method, + url, + options, + headers: req.headers, + }), + ); if (options.signal?.aborted) { throw new Errors.APIUserAbortError(); @@ -348,21 +392,45 @@ export class Perplexity { // deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)" // undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)" // others do not provide enough information to distinguish timeouts from other connection errors - const isTimeout = isAbortError(response) || /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')) + const isTimeout = + isAbortError(response) || + /timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : '')); if (retriesRemaining) { - loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`) - loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({ retryOfRequestLogID, url, durationMs: headersTime - startTime, message: response.message })); + loggerFor(this).info( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`, + ); + loggerFor(this).debug( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + }), + ); return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID); } - loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`) - loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({ retryOfRequestLogID, url, durationMs: headersTime - startTime, message: response.message })); + loggerFor(this).info( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`, + ); + loggerFor(this).debug( + `[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, + formatRequestDetails({ + retryOfRequestLogID, + url, + durationMs: headersTime - startTime, + message: response.message, + }), + ); if (isTimeout) { throw new Errors.APIConnectionTimeoutError(); } throw new Errors.APIConnectionError({ cause: response }); } - const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`; + const responseInfo = `[${requestLogID}${retryLogStr}] ${req.method} ${url} ${ + response.ok ? 'succeeded' : 'failed' + } with status ${response.status} in ${headersTime - startTime}ms`; if (!response.ok) { const shouldRetry = await this.shouldRetry(response); @@ -371,27 +439,60 @@ export class Perplexity { // We don't need the body of this response. await Shims.CancelReadableStream(response.body); - loggerFor(this).info(`${responseInfo} - ${retryMessage}`) - loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, headers: response.headers, durationMs: headersTime - startTime })); - return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers); + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); + loggerFor(this).debug( + `[${requestLogID}] response error (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + }), + ); + return this.retryRequest( + options, + retriesRemaining, + retryOfRequestLogID ?? requestLogID, + response.headers, + ); } const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`; - loggerFor(this).info(`${responseInfo} - ${retryMessage}`) + loggerFor(this).info(`${responseInfo} - ${retryMessage}`); const errText = await response.text().catch((err: any) => castToError(err).message); const errJSON = safeJSON(errText) as any; const errMessage = errJSON ? undefined : errText; - loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, headers: response.headers, message: errMessage, durationMs: Date.now() - startTime })); + loggerFor(this).debug( + `[${requestLogID}] response error (${retryMessage})`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + message: errMessage, + durationMs: Date.now() - startTime, + }), + ); const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers); throw err; } - loggerFor(this).info(responseInfo) - loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, headers: response.headers, durationMs: headersTime - startTime })); + loggerFor(this).info(responseInfo); + loggerFor(this).debug( + `[${requestLogID}] response start`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + headers: response.headers, + durationMs: headersTime - startTime, + }), + ); return { response, options, controller, requestLogID, retryOfRequestLogID, startTime }; } @@ -408,7 +509,9 @@ export class Perplexity { const timeout = setTimeout(abort, ms); - const isReadableBody = ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || (typeof options.body === "object" && options.body !== null && Symbol.asyncIterator in options.body); + const isReadableBody = + ((globalThis as any).ReadableStream && options.body instanceof (globalThis as any).ReadableStream) || + (typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body); const fetchOptions: RequestInit = { signal: controller.signal as any, @@ -423,7 +526,6 @@ export class Perplexity { } try { - // use undefined this binding; fetch errors if bound to something else in browser/cloudflare return await this.fetch.call(undefined, url, fetchOptions); } finally { @@ -524,11 +626,12 @@ export class Perplexity { const req: FinalizedRequestInit = { method, headers: reqHeaders, - ...(options.signal && { signal: options.signal}), - ...((globalThis as any).ReadableStream && body instanceof (globalThis as any).ReadableStream && { duplex: "half" }), + ...(options.signal && { signal: options.signal }), + ...((globalThis as any).ReadableStream && + body instanceof (globalThis as any).ReadableStream && { duplex: 'half' }), ...(body && { body }), - ...(this.fetchOptions as any ?? {}), - ...(options.fetchOptions as any ?? {}), + ...((this.fetchOptions as any) ?? {}), + ...((options.fetchOptions as any) ?? {}), }; return { req, url, timeout: options.timeout }; @@ -553,18 +656,19 @@ export class Perplexity { const headers = buildHeaders([ idempotencyHeaders, - {Accept: 'application/json', - 'User-Agent': this.getUserAgent(), - 'X-Stainless-Retry-Count': String(retryCount), - ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), - ...getPlatformHeaders(), + { + Accept: 'application/json', + 'User-Agent': this.getUserAgent(), + 'X-Stainless-Retry-Count': String(retryCount), + ...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}), + ...getPlatformHeaders(), 'X-Source': 'perplexity-node', 'X-Title': 'Perplexity Node SDK', }, await this.authHeaders(options), this._options.defaultHeaders, bodyHeaders, - options.headers + options.headers, ]); this.validateHeaders(headers); @@ -591,11 +695,9 @@ export class Perplexity { ArrayBuffer.isView(body) || body instanceof ArrayBuffer || body instanceof DataView || - ( - typeof body === 'string' && + (typeof body === 'string' && // Preserve legacy string encoding behavior for now - headers.values.has('content-type') - ) || + headers.values.has('content-type')) || // `Blob` is superset of `File` ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) || // `FormData` -> `multipart/form-data` @@ -626,7 +728,7 @@ export class Perplexity { } static Perplexity = this; - static DEFAULT_TIMEOUT = 900000 // 15 minutes + static DEFAULT_TIMEOUT = 900000; // 15 minutes static PerplexityError = Errors.PerplexityError; static APIError = Errors.APIError; @@ -662,69 +764,62 @@ Perplexity.Browser = Browser; Perplexity.Async = Async; export declare namespace Perplexity { - export type RequestOptions = Opts.RequestOptions; - - export { - Chat as Chat, - type StreamChunk as StreamChunk -}; - -export { - Search as Search, - type SearchCreateResponse as SearchCreateResponse, - type SearchCreateParams as SearchCreateParams -}; - -export { - Responses as Responses, - type Annotation as Annotation, - type ContentPart as ContentPart, - type ErrorInfo as ErrorInfo, - type FunctionCallOutputItem as FunctionCallOutputItem, - type FunctionTool as FunctionTool, - type InputItem as InputItem, - type OutputItem as OutputItem, - type ResponseStreamChunk as ResponseStreamChunk, - type ResponsesCreateParams as ResponsesCreateParams, - type ResponsesUsage as ResponsesUsage, - type ResponseCreateResponse as ResponseCreateResponse, - type ResponseCreateParams as ResponseCreateParams, - type ResponseCreateParamsNonStreaming as ResponseCreateParamsNonStreaming, - type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming -}; - -export { - Embeddings as Embeddings, - type EmbeddingCreateResponse as EmbeddingCreateResponse, - type EmbeddingCreateParams as EmbeddingCreateParams -}; - -export { - ContextualizedEmbeddings as ContextualizedEmbeddings, - type ContextualizedEmbeddingCreateResponse as ContextualizedEmbeddingCreateResponse, - type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams -}; - -export { - Browser as Browser -}; - -export { - Async as Async -}; - -export type APIPublicSearchResult = API.APIPublicSearchResult; -export type BrowserSessionResponse = API.BrowserSessionResponse; -export type ChatMessageInput = API.ChatMessageInput; -export type ChatMessageOutput = API.ChatMessageOutput; -export type Choice = API.Choice; -export type ContextualizedEmbeddingObject = API.ContextualizedEmbeddingObject; -export type EmbeddingObject = API.EmbeddingObject; -export type EmbeddingsUsage = API.EmbeddingsUsage; -export type JsonSchemaFormat = API.JsonSchemaFormat; -export type ResponseFormat = API.ResponseFormat; -export type SearchResult = API.SearchResult; -export type UsageInfo = API.UsageInfo; -export type UserLocation = API.UserLocation; -export type WebSearchOptions = API.WebSearchOptions; - } + export type RequestOptions = Opts.RequestOptions; + + export { Chat as Chat, type StreamChunk as StreamChunk }; + + export { + Search as Search, + type SearchCreateResponse as SearchCreateResponse, + type SearchCreateParams as SearchCreateParams, + }; + + export { + Responses as Responses, + type Annotation as Annotation, + type ContentPart as ContentPart, + type ErrorInfo as ErrorInfo, + type FunctionCallOutputItem as FunctionCallOutputItem, + type FunctionTool as FunctionTool, + type InputItem as InputItem, + type OutputItem as OutputItem, + type ResponseStreamChunk as ResponseStreamChunk, + type ResponsesCreateParams as ResponsesCreateParams, + type ResponsesUsage as ResponsesUsage, + type ResponseCreateResponse as ResponseCreateResponse, + type ResponseCreateParams as ResponseCreateParams, + type ResponseCreateParamsNonStreaming as ResponseCreateParamsNonStreaming, + type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming, + }; + + export { + Embeddings as Embeddings, + type EmbeddingCreateResponse as EmbeddingCreateResponse, + type EmbeddingCreateParams as EmbeddingCreateParams, + }; + + export { + ContextualizedEmbeddings as ContextualizedEmbeddings, + type ContextualizedEmbeddingCreateResponse as ContextualizedEmbeddingCreateResponse, + type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams, + }; + + export { Browser as Browser }; + + export { Async as Async }; + + export type APIPublicSearchResult = API.APIPublicSearchResult; + export type BrowserSessionResponse = API.BrowserSessionResponse; + export type ChatMessageInput = API.ChatMessageInput; + export type ChatMessageOutput = API.ChatMessageOutput; + export type Choice = API.Choice; + export type ContextualizedEmbeddingObject = API.ContextualizedEmbeddingObject; + export type EmbeddingObject = API.EmbeddingObject; + export type EmbeddingsUsage = API.EmbeddingsUsage; + export type JsonSchemaFormat = API.JsonSchemaFormat; + export type ResponseFormat = API.ResponseFormat; + export type SearchResult = API.SearchResult; + export type UsageInfo = API.UsageInfo; + export type UserLocation = API.UserLocation; + export type WebSearchOptions = API.WebSearchOptions; +} diff --git a/src/core/api-promise.ts b/src/core/api-promise.ts index 3cd5415..83c9de6 100644 --- a/src/core/api-promise.ts +++ b/src/core/api-promise.ts @@ -16,7 +16,10 @@ export class APIPromise extends Promise { constructor( client: Perplexity, private responsePromise: Promise, - private parseResponse: (client: Perplexity, props: APIResponseProps) => PromiseOrValue = defaultParseResponse, + private parseResponse: ( + client: Perplexity, + props: APIResponseProps, + ) => PromiseOrValue = defaultParseResponse, ) { super((resolve) => { // this is maybe a bit weird but this has to be a no-op to not implicitly @@ -28,7 +31,9 @@ export class APIPromise extends Promise { } _thenUnwrap(transform: (data: T, props: APIResponseProps) => U): APIPromise { - return new APIPromise(this.#client, this.responsePromise, async (client, props) => transform(await this.parseResponse(client, props), props)); + return new APIPromise(this.#client, this.responsePromise, async (client, props) => + transform(await this.parseResponse(client, props), props), + ); } /** diff --git a/src/core/error.ts b/src/core/error.ts index 218a66d..8932028 100644 --- a/src/core/error.ts +++ b/src/core/error.ts @@ -2,10 +2,13 @@ import { castToError } from '../internal/errors'; -export class PerplexityError extends Error { -} +export class PerplexityError extends Error {} -export class APIError extends PerplexityError { +export class APIError< + TStatus extends number | undefined = number | undefined, + THeaders extends Headers | undefined = Headers | undefined, + TError extends Object | undefined = Object | undefined, +> extends PerplexityError { /** HTTP status for the response that caused the error */ readonly status: TStatus; /** HTTP headers for the response that caused the error */ @@ -13,9 +16,6 @@ export class APIError { -} +export class BadRequestError extends APIError<400, Headers> {} -export class AuthenticationError extends APIError<401, Headers> { -} +export class AuthenticationError extends APIError<401, Headers> {} -export class PermissionDeniedError extends APIError<403, Headers> { -} +export class PermissionDeniedError extends APIError<403, Headers> {} -export class NotFoundError extends APIError<404, Headers> { -} +export class NotFoundError extends APIError<404, Headers> {} -export class ConflictError extends APIError<409, Headers> { -} +export class ConflictError extends APIError<409, Headers> {} -export class UnprocessableEntityError extends APIError<422, Headers> { -} +export class UnprocessableEntityError extends APIError<422, Headers> {} -export class RateLimitError extends APIError<429, Headers> { -} +export class RateLimitError extends APIError<429, Headers> {} -export class InternalServerError extends APIError { -} +export class InternalServerError extends APIError {} diff --git a/src/core/streaming.ts b/src/core/streaming.ts index 3f335ee..c7092c0 100644 --- a/src/core/streaming.ts +++ b/src/core/streaming.ts @@ -9,7 +9,7 @@ import { encodeUTF8 } from '../internal/utils/bytes'; import { loggerFor } from '../internal/utils/log'; import type { Perplexity } from '../client'; -import { APIError } from './error';; +import { APIError } from './error'; type Bytes = string | ArrayBuffer | Uint8Array | null | undefined; @@ -32,33 +32,33 @@ export class Stream implements AsyncIterable { this.#client = client; } - static fromSSEResponse(response: Response, -controller: AbortController, -client?: Perplexity,): Stream { + static fromSSEResponse( + response: Response, + controller: AbortController, + client?: Perplexity, + ): Stream { let consumed = false; const logger = client ? loggerFor(client) : console; async function* iterator(): AsyncIterator { if (consumed) { - throw new PerplexityError( - 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.', - ); + throw new PerplexityError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); } consumed = true; let done = false; try { for await (const sse of _iterSSEMessages(response, controller)) { if (done) continue; - + if (sse.data.startsWith('[DONE]')) { done = true; continue; } - + if (sse.event === 'error') { throw new APIError(undefined, safeJSON(sse.data) ?? sse.data, undefined, response.headers); } - + if (sse.event === null) { try { yield JSON.parse(sse.data) as Item; @@ -67,7 +67,7 @@ client?: Perplexity,): Stream { logger.error(`From chunk:`, sse.raw); throw e; } - }; + } } done = true; } catch (e) { @@ -111,9 +111,7 @@ client?: Perplexity,): Stream { async function* iterator(): AsyncIterator { if (consumed) { - throw new PerplexityError( - 'Cannot iterate over a consumed stream, use `.tee()` to split the stream.', - ); + throw new PerplexityError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); } consumed = true; let done = false; diff --git a/src/error.ts b/src/error.ts index d0832d3..fc55f46 100644 --- a/src/error.ts +++ b/src/error.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/error instead */ -export * from "./core/error" \ No newline at end of file +export * from './core/error'; diff --git a/src/index.ts b/src/index.ts index c397ccc..edad4bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,4 +5,18 @@ export { Perplexity as default } from './client'; export { type Uploadable, toFile } from './core/uploads'; export { APIPromise } from './core/api-promise'; export { Perplexity, type ClientOptions } from './client'; -export { PerplexityError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError } from './core/error'; +export { + PerplexityError, + APIError, + APIConnectionError, + APIConnectionTimeoutError, + APIUserAbortError, + NotFoundError, + ConflictError, + RateLimitError, + BadRequestError, + AuthenticationError, + InternalServerError, + PermissionDeniedError, + UnprocessableEntityError, +} from './core/error'; diff --git a/src/internal/builtin-types.ts b/src/internal/builtin-types.ts index 6059d5d..c23d3bd 100644 --- a/src/internal/builtin-types.ts +++ b/src/internal/builtin-types.ts @@ -1,23 +1,20 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export type Fetch = ( - input: string | URL | Request, - init?: RequestInit, -) => Promise +export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise; /** * An alias to the builtin `RequestInit` type so we can * easily alias it in import statements if there are name clashes. - * - * https://developer.mozilla.org/docs/Web/API/RequestInit + * + * https://developer.mozilla.org/docs/Web/API/RequestInit */ type _RequestInit = RequestInit; /** * An alias to the builtin `Response` type so we can * easily alias it in import statements if there are name clashes. - * - * https://developer.mozilla.org/docs/Web/API/Response + * + * https://developer.mozilla.org/docs/Web/API/Response */ type _Response = Response; @@ -54,7 +51,15 @@ type _Array = Array; */ type _Record = Record; -export type { _Array as Array, _BodyInit as BodyInit, _HeadersInit as HeadersInit, _Record as Record, _RequestInfo as RequestInfo, _RequestInit as RequestInit, _Response as Response }; +export type { + _Array as Array, + _BodyInit as BodyInit, + _HeadersInit as HeadersInit, + _Record as Record, + _RequestInfo as RequestInfo, + _RequestInit as RequestInit, + _Response as Response, +}; /** * A copy of the builtin `EndingType` type as it isn't fully supported in certain diff --git a/src/internal/detect-platform.ts b/src/internal/detect-platform.ts index 394ede8..e82d95c 100644 --- a/src/internal/detect-platform.ts +++ b/src/internal/detect-platform.ts @@ -25,7 +25,11 @@ function getDetectedPlatform(): DetectedPlatform { if (typeof EdgeRuntime !== 'undefined') { return 'edge'; } - if (Object.prototype.toString.call(typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0) === '[object process]') { + if ( + Object.prototype.toString.call( + typeof (globalThis as any).process !== 'undefined' ? (globalThis as any).process : 0, + ) === '[object process]' + ) { return 'node'; } return 'unknown'; diff --git a/src/internal/errors.ts b/src/internal/errors.ts index c14a742..82c7b14 100644 --- a/src/internal/errors.ts +++ b/src/internal/errors.ts @@ -2,12 +2,12 @@ export function isAbortError(err: unknown) { return ( - typeof err === 'object' && err !== null && ( - // Spec-compliant fetch implementations - ('name' in err && (err as any).name === 'AbortError') || + typeof err === 'object' && + err !== null && + // Spec-compliant fetch implementations + (('name' in err && (err as any).name === 'AbortError') || // Expo fetch - ('message' in err && String((err as any).message).includes('FetchRequestCanceledException')) - ) + ('message' in err && String((err as any).message).includes('FetchRequestCanceledException'))) ); } @@ -24,10 +24,10 @@ export const castToError = (err: any): Error => { if (err.name) error.name = err.name; return error; } - } catch { } + } catch {} try { return new Error(JSON.stringify(err)); - } catch { } + } catch {} } return new Error(err); }; diff --git a/src/internal/headers.ts b/src/internal/headers.ts index fa2ea2b..c724a9d 100644 --- a/src/internal/headers.ts +++ b/src/internal/headers.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { isReadonlyArray } from "./utils/values"; +import { isReadonlyArray } from './utils/values'; type HeaderValue = string | undefined | null; export type HeadersLike = @@ -51,7 +51,7 @@ function* iterateHeaders(headers: HeadersLike): IterableIterator(client: Perplexity, props: APIResp const text = await response.text(); return text as unknown as T; })(); - loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({ retryOfRequestLogID, url: response.url, status: response.status, body, durationMs: Date.now() - startTime })); + loggerFor(client).debug( + `[${requestLogID}] response parsed`, + formatRequestDetails({ + retryOfRequestLogID, + url: response.url, + status: response.status, + body, + durationMs: Date.now() - startTime, + }), + ); return body; } diff --git a/src/internal/request-options.ts b/src/internal/request-options.ts index 0a02e61..56765e5 100644 --- a/src/internal/request-options.ts +++ b/src/internal/request-options.ts @@ -77,14 +77,11 @@ export type RequestOptions = { defaultBaseURL?: string | undefined; __binaryResponse?: boolean | undefined; - __streamClass?: typeof Stream + __streamClass?: typeof Stream; }; export type EncodedContent = { bodyHeaders: HeadersLike; body: BodyInit }; -export type RequestEncoder = (request: { - headers: NullableHeaders; - body: unknown; -}) => EncodedContent; +export type RequestEncoder = (request: { headers: NullableHeaders; body: unknown }) => EncodedContent; export const FallbackEncoder: RequestEncoder = ({ headers, body }) => { return { diff --git a/src/internal/shim-types.ts b/src/internal/shim-types.ts index accbf57..8ddf7b0 100644 --- a/src/internal/shim-types.ts +++ b/src/internal/shim-types.ts @@ -19,8 +19,8 @@ type _ConditionalNodeReadableStream = typeof globalThis extends { ReadableStream: any } ? never : _NodeReadableStream; type _ReadableStream = NeverToAny< - ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) | - ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) + | ([0] extends [1 & _DOMReadableStream] ? never : _DOMReadableStream) + | ([0] extends [1 & _ConditionalNodeReadableStream] ? never : _ConditionalNodeReadableStream) >; export type { _ReadableStream as ReadableStream }; diff --git a/src/internal/shims.ts b/src/internal/shims.ts index 94c7086..ba237db 100644 --- a/src/internal/shims.ts +++ b/src/internal/shims.ts @@ -27,7 +27,9 @@ export function makeReadableStream(...args: ReadableStreamArgs): ReadableStream if (typeof ReadableStream === 'undefined') { // Note: All of the platforms / runtimes we officially support already define // `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes. - throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`'); + throw new Error( + '`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`', + ); } return new ReadableStream(...args); diff --git a/src/internal/to-file.ts b/src/internal/to-file.ts index c72a2b4..30eada3 100644 --- a/src/internal/to-file.ts +++ b/src/internal/to-file.ts @@ -1,4 +1,4 @@ -import { BlobPart, getName, makeFile, isAsyncIterable } from "./uploads"; +import { BlobPart, getName, makeFile, isAsyncIterable } from './uploads'; import type { FilePropertyBag } from './builtin-types'; import { checkFileSupport } from './uploads'; @@ -65,8 +65,11 @@ const isResponseLike = (value: any): value is ResponseLike => typeof value.url === 'string' && typeof value.blob === 'function'; -export type ToFileInput = FileLike | ResponseLike | Exclude | AsyncIterable; - +export type ToFileInput = + | FileLike + | ResponseLike + | Exclude + | AsyncIterable; /** * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats @@ -116,9 +119,7 @@ export async function toFile( return makeFile(parts, name, options); } -async function getBytes( - value: BlobLikePart | AsyncIterable, -): Promise> { +async function getBytes(value: BlobLikePart | AsyncIterable): Promise> { let parts: Array = []; if ( typeof value === 'string' || @@ -151,4 +152,3 @@ function propsForError(value: unknown): string { const props = Object.getOwnPropertyNames(value); return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`; } - diff --git a/src/internal/types.ts b/src/internal/types.ts index c45fee3..b668dfc 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -7,34 +7,40 @@ export type KeysEnum = { [P in keyof Required]: true }; export type FinalizedRequestInit = RequestInit & { headers: Headers }; -type NotAny = [0] extends [(1 & T)] ? never : T; +type NotAny = [0] extends [1 & T] ? never : T; /** * Some environments overload the global fetch function, and Parameters only gets the last signature. */ -type OverloadedParameters = T extends { - (...args: infer A): unknown; - (...args: infer B): unknown; - (...args: infer C): unknown; - (...args: infer D): unknown; -} - ? A | B | C | D - : T extends { +type OverloadedParameters = + T extends ( + { (...args: infer A): unknown; (...args: infer B): unknown; (...args: infer C): unknown; + (...args: infer D): unknown; } - ? A | B | C - : T extends { + ) ? + A | B | C | D + : T extends ( + { + (...args: infer A): unknown; + (...args: infer B): unknown; + (...args: infer C): unknown; + } + ) ? + A | B | C + : T extends ( + { (...args: infer A): unknown; (...args: infer B): unknown; } - ? A | B - : T extends (...args: infer A) => unknown - ? A + ) ? + A | B + : T extends (...args: infer A) => unknown ? A : never; - +/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -57,19 +63,19 @@ type OverloadedParameters = T extends { * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ +/** @ts-ignore For users with \@types/node */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ /* prettier-ignore */ +/** @ts-ignore For users with undici */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ +/** @ts-ignore For users with \@types/bun */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ +/** @ts-ignore For users with node-fetch@2 */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ /* prettier-ignore */ +/** @ts-ignore For users who use Deno */ type FetchRequestInit = NonNullable[1]>; - +/* eslint-enable */ type RequestInits = | NotAny diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index 4739f95..c8062b7 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -4,7 +4,7 @@ import { hasOwn } from './values'; import { type Perplexity } from '../../client'; import { RequestOptions } from '../request-options'; -type LogFn = (message: string, ...rest: unknown[]) => void +type LogFn = (message: string, ...rest: unknown[]) => void; export type Logger = { error: LogFn; warn: LogFn; @@ -21,14 +21,22 @@ const levelNumbers = { debug: 500, }; -export const parseLogLevel = (maybeLevel: string | undefined, sourceName: string, client: Perplexity): LogLevel | undefined => { +export const parseLogLevel = ( + maybeLevel: string | undefined, + sourceName: string, + client: Perplexity, +): LogLevel | undefined => { if (!maybeLevel) { return undefined; } if (hasOwn(levelNumbers, maybeLevel)) { return maybeLevel; - }; - loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); + } + loggerFor(client).warn( + `${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify( + Object.keys(levelNumbers), + )}`, + ); return undefined; }; @@ -89,11 +97,24 @@ export const formatRequestDetails = (details: { body?: unknown; }) => { if (details.options) { - details.options = {...details.options}; + details.options = { ...details.options }; delete details.options['headers']; // redundant + leaks internals } if (details.headers) { - details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [name, name.toLowerCase() === 'authorization' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ? '***' : value])) + details.headers = Object.fromEntries( + (details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map( + ([name, value]) => [ + name, + ( + name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'cookie' || + name.toLowerCase() === 'set-cookie' + ) ? + '***' + : value, + ], + ), + ); } if ('retryOfRequestLogID' in details) { if (details.retryOfRequestLogID) { @@ -101,5 +122,5 @@ export const formatRequestDetails = (details: { } delete details.retryOfRequestLogID; } - return details -} + return details; +}; diff --git a/src/internal/utils/uuid.ts b/src/internal/utils/uuid.ts index 53708ba..b0e53aa 100644 --- a/src/internal/utils/uuid.ts +++ b/src/internal/utils/uuid.ts @@ -10,10 +10,8 @@ export let uuid4 = function () { return crypto.randomUUID(); } const u8 = new Uint8Array(1); - const randomByte = crypto - ? () => crypto.getRandomValues(u8)[0]! - : () => (Math.random() * 0xff) & 0xff; - return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => + const randomByte = crypto ? () => crypto.getRandomValues(u8)[0]! : () => (Math.random() * 0xff) & 0xff; + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16), ); -} +}; diff --git a/src/resource.ts b/src/resource.ts index 57a27a9..363e351 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/resource instead */ -export * from "./core/resource" \ No newline at end of file +export * from './core/resource'; diff --git a/src/resources/async/async.ts b/src/resources/async/async.ts index d2c011c..00208d2 100644 --- a/src/resources/async/async.ts +++ b/src/resources/async/async.ts @@ -11,7 +11,5 @@ export class Async extends APIResource { Async.Chat = Chat; export declare namespace Async { - export { - Chat as Chat - }; + export { Chat as Chat }; } diff --git a/src/resources/async/chat/chat.ts b/src/resources/async/chat/chat.ts index 9da82d5..f593341 100644 --- a/src/resources/async/chat/chat.ts +++ b/src/resources/async/chat/chat.ts @@ -2,7 +2,14 @@ import { APIResource } from '../../../core/resource'; import * as CompletionsAPI from './completions'; -import { CompletionCreateParams, CompletionCreateResponse, CompletionGetParams, CompletionGetResponse, CompletionListResponse, Completions } from './completions'; +import { + CompletionCreateParams, + CompletionCreateResponse, + CompletionGetParams, + CompletionGetResponse, + CompletionListResponse, + Completions, +} from './completions'; export class Chat extends APIResource { completions: CompletionsAPI.Completions = new CompletionsAPI.Completions(this._client); @@ -17,6 +24,6 @@ export declare namespace Chat { type CompletionListResponse as CompletionListResponse, type CompletionGetResponse as CompletionGetResponse, type CompletionCreateParams as CompletionCreateParams, - type CompletionGetParams as CompletionGetParams + type CompletionGetParams as CompletionGetParams, }; } diff --git a/src/resources/async/chat/completions.ts b/src/resources/async/chat/completions.ts index 5b4fbd5..787240a 100644 --- a/src/resources/async/chat/completions.ts +++ b/src/resources/async/chat/completions.ts @@ -26,9 +26,37 @@ export class Completions extends APIResource { /** * Retrieve the response for a given asynchronous chat completion request. */ - get(apiRequest: string, params: CompletionGetParams | null | undefined = {}, options?: RequestOptions): APIPromise { - const { 'x-client-env': xClientEnv, 'x-client-name': xClientName, 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds, 'x-request-time': xRequestTime, 'x-usage-tier': xUsageTier, 'x-user-id': xUserID, ...query } = params ?? {} - return this._client.get(path`/async/chat/completions/${apiRequest}`, { query, ...options, headers: buildHeaders([{...(xClientEnv != null ? { 'x-client-env': xClientEnv } : undefined), ...(xClientName != null ? { 'x-client-name': xClientName } : undefined), ...(xCreatedAtEpochSeconds != null ? { 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds } : undefined), ...(xRequestTime != null ? { 'x-request-time': xRequestTime } : undefined), ...(xUsageTier != null ? { 'x-usage-tier': xUsageTier } : undefined), ...(xUserID != null ? { 'x-user-id': xUserID } : undefined)}, options?.headers]) }); + get( + apiRequest: string, + params: CompletionGetParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + const { + 'x-client-env': xClientEnv, + 'x-client-name': xClientName, + 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds, + 'x-request-time': xRequestTime, + 'x-usage-tier': xUsageTier, + 'x-user-id': xUserID, + ...query + } = params ?? {}; + return this._client.get(path`/async/chat/completions/${apiRequest}`, { + query, + ...options, + headers: buildHeaders([ + { + ...(xClientEnv != null ? { 'x-client-env': xClientEnv } : undefined), + ...(xClientName != null ? { 'x-client-name': xClientName } : undefined), + ...(xCreatedAtEpochSeconds != null ? + { 'x-created-at-epoch-seconds': xCreatedAtEpochSeconds } + : undefined), + ...(xRequestTime != null ? { 'x-request-time': xRequestTime } : undefined), + ...(xUsageTier != null ? { 'x-usage-tier': xUsageTier } : undefined), + ...(xUserID != null ? { 'x-user-id': xUserID } : undefined), + }, + options?.headers, + ]), + }); } } @@ -175,7 +203,11 @@ export namespace CompletionCreateParams { reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high' | null; - response_format?: Request.ResponseFormatText | Request.ResponseFormatJsonSchema | Request.ResponseFormatRegex | null; + response_format?: + | Request.ResponseFormatText + | Request.ResponseFormatJsonSchema + | Request.ResponseFormatRegex + | null; response_metadata?: { [key: string]: unknown } | null; @@ -348,6 +380,6 @@ export declare namespace Completions { type CompletionListResponse as CompletionListResponse, type CompletionGetResponse as CompletionGetResponse, type CompletionCreateParams as CompletionCreateParams, - type CompletionGetParams as CompletionGetParams + type CompletionGetParams as CompletionGetParams, }; } diff --git a/src/resources/async/chat/index.ts b/src/resources/async/chat/index.ts index 102fc9c..0f5e81e 100644 --- a/src/resources/async/chat/index.ts +++ b/src/resources/async/chat/index.ts @@ -1,4 +1,11 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Chat } from './chat';; -export { Completions, type CompletionCreateResponse, type CompletionListResponse, type CompletionGetResponse, type CompletionCreateParams, type CompletionGetParams } from './completions';; +export { Chat } from './chat'; +export { + Completions, + type CompletionCreateResponse, + type CompletionListResponse, + type CompletionGetResponse, + type CompletionCreateParams, + type CompletionGetParams, +} from './completions'; diff --git a/src/resources/async/index.ts b/src/resources/async/index.ts index f6ff95a..628a398 100644 --- a/src/resources/async/index.ts +++ b/src/resources/async/index.ts @@ -1,4 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Async } from './async';; -export { Chat } from './chat/index';; +export { Async } from './async'; +export { Chat } from './chat/index'; diff --git a/src/resources/browser/browser.ts b/src/resources/browser/browser.ts index a5c90ce..f854818 100644 --- a/src/resources/browser/browser.ts +++ b/src/resources/browser/browser.ts @@ -11,8 +11,5 @@ export class Browser extends APIResource { Browser.Sessions = Sessions; export declare namespace Browser { - export { - Sessions as Sessions, - type SessionCreateParams as SessionCreateParams - }; + export { Sessions as Sessions, type SessionCreateParams as SessionCreateParams }; } diff --git a/src/resources/browser/index.ts b/src/resources/browser/index.ts index a617b4d..6084119 100644 --- a/src/resources/browser/index.ts +++ b/src/resources/browser/index.ts @@ -1,4 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Browser } from './browser';; -export { Sessions, type SessionCreateParams } from './sessions';; +export { Browser } from './browser'; +export { Sessions, type SessionCreateParams } from './sessions'; diff --git a/src/resources/browser/sessions.ts b/src/resources/browser/sessions.ts index 5828dba..14c551f 100644 --- a/src/resources/browser/sessions.ts +++ b/src/resources/browser/sessions.ts @@ -11,7 +11,10 @@ export class Sessions extends APIResource { /** * Create a new remote browser session for CDP-based automation. */ - create(body?: SessionCreateParams | null | undefined, options?: RequestOptions): APIPromise { + create( + body?: SessionCreateParams | null | undefined, + options?: RequestOptions, + ): APIPromise { return this._client.post('/v1/browser/sessions', { body, ...options }); } @@ -19,15 +22,15 @@ export class Sessions extends APIResource { * Stop and clean up a remote browser session. */ delete(sessionID: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/v1/browser/sessions/${sessionID}`, { ...options, headers: buildHeaders([{Accept: '*/*'}, options?.headers]) }); + return this._client.delete(path`/v1/browser/sessions/${sessionID}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); } } -export interface SessionCreateParams { -} +export interface SessionCreateParams {} export declare namespace Sessions { - export { - type SessionCreateParams as SessionCreateParams - }; + export { type SessionCreateParams as SessionCreateParams }; } diff --git a/src/resources/chat/chat.ts b/src/resources/chat/chat.ts index b03d9ac..952dc2e 100644 --- a/src/resources/chat/chat.ts +++ b/src/resources/chat/chat.ts @@ -3,7 +3,12 @@ import { APIResource } from '../../core/resource'; import * as Shared from '../shared'; import * as CompletionsAPI from './completions'; -import { CompletionCreateParams, CompletionCreateParamsNonStreaming, CompletionCreateParamsStreaming, Completions } from './completions'; +import { + CompletionCreateParams, + CompletionCreateParamsNonStreaming, + CompletionCreateParamsStreaming, + Completions, +} from './completions'; export class Chat extends APIResource { completions: CompletionsAPI.Completions = new CompletionsAPI.Completions(this._client); @@ -34,14 +39,12 @@ export interface StreamChunk { Chat.Completions = Completions; export declare namespace Chat { - export { - type StreamChunk as StreamChunk - }; + export { type StreamChunk as StreamChunk }; export { Completions as Completions, type CompletionCreateParams as CompletionCreateParams, type CompletionCreateParamsNonStreaming as CompletionCreateParamsNonStreaming, - type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming + type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming, }; } diff --git a/src/resources/chat/completions.ts b/src/resources/chat/completions.ts index 25bc1f7..225d8fd 100644 --- a/src/resources/chat/completions.ts +++ b/src/resources/chat/completions.ts @@ -12,15 +12,26 @@ export class Completions extends APIResource { /** * Generate a chat completion response for the given conversation. */ - create(body: CompletionCreateParamsNonStreaming, options?: RequestOptions): APIPromise - create(body: CompletionCreateParamsStreaming, options?: RequestOptions): APIPromise> - create(body: CompletionCreateParamsBase, options?: RequestOptions): APIPromise | ChatAPI.StreamChunk> - create(body: CompletionCreateParams, options?: RequestOptions): APIPromise | APIPromise> { - return this._client.post('/chat/completions', { body, ...options, stream: body.stream ?? false }) as APIPromise | APIPromise>; + create(body: CompletionCreateParamsNonStreaming, options?: RequestOptions): APIPromise; + create( + body: CompletionCreateParamsStreaming, + options?: RequestOptions, + ): APIPromise>; + create( + body: CompletionCreateParamsBase, + options?: RequestOptions, + ): APIPromise | ChatAPI.StreamChunk>; + create( + body: CompletionCreateParams, + options?: RequestOptions, + ): APIPromise | APIPromise> { + return this._client.post('/chat/completions', { body, ...options, stream: body.stream ?? false }) as + | APIPromise + | APIPromise>; } } -export type CompletionCreateParams = CompletionCreateParamsNonStreaming | CompletionCreateParamsStreaming +export type CompletionCreateParams = CompletionCreateParamsNonStreaming | CompletionCreateParamsStreaming; export interface CompletionCreateParamsBase { messages: Array; @@ -85,7 +96,11 @@ export interface CompletionCreateParamsBase { reasoning_effort?: 'minimal' | 'low' | 'medium' | 'high' | null; - response_format?: CompletionCreateParams.ResponseFormatText | CompletionCreateParams.ResponseFormatJsonSchema | CompletionCreateParams.ResponseFormatRegex | null; + response_format?: + | CompletionCreateParams.ResponseFormatText + | CompletionCreateParams.ResponseFormatJsonSchema + | CompletionCreateParams.ResponseFormatRegex + | null; response_metadata?: { [key: string]: unknown } | null; @@ -213,8 +228,8 @@ export namespace CompletionCreateParams { } } - export type CompletionCreateParamsNonStreaming = CompletionsAPI.CompletionCreateParamsNonStreaming - export type CompletionCreateParamsStreaming = CompletionsAPI.CompletionCreateParamsStreaming + export type CompletionCreateParamsNonStreaming = CompletionsAPI.CompletionCreateParamsNonStreaming; + export type CompletionCreateParamsStreaming = CompletionsAPI.CompletionCreateParamsStreaming; } export interface CompletionCreateParamsNonStreaming extends CompletionCreateParamsBase { @@ -229,6 +244,6 @@ export declare namespace Completions { export { type CompletionCreateParams as CompletionCreateParams, type CompletionCreateParamsNonStreaming as CompletionCreateParamsNonStreaming, - type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming + type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming, }; } diff --git a/src/resources/chat/index.ts b/src/resources/chat/index.ts index 8fd7656..1a4bddc 100644 --- a/src/resources/chat/index.ts +++ b/src/resources/chat/index.ts @@ -1,4 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Chat, type StreamChunk } from './chat';; -export { Completions, type CompletionCreateParams, type CompletionCreateParamsNonStreaming, type CompletionCreateParamsStreaming } from './completions';; +export { Chat, type StreamChunk } from './chat'; +export { + Completions, + type CompletionCreateParams, + type CompletionCreateParamsNonStreaming, + type CompletionCreateParamsStreaming, +} from './completions'; diff --git a/src/resources/contextualized-embeddings.ts b/src/resources/contextualized-embeddings.ts index f386c53..231f25a 100644 --- a/src/resources/contextualized-embeddings.ts +++ b/src/resources/contextualized-embeddings.ts @@ -11,7 +11,10 @@ export class ContextualizedEmbeddings extends APIResource { * document share context awareness, improving retrieval quality for document-based * applications. */ - create(body: ContextualizedEmbeddingCreateParams, options?: RequestOptions): APIPromise { + create( + body: ContextualizedEmbeddingCreateParams, + options?: RequestOptions, + ): APIPromise { return this._client.post('/v1/contextualizedembeddings', { body, ...options }); } } @@ -75,6 +78,6 @@ export interface ContextualizedEmbeddingCreateParams { export declare namespace ContextualizedEmbeddings { export { type ContextualizedEmbeddingCreateResponse as ContextualizedEmbeddingCreateResponse, - type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams + type ContextualizedEmbeddingCreateParams as ContextualizedEmbeddingCreateParams, }; } diff --git a/src/resources/embeddings.ts b/src/resources/embeddings.ts index c1c0a42..73abb51 100644 --- a/src/resources/embeddings.ts +++ b/src/resources/embeddings.ts @@ -71,6 +71,6 @@ export interface EmbeddingCreateParams { export declare namespace Embeddings { export { type EmbeddingCreateResponse as EmbeddingCreateResponse, - type EmbeddingCreateParams as EmbeddingCreateParams + type EmbeddingCreateParams as EmbeddingCreateParams, }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 93dc8fb..29654c9 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,10 +1,30 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './shared';; -export { Async } from './async/async';; -export { Browser } from './browser/browser';; -export { Chat, type StreamChunk } from './chat/chat';; -export { ContextualizedEmbeddings, type ContextualizedEmbeddingCreateResponse, type ContextualizedEmbeddingCreateParams } from './contextualized-embeddings';; -export { Embeddings, type EmbeddingCreateResponse, type EmbeddingCreateParams } from './embeddings';; -export { Responses, type Annotation, type ContentPart, type ErrorInfo, type FunctionCallOutputItem, type FunctionTool, type InputItem, type OutputItem, type ResponseStreamChunk, type ResponsesCreateParams, type ResponsesUsage, type ResponseCreateResponse, type ResponseCreateParams, type ResponseCreateParamsNonStreaming, type ResponseCreateParamsStreaming } from './responses';; -export { Search, type SearchCreateResponse, type SearchCreateParams } from './search';; +export * from './shared'; +export { Async } from './async/async'; +export { Browser } from './browser/browser'; +export { Chat, type StreamChunk } from './chat/chat'; +export { + ContextualizedEmbeddings, + type ContextualizedEmbeddingCreateResponse, + type ContextualizedEmbeddingCreateParams, +} from './contextualized-embeddings'; +export { Embeddings, type EmbeddingCreateResponse, type EmbeddingCreateParams } from './embeddings'; +export { + Responses, + type Annotation, + type ContentPart, + type ErrorInfo, + type FunctionCallOutputItem, + type FunctionTool, + type InputItem, + type OutputItem, + type ResponseStreamChunk, + type ResponsesCreateParams, + type ResponsesUsage, + type ResponseCreateResponse, + type ResponseCreateParams, + type ResponseCreateParamsNonStreaming, + type ResponseCreateParamsStreaming, +} from './responses'; +export { Search, type SearchCreateResponse, type SearchCreateParams } from './search'; diff --git a/src/resources/responses.ts b/src/resources/responses.ts index 42d4f10..5b7c45c 100644 --- a/src/resources/responses.ts +++ b/src/resources/responses.ts @@ -13,10 +13,22 @@ export class Responses extends APIResource { * Generate a response for the provided input with optional web search and * reasoning. */ - create(body: ResponseCreateParamsNonStreaming, options?: RequestOptions): APIPromise - create(body: ResponseCreateParamsStreaming, options?: RequestOptions): APIPromise> - create(body: ResponseCreateParamsBase, options?: RequestOptions): APIPromise | ResponseCreateResponse> - create(body: ResponseCreateParams, options?: RequestOptions): APIPromise | APIPromise> { + create( + body: ResponseCreateParamsNonStreaming, + options?: RequestOptions, + ): APIPromise; + create( + body: ResponseCreateParamsStreaming, + options?: RequestOptions, + ): APIPromise>; + create( + body: ResponseCreateParamsBase, + options?: RequestOptions, + ): APIPromise | ResponseCreateResponse>; + create( + body: ResponseCreateParams, + options?: RequestOptions, + ): APIPromise | APIPromise> { const promise = this._client.post('/v1/responses', { body, ...options, stream: body.stream ?? false }); // For non-streaming responses, automatically add output_text property @@ -119,7 +131,10 @@ export interface FunctionTool { strict?: boolean; } -export type InputItem = InputItem.InputMessage | InputItem.FunctionCallOutputInput | InputItem.FunctionCallInput +export type InputItem = + | InputItem.InputMessage + | InputItem.FunctionCallOutputInput + | InputItem.FunctionCallInput; export namespace InputItem { export interface InputMessage { @@ -192,7 +207,11 @@ export namespace InputItem { } } -export type OutputItem = OutputItem.MessageOutputItem | OutputItem.SearchResultsOutputItem | OutputItem.FetchURLResultsOutputItem | FunctionCallOutputItem +export type OutputItem = + | OutputItem.MessageOutputItem + | OutputItem.SearchResultsOutputItem + | OutputItem.FetchURLResultsOutputItem + | FunctionCallOutputItem; export namespace OutputItem { export interface MessageOutputItem { @@ -268,7 +287,21 @@ export namespace OutputItem { * - `response.reasoning.fetch_url_results`: URL fetch results received * - `response.reasoning.stopped`: Reasoning phase complete */ -export type ResponseStreamChunk = ResponseStreamChunk.ResponseCreatedEvent | ResponseStreamChunk.ResponseInProgressEvent | ResponseStreamChunk.ResponseCompletedEvent | ResponseStreamChunk.ResponseFailedEvent | ResponseStreamChunk.OutputItemAddedEvent | ResponseStreamChunk.OutputItemDoneEvent | ResponseStreamChunk.TextDeltaEvent | ResponseStreamChunk.TextDoneEvent | ResponseStreamChunk.ReasoningStartedEvent | ResponseStreamChunk.SearchQueriesEvent | ResponseStreamChunk.SearchResultsEvent | ResponseStreamChunk.FetchURLQueriesEvent | ResponseStreamChunk.FetchURLResultsEvent | ResponseStreamChunk.ReasoningStoppedEvent +export type ResponseStreamChunk = + | ResponseStreamChunk.ResponseCreatedEvent + | ResponseStreamChunk.ResponseInProgressEvent + | ResponseStreamChunk.ResponseCompletedEvent + | ResponseStreamChunk.ResponseFailedEvent + | ResponseStreamChunk.OutputItemAddedEvent + | ResponseStreamChunk.OutputItemDoneEvent + | ResponseStreamChunk.TextDeltaEvent + | ResponseStreamChunk.TextDoneEvent + | ResponseStreamChunk.ReasoningStartedEvent + | ResponseStreamChunk.SearchQueriesEvent + | ResponseStreamChunk.SearchResultsEvent + | ResponseStreamChunk.FetchURLQueriesEvent + | ResponseStreamChunk.FetchURLResultsEvent + | ResponseStreamChunk.ReasoningStoppedEvent; export namespace ResponseStreamChunk { /** @@ -284,7 +317,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; /** * Non-streaming response returned when stream is false @@ -334,7 +381,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; /** * Non-streaming response returned when stream is false @@ -383,7 +444,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; /** * Non-streaming response returned when stream is false @@ -435,7 +510,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; } /** @@ -455,7 +544,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; } /** @@ -475,7 +578,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; } /** @@ -499,7 +616,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; } /** @@ -523,7 +654,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; } /** @@ -539,7 +684,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; thought?: string; } @@ -559,7 +718,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; thought?: string; } @@ -579,7 +752,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; thought?: string; @@ -599,7 +786,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; urls: Array; @@ -621,7 +822,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; thought?: string; } @@ -661,7 +876,21 @@ export namespace ResponseStreamChunk { /** * SSE event type discriminator */ - type: 'response.created' | 'response.in_progress' | 'response.completed' | 'response.failed' | 'response.output_item.added' | 'response.output_item.done' | 'response.output_text.delta' | 'response.output_text.done' | 'response.reasoning.started' | 'response.reasoning.search_queries' | 'response.reasoning.search_results' | 'response.reasoning.fetch_url_queries' | 'response.reasoning.fetch_url_results' | 'response.reasoning.stopped'; + type: + | 'response.created' + | 'response.in_progress' + | 'response.completed' + | 'response.failed' + | 'response.output_item.added' + | 'response.output_item.done' + | 'response.output_text.delta' + | 'response.output_text.done' + | 'response.reasoning.started' + | 'response.reasoning.search_queries' + | 'response.reasoning.search_results' + | 'response.reasoning.fetch_url_queries' + | 'response.reasoning.fetch_url_results' + | 'response.reasoning.stopped'; thought?: string; } @@ -894,7 +1123,7 @@ export interface ResponseCreateResponse { output_text?: string; } -export type ResponseCreateParams = ResponseCreateParamsNonStreaming | ResponseCreateParamsStreaming +export type ResponseCreateParams = ResponseCreateParamsNonStreaming | ResponseCreateParamsStreaming; export interface ResponseCreateParamsBase { /** @@ -1041,8 +1270,8 @@ export namespace ResponseCreateParams { max_urls?: number; } - export type ResponseCreateParamsNonStreaming = ResponsesAPI.ResponseCreateParamsNonStreaming - export type ResponseCreateParamsStreaming = ResponsesAPI.ResponseCreateParamsStreaming + export type ResponseCreateParamsNonStreaming = ResponsesAPI.ResponseCreateParamsNonStreaming; + export type ResponseCreateParamsStreaming = ResponsesAPI.ResponseCreateParamsStreaming; } export interface ResponseCreateParamsNonStreaming extends ResponseCreateParamsBase { @@ -1074,6 +1303,6 @@ export declare namespace Responses { type ResponseCreateResponse as ResponseCreateResponse, type ResponseCreateParams as ResponseCreateParams, type ResponseCreateParamsNonStreaming as ResponseCreateParamsNonStreaming, - type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming + type ResponseCreateParamsStreaming as ResponseCreateParamsStreaming, }; } diff --git a/src/resources/search.ts b/src/resources/search.ts index 0385cbf..3465db6 100644 --- a/src/resources/search.ts +++ b/src/resources/search.ts @@ -66,8 +66,5 @@ export interface SearchCreateParams { } export declare namespace Search { - export { - type SearchCreateResponse as SearchCreateResponse, - type SearchCreateParams as SearchCreateParams - }; + export { type SearchCreateResponse as SearchCreateResponse, type SearchCreateParams as SearchCreateParams }; } diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 6868e0e..ee49414 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -32,7 +32,16 @@ export interface BrowserSessionResponse { } export interface ChatMessageInput { - content: string | Array | null; + content: + | string + | Array< + | ChatMessageInput.ChatMessageContentTextChunk + | ChatMessageInput.ChatMessageContentImageChunk + | ChatMessageInput.ChatMessageContentFileChunk + | ChatMessageInput.ChatMessageContentPdfChunk + | ChatMessageInput.ChatMessageContentVideoChunk + > + | null; /** * Chat roles enum @@ -174,7 +183,16 @@ export namespace ChatMessageInput { } export interface ChatMessageOutput { - content: string | Array | null; + content: + | string + | Array< + | ChatMessageOutput.ChatMessageContentTextChunk + | ChatMessageOutput.ChatMessageContentImageChunk + | ChatMessageOutput.ChatMessageContentFileChunk + | ChatMessageOutput.ChatMessageContentPdfChunk + | ChatMessageOutput.ChatMessageContentVideoChunk + > + | null; /** * Chat roles enum diff --git a/src/streaming.ts b/src/streaming.ts index 1708536..9e6da10 100644 --- a/src/streaming.ts +++ b/src/streaming.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/streaming instead */ -export * from "./core/streaming" \ No newline at end of file +export * from './core/streaming'; diff --git a/src/uploads.ts b/src/uploads.ts index d543708..b2ef647 100644 --- a/src/uploads.ts +++ b/src/uploads.ts @@ -1,2 +1,2 @@ /** @deprecated Import from ./core/uploads instead */ -export * from "./core/uploads" \ No newline at end of file +export * from './core/uploads'; diff --git a/src/version.ts b/src/version.ts index da70f84..288031c 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.27.0';// x-release-please-version +export const VERSION = '0.27.0'; // x-release-please-version diff --git a/tests/api-resources/async/chat/completions.test.ts b/tests/api-resources/async/chat/completions.test.ts index 07b0415..429241a 100644 --- a/tests/api-resources/async/chat/completions.test.ts +++ b/tests/api-resources/async/chat/completions.test.ts @@ -2,12 +2,17 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource completions', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.async.chat.completions.create({ request: { messages: [{ content: 'string', role: 'system' }], model: 'model' } }); + const responsePromise = client.async.chat.completions.create({ + request: { messages: [{ content: 'string', role: 'system' }], model: 'model' }, + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,123 +25,140 @@ describe('resource completions', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.async.chat.completions.create({ - request: { - messages: [{ - content: 'string', - role: 'system', - reasoning_steps: [{ - thought: 'thought', - execute_python: { code: 'code', result: 'result' }, - fetch_url_content: { contents: [{ - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }] }, - type: 'type', - web_search: { search_keywords: ['string'], search_results: [{ - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }] }, - }], - tool_call_id: 'tool_call_id', - tool_calls: [{ - id: 'id', - function: { arguments: 'arguments', name: 'name' }, - type: 'function', - }], - }], - model: 'model', - _debug_pro_search: true, - _force_new_agent: true, - _inputs: [0], - _prompt_token_length: 0, - best_of: 0, - country: 'country', - cum_logprobs: true, - disable_search: true, - diverse_first_token: true, - enable_search_classifier: true, - file_workspace_id: 'file_workspace_id', - frequency_penalty: -2, - has_image_url: true, - image_domain_filter: ['string'], - image_format_filter: ['string'], - language_preference: 'language_preference', - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - latitude: 0, - logprobs: true, - longitude: 0, - max_tokens: 1, - n: 1, - num_images: 0, - num_search_results: 0, - parallel_tool_calls: true, - presence_penalty: -2, - ranking_model: 'ranking_model', - reasoning_effort: 'minimal', - response_format: { type: 'text' }, - response_metadata: { foo: 'bar' }, - return_images: true, - return_related_questions: true, - safe_search: true, - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_internal_properties: { foo: 'bar' }, - search_language_filter: ['string'], - search_mode: 'web', - search_recency_filter: 'hour', - search_tenant: 'search_tenant', - stop: 'string', - stream: true, - stream_mode: 'full', - temperature: 0, - thread_id: 'thread_id', - tool_choice: 'none', - tools: [{ - function: { - description: 'description', - name: 'name', - parameters: { - properties: { foo: 'bar' }, - type: 'type', - additional_properties: true, - required: ['string'], - }, - strict: true, - }, - type: 'function', - }], - top_k: 0, - top_logprobs: 0, - top_p: 0, - updated_after_timestamp: 0, - updated_before_timestamp: 0, - use_threads: true, - user_original_query: 'user_original_query', - web_search_options: { - image_results_enhanced_relevance: true, - search_context_size: 'low', - search_type: 'fast', - user_location: { - city: 'city', - country: 'country', - latitude: 0, - longitude: 0, - region: 'region', - }, - }, - }, - idempotency_key: 'idempotency_key', - }); + request: { + messages: [ + { + content: 'string', + role: 'system', + reasoning_steps: [ + { + thought: 'thought', + execute_python: { code: 'code', result: 'result' }, + fetch_url_content: { + contents: [ + { + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }, + ], + }, + type: 'type', + web_search: { + search_keywords: ['string'], + search_results: [ + { + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }, + ], + }, + }, + ], + tool_call_id: 'tool_call_id', + tool_calls: [ + { + id: 'id', + function: { arguments: 'arguments', name: 'name' }, + type: 'function', + }, + ], + }, + ], + model: 'model', + _debug_pro_search: true, + _force_new_agent: true, + _inputs: [0], + _prompt_token_length: 0, + best_of: 0, + country: 'country', + cum_logprobs: true, + disable_search: true, + diverse_first_token: true, + enable_search_classifier: true, + file_workspace_id: 'file_workspace_id', + frequency_penalty: -2, + has_image_url: true, + image_domain_filter: ['string'], + image_format_filter: ['string'], + language_preference: 'language_preference', + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + latitude: 0, + logprobs: true, + longitude: 0, + max_tokens: 1, + n: 1, + num_images: 0, + num_search_results: 0, + parallel_tool_calls: true, + presence_penalty: -2, + ranking_model: 'ranking_model', + reasoning_effort: 'minimal', + response_format: { type: 'text' }, + response_metadata: { foo: 'bar' }, + return_images: true, + return_related_questions: true, + safe_search: true, + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_internal_properties: { foo: 'bar' }, + search_language_filter: ['string'], + search_mode: 'web', + search_recency_filter: 'hour', + search_tenant: 'search_tenant', + stop: 'string', + stream: true, + stream_mode: 'full', + temperature: 0, + thread_id: 'thread_id', + tool_choice: 'none', + tools: [ + { + function: { + description: 'description', + name: 'name', + parameters: { + properties: { foo: 'bar' }, + type: 'type', + additional_properties: true, + required: ['string'], + }, + strict: true, + }, + type: 'function', + }, + ], + top_k: 0, + top_logprobs: 0, + top_p: 0, + updated_after_timestamp: 0, + updated_before_timestamp: 0, + use_threads: true, + user_original_query: 'user_original_query', + web_search_options: { + image_results_enhanced_relevance: true, + search_context_size: 'low', + search_type: 'fast', + user_location: { + city: 'city', + country: 'country', + latitude: 0, + longitude: 0, + region: 'region', + }, + }, + }, + idempotency_key: 'idempotency_key', + }); }); // Mock server tests are disabled @@ -166,16 +188,20 @@ describe('resource completions', () => { // Mock server tests are disabled test.skip('get: 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.async.chat.completions.get('api_request', { - local_mode: true, - 'x-client-env': 'x-client-env', - 'x-client-name': 'x-client-name', - 'x-created-at-epoch-seconds': 'x-created-at-epoch-seconds', - 'x-request-time': 'x-request-time', - 'x-usage-tier': 'x-usage-tier', - 'x-user-id': 'x-user-id', - }, { path: '/_stainless_unknown_path' })) - .rejects - .toThrow(Perplexity.NotFoundError); + await expect( + client.async.chat.completions.get( + 'api_request', + { + local_mode: true, + 'x-client-env': 'x-client-env', + 'x-client-name': 'x-client-name', + 'x-created-at-epoch-seconds': 'x-created-at-epoch-seconds', + 'x-request-time': 'x-request-time', + 'x-usage-tier': 'x-usage-tier', + 'x-user-id': 'x-user-id', + }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Perplexity.NotFoundError); }); }); diff --git a/tests/api-resources/browser/sessions.test.ts b/tests/api-resources/browser/sessions.test.ts index aa7a74f..1095635 100644 --- a/tests/api-resources/browser/sessions.test.ts +++ b/tests/api-resources/browser/sessions.test.ts @@ -2,7 +2,10 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource sessions', () => { // Mock server tests are disabled @@ -20,9 +23,9 @@ describe('resource sessions', () => { // Mock server tests are disabled test.skip('create: 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.browser.sessions.create({}, { path: '/_stainless_unknown_path' })) - .rejects - .toThrow(Perplexity.NotFoundError); + await expect(client.browser.sessions.create({}, { path: '/_stainless_unknown_path' })).rejects.toThrow( + Perplexity.NotFoundError, + ); }); // Mock server tests are disabled diff --git a/tests/api-resources/chat/completions.test.ts b/tests/api-resources/chat/completions.test.ts index 8393533..aede87d 100644 --- a/tests/api-resources/chat/completions.test.ts +++ b/tests/api-resources/chat/completions.test.ts @@ -2,12 +2,18 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource completions', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.chat.completions.create({ messages: [{ content: 'string', role: 'system' }], model: 'model' }); + const responsePromise = client.chat.completions.create({ + messages: [{ content: 'string', role: 'system' }], + model: 'model', + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,119 +26,136 @@ describe('resource completions', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.chat.completions.create({ - messages: [{ - content: 'string', - role: 'system', - reasoning_steps: [{ - thought: 'thought', - execute_python: { code: 'code', result: 'result' }, - fetch_url_content: { contents: [{ - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }] }, - type: 'type', - web_search: { search_keywords: ['string'], search_results: [{ - title: 'title', - url: 'url', - date: 'date', - last_updated: 'last_updated', - snippet: 'snippet', - source: 'web', - }] }, - }], - tool_call_id: 'tool_call_id', - tool_calls: [{ - id: 'id', - function: { arguments: 'arguments', name: 'name' }, - type: 'function', - }], - }], - model: 'model', - _debug_pro_search: true, - _force_new_agent: true, - _inputs: [0], - _prompt_token_length: 0, - best_of: 0, - country: 'country', - cum_logprobs: true, - disable_search: true, - diverse_first_token: true, - enable_search_classifier: true, - file_workspace_id: 'file_workspace_id', - frequency_penalty: -2, - has_image_url: true, - image_domain_filter: ['string'], - image_format_filter: ['string'], - language_preference: 'language_preference', - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - latitude: 0, - logprobs: true, - longitude: 0, - max_tokens: 1, - n: 1, - num_images: 0, - num_search_results: 0, - parallel_tool_calls: true, - presence_penalty: -2, - ranking_model: 'ranking_model', - reasoning_effort: 'minimal', - response_format: { type: 'text' }, - response_metadata: { foo: 'bar' }, - return_images: true, - return_related_questions: true, - safe_search: true, - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_internal_properties: { foo: 'bar' }, - search_language_filter: ['string'], - search_mode: 'web', - search_recency_filter: 'hour', - search_tenant: 'search_tenant', - stop: 'string', - stream: false, - stream_mode: 'full', - temperature: 0, - thread_id: 'thread_id', - tool_choice: 'none', - tools: [{ - function: { - description: 'description', - name: 'name', - parameters: { - properties: { foo: 'bar' }, - type: 'type', - additional_properties: true, - required: ['string'], - }, - strict: true, - }, - type: 'function', - }], - top_k: 0, - top_logprobs: 0, - top_p: 0, - updated_after_timestamp: 0, - updated_before_timestamp: 0, - use_threads: true, - user_original_query: 'user_original_query', - web_search_options: { - image_results_enhanced_relevance: true, - search_context_size: 'low', - search_type: 'fast', - user_location: { - city: 'city', - country: 'country', - latitude: 0, - longitude: 0, - region: 'region', - }, - }, - }); + messages: [ + { + content: 'string', + role: 'system', + reasoning_steps: [ + { + thought: 'thought', + execute_python: { code: 'code', result: 'result' }, + fetch_url_content: { + contents: [ + { + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }, + ], + }, + type: 'type', + web_search: { + search_keywords: ['string'], + search_results: [ + { + title: 'title', + url: 'url', + date: 'date', + last_updated: 'last_updated', + snippet: 'snippet', + source: 'web', + }, + ], + }, + }, + ], + tool_call_id: 'tool_call_id', + tool_calls: [ + { + id: 'id', + function: { arguments: 'arguments', name: 'name' }, + type: 'function', + }, + ], + }, + ], + model: 'model', + _debug_pro_search: true, + _force_new_agent: true, + _inputs: [0], + _prompt_token_length: 0, + best_of: 0, + country: 'country', + cum_logprobs: true, + disable_search: true, + diverse_first_token: true, + enable_search_classifier: true, + file_workspace_id: 'file_workspace_id', + frequency_penalty: -2, + has_image_url: true, + image_domain_filter: ['string'], + image_format_filter: ['string'], + language_preference: 'language_preference', + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + latitude: 0, + logprobs: true, + longitude: 0, + max_tokens: 1, + n: 1, + num_images: 0, + num_search_results: 0, + parallel_tool_calls: true, + presence_penalty: -2, + ranking_model: 'ranking_model', + reasoning_effort: 'minimal', + response_format: { type: 'text' }, + response_metadata: { foo: 'bar' }, + return_images: true, + return_related_questions: true, + safe_search: true, + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_internal_properties: { foo: 'bar' }, + search_language_filter: ['string'], + search_mode: 'web', + search_recency_filter: 'hour', + search_tenant: 'search_tenant', + stop: 'string', + stream: false, + stream_mode: 'full', + temperature: 0, + thread_id: 'thread_id', + tool_choice: 'none', + tools: [ + { + function: { + description: 'description', + name: 'name', + parameters: { + properties: { foo: 'bar' }, + type: 'type', + additional_properties: true, + required: ['string'], + }, + strict: true, + }, + type: 'function', + }, + ], + top_k: 0, + top_logprobs: 0, + top_p: 0, + updated_after_timestamp: 0, + updated_before_timestamp: 0, + use_threads: true, + user_original_query: 'user_original_query', + web_search_options: { + image_results_enhanced_relevance: true, + search_context_size: 'low', + search_type: 'fast', + user_location: { + city: 'city', + country: 'country', + latitude: 0, + longitude: 0, + region: 'region', + }, + }, + }); }); }); diff --git a/tests/api-resources/contextualized-embeddings.test.ts b/tests/api-resources/contextualized-embeddings.test.ts index 1443b98..05f97a5 100644 --- a/tests/api-resources/contextualized-embeddings.test.ts +++ b/tests/api-resources/contextualized-embeddings.test.ts @@ -2,12 +2,18 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource contextualizedEmbeddings', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { - const responsePromise = client.contextualizedEmbeddings.create({ input: [['x']], model: 'pplx-embed-context-v1-0.6b' }); + const responsePromise = client.contextualizedEmbeddings.create({ + input: [['x']], + model: 'pplx-embed-context-v1-0.6b', + }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,10 +26,10 @@ describe('resource contextualizedEmbeddings', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.contextualizedEmbeddings.create({ - input: [['x']], - model: 'pplx-embed-context-v1-0.6b', - dimensions: 128, - encoding_format: 'base64_int8', - }); + input: [['x']], + model: 'pplx-embed-context-v1-0.6b', + dimensions: 128, + encoding_format: 'base64_int8', + }); }); }); diff --git a/tests/api-resources/embeddings.test.ts b/tests/api-resources/embeddings.test.ts index 1fc540c..07bb0c8 100644 --- a/tests/api-resources/embeddings.test.ts +++ b/tests/api-resources/embeddings.test.ts @@ -2,7 +2,10 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource embeddings', () => { // Mock server tests are disabled @@ -20,10 +23,10 @@ describe('resource embeddings', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.embeddings.create({ - input: 'x', - model: 'pplx-embed-v1-0.6b', - dimensions: 128, - encoding_format: 'base64_int8', - }); + input: 'x', + model: 'pplx-embed-v1-0.6b', + dimensions: 128, + encoding_format: 'base64_int8', + }); }); }); diff --git a/tests/api-resources/responses.test.ts b/tests/api-resources/responses.test.ts index 929f123..cf715c9 100644 --- a/tests/api-resources/responses.test.ts +++ b/tests/api-resources/responses.test.ts @@ -2,7 +2,10 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource responses', () => { // Mock server tests are disabled @@ -20,45 +23,47 @@ describe('resource responses', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.responses.create({ - input: 'string', - instructions: 'instructions', - language_preference: 'language_preference', - max_output_tokens: 1, - max_steps: 1, - model: 'model', - models: ['string'], - preset: 'preset', - reasoning: { effort: 'low' }, - response_format: { - type: 'json_schema', - json_schema: { - name: 'x', - schema: { foo: 'bar' }, - description: 'description', - strict: true, - }, - }, - stream: false, - tools: [{ - type: 'web_search', - filters: { - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_recency_filter: 'hour', - }, - max_tokens: 0, - max_tokens_per_page: 0, - user_location: { - city: 'city', - country: 'country', - latitude: 0, - longitude: 0, - region: 'region', - }, - }], - }); + input: 'string', + instructions: 'instructions', + language_preference: 'language_preference', + max_output_tokens: 1, + max_steps: 1, + model: 'model', + models: ['string'], + preset: 'preset', + reasoning: { effort: 'low' }, + response_format: { + type: 'json_schema', + json_schema: { + name: 'x', + schema: { foo: 'bar' }, + description: 'description', + strict: true, + }, + }, + stream: false, + tools: [ + { + type: 'web_search', + filters: { + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_recency_filter: 'hour', + }, + max_tokens: 0, + max_tokens_per_page: 0, + user_location: { + city: 'city', + country: 'country', + latitude: 0, + longitude: 0, + region: 'region', + }, + }, + ], + }); }); }); diff --git a/tests/api-resources/search.test.ts b/tests/api-resources/search.test.ts index 8bdb96a..4ecb303 100644 --- a/tests/api-resources/search.test.ts +++ b/tests/api-resources/search.test.ts @@ -2,7 +2,10 @@ import Perplexity from '@perplexity-ai/perplexity_ai'; -const client = new Perplexity({ apiKey: 'My API Key', baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010' }); +const client = new Perplexity({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); describe('resource search', () => { // Mock server tests are disabled @@ -20,20 +23,20 @@ describe('resource search', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.search.create({ - query: 'string', - country: 'country', - display_server_time: true, - last_updated_after_filter: 'last_updated_after_filter', - last_updated_before_filter: 'last_updated_before_filter', - max_results: 0, - max_tokens: 0, - max_tokens_per_page: 0, - search_after_date_filter: 'search_after_date_filter', - search_before_date_filter: 'search_before_date_filter', - search_domain_filter: ['string'], - search_language_filter: ['string'], - search_mode: 'web', - search_recency_filter: 'hour', - }); + query: 'string', + country: 'country', + display_server_time: true, + last_updated_after_filter: 'last_updated_after_filter', + last_updated_before_filter: 'last_updated_before_filter', + max_results: 0, + max_tokens: 0, + max_tokens_per_page: 0, + search_after_date_filter: 'search_after_date_filter', + search_before_date_filter: 'search_before_date_filter', + search_domain_filter: ['string'], + search_language_filter: ['string'], + search_mode: 'web', + search_recency_filter: 'hour', + }); }); }); diff --git a/tests/buildHeaders.test.ts b/tests/buildHeaders.test.ts index b3db93a..4cbe1e7 100644 --- a/tests/buildHeaders.test.ts +++ b/tests/buildHeaders.test.ts @@ -1,5 +1,9 @@ import { inspect } from 'node:util'; -import { buildHeaders, type HeadersLike, type NullableHeaders } from '@perplexity-ai/perplexity_ai/internal/headers'; +import { + buildHeaders, + type HeadersLike, + type NullableHeaders, +} from '@perplexity-ai/perplexity_ai/internal/headers'; function inspectNullableHeaders(headers: NullableHeaders) { return `NullableHeaders {${[ diff --git a/tests/index.test.ts b/tests/index.test.ts index bf861e3..704454e 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -21,10 +21,10 @@ describe('instantiate client', () => { describe('defaultHeaders', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultHeaders: { 'X-My-Default-Header': '2' }, - apiKey: 'My API Key', -}) + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-My-Default-Header': '2' }, + apiKey: 'My API Key', + }); test('they are used in the request', async () => { const { req } = await client.buildRequest({ path: '/foo', method: 'post' }); @@ -49,191 +49,193 @@ describe('instantiate client', () => { expect(req.headers.has('x-my-default-header')).toBe(false); }); }); -describe('logging', () => { - const env = process.env; + describe('logging', () => { + const env = process.env; - beforeEach(() => { - process.env = { ...env }; - process.env['PERPLEXITY_LOG'] = undefined; - }); + beforeEach(() => { + process.env = { ...env }; + process.env['PERPLEXITY_LOG'] = undefined; + }); - afterEach(() => { - process.env = env; - }); + afterEach(() => { + process.env = env; + }); - const forceAPIResponseForClient = async (client: Perplexity) => { - await new APIPromise( - client, - Promise.resolve({ - response: new Response(), - controller: new AbortController(), - requestLogID: 'log_000000', - retryOfRequestLogID: undefined, - startTime: Date.now(), - options: { - method: 'get', - path: '/', - }, - }), - ); - }; - - test('debug logs when log level is debug', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), + const forceAPIResponseForClient = async (client: Perplexity) => { + await new APIPromise( + client, + Promise.resolve({ + response: new Response(), + controller: new AbortController(), + requestLogID: 'log_000000', + retryOfRequestLogID: undefined, + startTime: Date.now(), + options: { + method: 'get', + path: '/', + }, + }), + ); }; - const client = new Perplexity({ - logger: logger, - logLevel: 'debug', - apiKey: 'My API Key', -}); + test('debug logs when log level is debug', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - await forceAPIResponseForClient(client); - expect(debugMock).toHaveBeenCalled(); - }); + const client = new Perplexity({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); - test('default logLevel is warn', async () => { - const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.logLevel).toBe('warn'); - }); + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); - test('debug logs are skipped when log level is info', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; + test('default logLevel is warn', async () => { + const client = new Perplexity({ apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + }); - const client = new Perplexity({ - logger: logger, - logLevel: 'info', - apiKey: 'My API Key', -}); + test('debug logs are skipped when log level is info', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - await forceAPIResponseForClient(client); - expect(debugMock).not.toHaveBeenCalled(); - }); + const client = new Perplexity({ + logger: logger, + logLevel: 'info', + apiKey: 'My API Key', + }); - test('debug logs happen with debug env var', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); - process.env['PERPLEXITY_LOG'] = 'debug'; - const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); - expect(client.logLevel).toBe('debug'); + test('debug logs happen with debug env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - await forceAPIResponseForClient(client); - expect(debugMock).toHaveBeenCalled(); - }); + process.env['PERPLEXITY_LOG'] = 'debug'; + const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('debug'); - test('warn when env var level is invalid', async () => { - const warnMock = jest.fn(); - const logger = { - debug: jest.fn(), - info: jest.fn(), - warn: warnMock, - error: jest.fn(), - }; + await forceAPIResponseForClient(client); + expect(debugMock).toHaveBeenCalled(); + }); - process.env['PERPLEXITY_LOG'] = 'not a log level'; - const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); - expect(client.logLevel).toBe('warn'); - expect(warnMock).toHaveBeenCalledWith('process.env[\'PERPLEXITY_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]'); - }); + test('warn when env var level is invalid', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; - test('client log level overrides env var', async () => { - const debugMock = jest.fn(); - const logger = { - debug: debugMock, - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }; + process.env['PERPLEXITY_LOG'] = 'not a log level'; + const client = new Perplexity({ logger: logger, apiKey: 'My API Key' }); + expect(client.logLevel).toBe('warn'); + expect(warnMock).toHaveBeenCalledWith( + 'process.env[\'PERPLEXITY_LOG\'] was set to "not a log level", expected one of ["off","error","warn","info","debug"]', + ); + }); - process.env['PERPLEXITY_LOG'] = 'debug'; - const client = new Perplexity({ - logger: logger, - logLevel: 'off', - apiKey: 'My API Key', -}); + test('client log level overrides env var', async () => { + const debugMock = jest.fn(); + const logger = { + debug: debugMock, + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }; - await forceAPIResponseForClient(client); - expect(debugMock).not.toHaveBeenCalled(); - }); + process.env['PERPLEXITY_LOG'] = 'debug'; + const client = new Perplexity({ + logger: logger, + logLevel: 'off', + apiKey: 'My API Key', + }); - test('no warning logged for invalid env var level + valid client level', async () => { - const warnMock = jest.fn(); - const logger = { - debug: jest.fn(), - info: jest.fn(), - warn: warnMock, - error: jest.fn(), - }; + await forceAPIResponseForClient(client); + expect(debugMock).not.toHaveBeenCalled(); + }); - process.env['PERPLEXITY_LOG'] = 'not a log level'; - const client = new Perplexity({ - logger: logger, - logLevel: 'debug', - apiKey: 'My API Key', -}); - expect(client.logLevel).toBe('debug'); - expect(warnMock).not.toHaveBeenCalled(); + test('no warning logged for invalid env var level + valid client level', async () => { + const warnMock = jest.fn(); + const logger = { + debug: jest.fn(), + info: jest.fn(), + warn: warnMock, + error: jest.fn(), + }; + + process.env['PERPLEXITY_LOG'] = 'not a log level'; + const client = new Perplexity({ + logger: logger, + logLevel: 'debug', + apiKey: 'My API Key', + }); + expect(client.logLevel).toBe('debug'); + expect(warnMock).not.toHaveBeenCalled(); + }); }); -}); describe('defaultQuery', () => { test('with null query params given', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultQuery: { apiVersion: 'foo' }, - apiKey: 'My API Key', -}); + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo' }, + apiKey: 'My API Key', + }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); test('multiple default query params', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultQuery: { apiVersion: 'foo', hello: 'world' }, - apiKey: 'My API Key', -}); + baseURL: 'http://localhost:5000/', + defaultQuery: { apiVersion: 'foo', hello: 'world' }, + apiKey: 'My API Key', + }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); test('overriding with `undefined`', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultQuery: { hello: 'world' }, - apiKey: 'My API Key', -}) + baseURL: 'http://localhost:5000/', + defaultQuery: { hello: 'world' }, + apiKey: 'My API Key', + }); expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); }); test('custom fetch', async () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: (url) => { - return Promise.resolve( - new Response(JSON.stringify({ url, custom: true }), { - headers: { 'Content-Type': 'application/json' }, - }), - ); -}, -}); + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: (url) => { + return Promise.resolve( + new Response(JSON.stringify({ url, custom: true }), { + headers: { 'Content-Type': 'application/json' }, + }), + ); + }, + }); const response = await client.get('/foo'); expect(response).toEqual({ url: 'http://localhost:5000/foo', custom: true }); @@ -242,37 +244,35 @@ describe('logging', () => { test('explicit global fetch', async () => { // make sure the global fetch type is assignable to our Fetch type const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: defaultFetch, -}); + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: defaultFetch, + }); }); test('custom signal', async () => { const client = new Perplexity({ - baseURL: process.env["TEST_API_BASE_URL"] ?? 'http://127.0.0.1:4010', - apiKey: 'My API Key', - fetch: (...args) => { - return new Promise((resolve, reject) => - setTimeout( - () => - defaultFetch(...args) - .then(resolve) - .catch(reject), - 300, - ), - ); -}, -}); + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + apiKey: 'My API Key', + fetch: (...args) => { + return new Promise((resolve, reject) => + setTimeout( + () => + defaultFetch(...args) + .then(resolve) + .catch(reject), + 300, + ), + ); + }, + }); const controller = new AbortController(); setTimeout(() => controller.abort(), 200); const spy = jest.spyOn(client, 'request'); - await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError( - APIUserAbortError, - ); + await expect(client.get('/foo', { signal: controller.signal })).rejects.toThrowError(APIUserAbortError); expect(spy).toHaveBeenCalledTimes(1); }); @@ -284,10 +284,10 @@ describe('logging', () => { }; const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', - fetch: testFetch, -}); + baseURL: 'http://localhost:5000/', + apiKey: 'My API Key', + fetch: testFetch, + }); await client.patch('/foo'); expect(capturedRequest?.method).toEqual('PATCH'); @@ -322,29 +322,35 @@ describe('logging', () => { test('empty env variable', () => { process.env['PERPLEXITY_BASE_URL'] = ''; // empty const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.perplexity.ai') + expect(client.baseURL).toEqual('https://api.perplexity.ai'); }); test('blank env variable', () => { process.env['PERPLEXITY_BASE_URL'] = ' '; // blank const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.baseURL).toEqual('https://api.perplexity.ai') + expect(client.baseURL).toEqual('https://api.perplexity.ai'); }); test('in request options', () => { const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual('http://localhost:5000/option/foo'); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/option/foo', + ); }); test('in request options overridden by client options', () => { const client = new Perplexity({ apiKey: 'My API Key', baseURL: 'http://localhost:5000/client' }); - expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual('http://localhost:5000/client/foo'); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/client/foo', + ); }); test('in request options overridden by env variable', () => { process.env['PERPLEXITY_BASE_URL'] = 'http://localhost:5000/env'; const client = new Perplexity({ apiKey: 'My API Key' }); - expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual('http://localhost:5000/env/foo'); + expect(client.buildURL('/foo', null, 'http://localhost:5000/option')).toEqual( + 'http://localhost:5000/env/foo', + ); }); }); @@ -360,10 +366,10 @@ describe('logging', () => { describe('withOptions', () => { test('creates a new client with overridden options', async () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - maxRetries: 3, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + maxRetries: 3, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ maxRetries: 5, @@ -385,11 +391,11 @@ describe('logging', () => { test('inherits options from the parent client', async () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - defaultHeaders: { 'X-Test-Header': 'test-value' }, - defaultQuery: { 'test-param': 'test-value' }, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + defaultHeaders: { 'X-Test-Header': 'test-value' }, + defaultQuery: { 'test-param': 'test-value' }, + apiKey: 'My API Key', + }); const newClient = client.withOptions({ baseURL: 'http://localhost:5001/', @@ -404,10 +410,10 @@ describe('logging', () => { test('respects runtime property changes when creating new client', () => { const client = new Perplexity({ - baseURL: 'http://localhost:5000/', - timeout: 1000, - apiKey: 'My API Key', - }); + baseURL: 'http://localhost:5000/', + timeout: 1000, + apiKey: 'My API Key', + }); // Modify the client properties directly after creation client.baseURL = 'http://localhost:6000/'; @@ -453,13 +459,18 @@ describe('request building', () => { describe('custom headers', () => { test('handles undefined', async () => { - const { req } = await client.buildRequest({ path: '/foo', method: 'post', body: { value: 'hello' }, headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null } }); + const { req } = await client.buildRequest({ + path: '/foo', + method: 'post', + body: { value: 'hello' }, + headers: { 'X-Foo': 'baz', 'x-foo': 'bar', 'x-Foo': undefined, 'x-baz': 'bam', 'X-Baz': null }, + }); expect(req.headers.get('x-foo')).toEqual('bar'); expect(req.headers.get('x-Foo')).toEqual('bar'); expect(req.headers.get('X-Foo')).toEqual('bar'); expect(req.headers.get('x-baz')).toEqual(null); }); - }) + }); }); describe('default encoder', () => { @@ -536,37 +547,40 @@ describe('default encoder', () => { describe('retries', () => { test('retry on timeout', async () => { let count = 0; - const testFetch = async (url: string | URL | Request, { signal }: RequestInit = {}): Promise => { - if (count++ === 0) { - return new Promise((resolve, reject) => - signal?.addEventListener('abort', () => reject(new Error('timed out'))), - ); - } - return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); - }; - - const client = new Perplexity({ - apiKey: 'My API Key', - timeout: 10, - fetch: testFetch, - }); + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { + if (count++ === 0) { + return new Promise( + (resolve, reject) => signal?.addEventListener('abort', () => reject(new Error('timed out'))), + ); + } + return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); + }; - expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); - expect(count).toEqual(2); - expect( - await client - .request({ path: '/foo', method: 'get' }) - .asResponse() - .then((r) => r.text()), - ).toEqual(JSON.stringify({ a: 1 })); - expect(count).toEqual(3); + const client = new Perplexity({ + apiKey: 'My API Key', + timeout: 10, + fetch: testFetch, }); + expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); + expect(count).toEqual(2); + expect( + await client + .request({ path: '/foo', method: 'get' }) + .asResponse() + .then((r) => r.text()), + ).toEqual(JSON.stringify({ a: 1 })); + expect(count).toEqual(3); + }); + test('retry count header', async () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++ + count++; if (count <= 2) { return new Response(undefined, { status: 429, @@ -580,10 +594,10 @@ describe('retries', () => { }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); @@ -595,7 +609,7 @@ describe('retries', () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++ + count++; if (count <= 2) { return new Response(undefined, { status: 429, @@ -608,10 +622,10 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -628,7 +642,7 @@ describe('retries', () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++ + count++; if (count <= 2) { return new Response(undefined, { status: 429, @@ -641,11 +655,11 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - defaultHeaders: { 'X-Stainless-Retry-Count': null }, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + defaultHeaders: { 'X-Stainless-Retry-Count': null }, + }); expect( await client.request({ @@ -661,7 +675,7 @@ describe('retries', () => { let count = 0; let capturedRequest: RequestInit | undefined; const testFetch = async (url: string | URL | Request, init: RequestInit = {}): Promise => { - count++ + count++; if (count <= 2) { return new Response(undefined, { status: 429, @@ -674,10 +688,10 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; const client = new Perplexity({ - apiKey: 'My API Key', - fetch: testFetch, - maxRetries: 4, - }); + apiKey: 'My API Key', + fetch: testFetch, + maxRetries: 4, + }); expect( await client.request({ @@ -692,7 +706,10 @@ describe('retries', () => { test('retry on 429 with retry-after', async () => { let count = 0; - const testFetch = async (url: string | URL | Request, { signal }: RequestInit = {}): Promise => { + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { if (count++ === 0) { return new Response(undefined, { status: 429, @@ -719,7 +736,10 @@ describe('retries', () => { test('retry on 429 with retry-after-ms', async () => { let count = 0; - const testFetch = async (url: string | URL | Request, { signal }: RequestInit = {}): Promise => { + const testFetch = async ( + url: string | URL | Request, + { signal }: RequestInit = {}, + ): Promise => { if (count++ === 0) { return new Response(undefined, { status: 429, diff --git a/tests/streaming.test.ts b/tests/streaming.test.ts index 18d682b..5c1599c 100644 --- a/tests/streaming.test.ts +++ b/tests/streaming.test.ts @@ -242,4 +242,4 @@ test('error handling', async () => { `[Error: {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}]`, ); await err.toBeInstanceOf(APIError); -});; +}); diff --git a/tests/stringifyQuery.test.ts b/tests/stringifyQuery.test.ts index a2fb223..2358ac4 100644 --- a/tests/stringifyQuery.test.ts +++ b/tests/stringifyQuery.test.ts @@ -2,24 +2,26 @@ import { stringifyQuery } from '@perplexity-ai/perplexity_ai/internal/utils/query'; -describe(stringifyQuery, () => { for (const [input, expected] of [ - [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], - [{ a: null, b: false, c: undefined }, 'a=&b=false'], - [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], - [ - { 'a/b': 'c/d', 'e=f': 'g&h' }, - `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( - 'e=f', - )}=${encodeURIComponent('g&h')}`, - ], -] as const) { - it(`${JSON.stringify(input)} -> ${expected}`, () => { - expect(stringifyQuery(input)).toEqual(expected); - }); -} +describe(stringifyQuery, () => { + for (const [input, expected] of [ + [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], + [{ a: null, b: false, c: undefined }, 'a=&b=false'], + [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], + [ + { 'a/b': 'c/d', 'e=f': 'g&h' }, + `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( + 'e=f', + )}=${encodeURIComponent('g&h')}`, + ], + ] as const) { + it(`${JSON.stringify(input)} -> ${expected}`, () => { + expect(stringifyQuery(input)).toEqual(expected); + }); + } -for (const value of [[], {}, new Date()]) { - it(`${JSON.stringify(value)} -> `, () => { - expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); - }); -} }) + for (const value of [[], {}, new Date()]) { + it(`${JSON.stringify(value)} -> `, () => { + expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); + }); + } +}); diff --git a/yarn.lock b/yarn.lock index 18e7cbd..f6eae3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,6 +709,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pkgr/core@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" + integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1510,6 +1515,14 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +eslint-plugin-prettier@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" + integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.11.7" + eslint-plugin-unused-imports@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" @@ -1661,6 +1674,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -2823,6 +2841,13 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" @@ -3119,6 +3144,13 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +synckit@^0.11.7: + version "0.11.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" + integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== + dependencies: + "@pkgr/core" "^0.2.4" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From 8d99818d6981bc084189213fc03f38408aa4dfe6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:26:54 +0000 Subject: [PATCH 04/12] feat: support setting headers via env --- src/client.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/client.ts b/src/client.ts index 20f90f3..cf2129d 100644 --- a/src/client.ts +++ b/src/client.ts @@ -194,6 +194,18 @@ export class Perplexity { this.fetch = options.fetch ?? Shims.getDefaultFetch(); this.#encoder = Opts.FallbackEncoder; + const customHeadersEnv = readEnv('PERPLEXITY_CUSTOM_HEADERS'); + if (customHeadersEnv) { + const parsed: Record = {}; + for (const line of customHeadersEnv.split('\n')) { + const colon = line.indexOf(':'); + if (colon >= 0) { + parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim(); + } + } + options.defaultHeaders = { ...parsed, ...options.defaultHeaders }; + } + this._options = options; this.apiKey = apiKey; From bd0078c41267bf36971c2a621076d07056bd2e13 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:48:00 +0000 Subject: [PATCH 05/12] chore(format): run eslint and prettier separately --- .github/workflows/release-doctor.yml | 1 - eslint.config.mjs | 3 --- package.json | 1 - scripts/fast-format | 9 +++----- scripts/format | 3 +-- scripts/lint | 3 +++ src/internal/types.ts | 14 ++++++------ yarn.lock | 32 ---------------------------- 8 files changed, 13 insertions(+), 53 deletions(-) diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 725f00a..fcfb0ed 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -17,4 +17,3 @@ jobs: - name: Check release environment run: | bash ./bin/check-release-environment - diff --git a/eslint.config.mjs b/eslint.config.mjs index 230d8df..6642dab 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,6 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; -import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -14,11 +13,9 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, - prettier, }, rules: { 'no-unused-vars': 'off', - 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 17bd582..70a8daa 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", - "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/scripts/fast-format b/scripts/fast-format index 53721ac..f1873ae 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,10 +31,7 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -# format things eslint didn't -PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" -if ! [ -z "$PRETTIER_FILES" ]; then - echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ - '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +if ! [ -z "$FILE_LIST" ]; then + cat "$FILE_LIST" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern --ignore-unknown fi diff --git a/scripts/format b/scripts/format index 7a75640..b1b2c17 100755 --- a/scripts/format +++ b/scripts/format @@ -8,5 +8,4 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -# format things eslint didn't -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . diff --git a/scripts/lint b/scripts/lint index 3ffb78a..1f53254 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,6 +4,9 @@ set -e cd "$(dirname "$0")/.." +echo "==> Running prettier --check" +./node_modules/.bin/prettier --check . + echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/src/internal/types.ts b/src/internal/types.ts index b668dfc..a050513 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -40,7 +40,6 @@ type OverloadedParameters = : T extends (...args: infer A) => unknown ? A : never; -/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -63,19 +62,18 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ +/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ +/** @ts-ignore For users with undici */ /* prettier-ignore */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ +/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ +/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ +/** @ts-ignore For users who use Deno */ /* prettier-ignore */ type FetchRequestInit = NonNullable[1]>; -/* eslint-enable */ type RequestInits = | NotAny diff --git a/yarn.lock b/yarn.lock index f6eae3c..18e7cbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -709,11 +709,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" - integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1515,14 +1510,6 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" - integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.11.7" - eslint-plugin-unused-imports@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" @@ -1674,11 +1661,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -2841,13 +2823,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" @@ -3144,13 +3119,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.11.7: - version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" - integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== - dependencies: - "@pkgr/core" "^0.2.4" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" From a78df5a33fb649566663afe019711d56d2687b94 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:13:30 +0000 Subject: [PATCH 06/12] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 86b0bd0..a30276e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai%2Fperplexity-e5052719572f5155f4cf704d996e5c7a875700a16f68f2335975ea3d06140b17.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai/perplexity-e5052719572f5155f4cf704d996e5c7a875700a16f68f2335975ea3d06140b17.yml openapi_spec_hash: 97d9df5dc228bb6d71be54212bc5b600 config_hash: e09a1767e929614701fb498eaaac682d From 818a7021ef9036562be0fa0ca2f18fbb23c6c8bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:20:11 +0000 Subject: [PATCH 07/12] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index a30276e..2bc4e3e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai/perplexity-e5052719572f5155f4cf704d996e5c7a875700a16f68f2335975ea3d06140b17.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai/perplexity-ebf1d5e2e90a335c4b7ddf6e0c98b4f69390836ae2dd806ffe255559e51d45b0.yml openapi_spec_hash: 97d9df5dc228bb6d71be54212bc5b600 config_hash: e09a1767e929614701fb498eaaac682d From af8b1eee91c3ad2fa5f5f1adbb00d836e1560799 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 14:47:47 +0000 Subject: [PATCH 08/12] chore: redact api-key headers in debug logs --- src/internal/utils/log.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index c8062b7..21b42dd 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -107,6 +107,8 @@ export const formatRequestDetails = (details: { name, ( name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'api-key' || + name.toLowerCase() === 'x-api-key' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ) ? From 149b420429b381fe351fd63f3e4a0ce73dd1f3b1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 18:50:21 +0000 Subject: [PATCH 09/12] ci: pin GitHub Actions to commit SHAs Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run. --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/publish-npm.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 392da0f..57d308f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/perplexity-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node uses: actions/setup-node@v6 @@ -43,7 +43,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node uses: actions/setup-node@v6 @@ -61,7 +61,7 @@ jobs: github.repository == 'stainless-sdks/perplexity-typescript' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -80,7 +80,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/perplexity-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node uses: actions/setup-node@v6 diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index cf69b78..ffacf56 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -17,7 +17,7 @@ jobs: id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node uses: actions/setup-node@v6 diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index fcfb0ed..0a647c2 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'perplexityai/perplexity-node' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From f73d971af644ff4d3166fe2f0c319a33a85e5e1c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 18:33:46 +0000 Subject: [PATCH 10/12] feat(responses): add people_search and finance_search built-in tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds two new built-in tools to the Responses API: - `people_search`: surfaces structured biographical and professional data (e.g. LinkedIn results) when the model decides to look up a person. - `finance_search`: returns structured financial data (quotes, financials, segments, earnings transcripts) via category-based fan-out to FMP, Finchat, and Quartr. Both tools are zero-config — pass `{"type": "people_search"}` or `{"type": "finance_search"}` in the `tools` array on `responses.create(...)`. --- .stats.yml | 4 ++-- src/resources/responses.ts | 48 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2bc4e3e..7936813 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai/perplexity-ebf1d5e2e90a335c4b7ddf6e0c98b4f69390836ae2dd806ffe255559e51d45b0.yml -openapi_spec_hash: 97d9df5dc228bb6d71be54212bc5b600 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/perplexity-ai/perplexity-cefddb763d493b69465328583ef47cf95655d9cdb3dd0f2c8680fd9679f3c8d8.yml +openapi_spec_hash: 72274397b70c787db6db52dfd34a75ee config_hash: e09a1767e929614701fb498eaaac682d diff --git a/src/resources/responses.ts b/src/resources/responses.ts index 5b7c45c..0deca6b 100644 --- a/src/resources/responses.ts +++ b/src/resources/responses.ts @@ -960,7 +960,13 @@ export interface ResponsesCreateParams { /** * Tools available to the model */ - tools?: Array; + tools?: Array< + | ResponsesCreateParams.WebSearchTool + | ResponsesCreateParams.FetchURLTool + | ResponsesCreateParams.PeopleSearchTool + | FunctionTool + | ResponsesCreateParams.FinanceSearchTool + >; } export namespace ResponsesCreateParams { @@ -1040,6 +1046,22 @@ export namespace ResponsesCreateParams { */ max_urls?: number; } + + export interface PeopleSearchTool { + /** + * Enables the `people_search` tool. + */ + type: 'people_search'; + } + + export interface FinanceSearchTool { + /** + * Enables the `finance_search` tool. The model can request structured financial + * data (quotes, financials, segments, earnings transcripts, etc.) via + * category-based fan-out to FMP, Finchat, and Quartr. + */ + type: 'finance_search'; + } } export interface ResponsesUsage { @@ -1189,7 +1211,13 @@ export interface ResponseCreateParamsBase { /** * Tools available to the model */ - tools?: Array; + tools?: Array< + | ResponseCreateParams.WebSearchTool + | ResponseCreateParams.FetchURLTool + | ResponseCreateParams.PeopleSearchTool + | FunctionTool + | ResponseCreateParams.FinanceSearchTool + >; } export namespace ResponseCreateParams { @@ -1270,6 +1298,22 @@ export namespace ResponseCreateParams { max_urls?: number; } + export interface PeopleSearchTool { + /** + * Enables the `people_search` tool. + */ + type: 'people_search'; + } + + export interface FinanceSearchTool { + /** + * Enables the `finance_search` tool. The model can request structured financial + * data (quotes, financials, segments, earnings transcripts, etc.) via + * category-based fan-out to FMP, Finchat, and Quartr. + */ + type: 'finance_search'; + } + export type ResponseCreateParamsNonStreaming = ResponsesAPI.ResponseCreateParamsNonStreaming; export type ResponseCreateParamsStreaming = ResponsesAPI.ResponseCreateParamsStreaming; } From 147cf3973b774527f0cba6426bb0c963a67befef Mon Sep 17 00:00:00 2001 From: Ryan Buchmayer Date: Wed, 13 May 2026 11:54:03 -0700 Subject: [PATCH 11/12] chore: apply prettier formatting to README --- README.md | 109 +++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index d6c9588..cc1f9da 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ const client = new Perplexity({ }); const search = await client.search.create({ - query: "latest AI developments 2024", - max_results: 5 + query: 'latest AI developments 2024', + max_results: 5, }); for (const result of search.results) { @@ -66,12 +66,8 @@ Run multiple related searches in a single request: ```js const search = await client.search.create({ - query: [ - "renewable energy trends 2024", - "solar power innovations", - "wind energy developments" - ], - max_results: 10 + query: ['renewable energy trends 2024', 'solar power innovations', 'wind energy developments'], + max_results: 10, }); ``` @@ -81,14 +77,9 @@ Limit search results to specific trusted domains: ```js const search = await client.search.create({ - query: "climate change research", - search_domain_filter: [ - "science.org", - "pnas.org", - "cell.com", - "nature.com" - ], - max_results: 10 + query: 'climate change research', + search_domain_filter: ['science.org', 'pnas.org', 'cell.com', 'nature.com'], + max_results: 10, }); ``` @@ -99,15 +90,15 @@ Filter results by recency or specific date ranges: ```js // Get results from the past week const recentSearch = await client.search.create({ - query: "latest AI developments", - search_recency_filter: "week" + query: 'latest AI developments', + search_recency_filter: 'week', }); // Search within a specific date range const dateRangeSearch = await client.search.create({ - query: "AI developments", - search_after_date_filter: "01/01/2024", - search_before_date_filter: "12/31/2024" + query: 'AI developments', + search_after_date_filter: '01/01/2024', + search_before_date_filter: '12/31/2024', }); ``` @@ -117,9 +108,9 @@ Search academic sources for research purposes: ```js const academicSearch = await client.search.create({ - query: "machine learning algorithms", - search_mode: "academic", - max_results: 10 + query: 'machine learning algorithms', + search_mode: 'academic', + max_results: 10, }); ``` @@ -158,16 +149,16 @@ const client = new Perplexity({ // Search API types const searchParams: Perplexity.Search.SearchCreateParams = { - query: "artificial intelligence trends", + query: 'artificial intelligence trends', max_results: 5, - search_mode: "web" + search_mode: 'web', }; const searchResponse: Perplexity.Search.SearchCreateResponse = await client.search.create(searchParams); // Responses API types const responseParams: Perplexity.ResponseCreateParams = { - input: "What is the capital of France?", - model: "sonar", + input: 'What is the capital of France?', + model: 'sonar', }; const response: Perplexity.ResponseCreateResponse = await client.responses.create(responseParams); @@ -189,17 +180,15 @@ a subclass of `APIError` will be thrown: ```ts // Search API error handling -const search = await client.search - .create({ query: "AI developments", max_results: 5 }) - .catch(async (err) => { - if (err instanceof Perplexity.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); +const search = await client.search.create({ query: 'AI developments', max_results: 5 }).catch(async (err) => { + if (err instanceof Perplexity.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } +}); // Chat completions error handling const streamChunk = await client.chat.completions @@ -246,13 +235,19 @@ const client = new Perplexity({ }); // Or, configure per-request: -await client.search.create({ query: "AI developments", max_results: 5 }, { - maxRetries: 5, -}); +await client.search.create( + { query: 'AI developments', max_results: 5 }, + { + maxRetries: 5, + }, +); -await client.chat.completions.create({ messages: [{ role: 'user', content: 'What is the capital of France?' }], model: 'sonar' }, { - maxRetries: 5, -}); +await client.chat.completions.create( + { messages: [{ role: 'user', content: 'What is the capital of France?' }], model: 'sonar' }, + { + maxRetries: 5, + }, +); ``` ### Timeouts @@ -266,13 +261,19 @@ const client = new Perplexity({ }); // Override per-request: -await client.search.create({ query: "AI developments", max_results: 5 }, { - timeout: 5 * 1000, -}); +await client.search.create( + { query: 'AI developments', max_results: 5 }, + { + timeout: 5 * 1000, + }, +); -await client.chat.completions.create({ messages: [{ role: 'user', content: 'What is the capital of France?' }], model: 'sonar' }, { - timeout: 5 * 1000, -}); +await client.chat.completions.create( + { messages: [{ role: 'user', content: 'What is the capital of France?' }], model: 'sonar' }, + { + timeout: 5 * 1000, + }, +); ``` On timeout, an `APIConnectionTimeoutError` is thrown. @@ -293,14 +294,12 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse const client = new Perplexity(); // With search API -const searchResponse = await client.search - .create({ query: "AI developments", max_results: 5 }) - .asResponse(); +const searchResponse = await client.search.create({ query: 'AI developments', max_results: 5 }).asResponse(); console.log(searchResponse.headers.get('X-My-Header')); console.log(searchResponse.statusText); // access the underlying Response object const { data: search, response: rawSearchResponse } = await client.search - .create({ query: "AI developments", max_results: 5 }) + .create({ query: 'AI developments', max_results: 5 }) .withResponse(); console.log(rawSearchResponse.headers.get('X-My-Header')); console.log(search.results.length); From 34e41ebad68e152cb4276b9a0c0c0d33c0a2daca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 18:54:31 +0000 Subject: [PATCH 12/12] release: 0.28.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 +++++++++++++++++++ package.json | 2 +- src/version.ts | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2b11449..9800444 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.27.0" + ".": "0.28.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 6372a0b..508ed4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.28.0 (2026-05-13) + +Full Changelog: [v0.27.0...v0.28.0](https://github.com/perplexityai/perplexity-node/compare/v0.27.0...v0.28.0) + +### Features + +* **responses:** add people_search and finance_search built-in tools ([f73d971](https://github.com/perplexityai/perplexity-node/commit/f73d971af644ff4d3166fe2f0c319a33a85e5e1c)) +* support setting headers via env ([8d99818](https://github.com/perplexityai/perplexity-node/commit/8d99818d6981bc084189213fc03f38408aa4dfe6)) + + +### Chores + +* apply prettier formatting to README ([147cf39](https://github.com/perplexityai/perplexity-node/commit/147cf3973b774527f0cba6426bb0c963a67befef)) +* **format:** run eslint and prettier separately ([bd0078c](https://github.com/perplexityai/perplexity-node/commit/bd0078c41267bf36971c2a621076d07056bd2e13)) +* **formatter:** run prettier and eslint separately ([e5b3c00](https://github.com/perplexityai/perplexity-node/commit/e5b3c0095da82ac41791343a1ba5333ca011fb7f)) +* **internal:** codegen related update ([d99d9e3](https://github.com/perplexityai/perplexity-node/commit/d99d9e316cf824d4a67cd29cb9ac026d63351aca)) +* **internal:** more robust bootstrap script ([c32e68e](https://github.com/perplexityai/perplexity-node/commit/c32e68ee007146374b83abb0901fde46731f0e3d)) +* redact api-key headers in debug logs ([af8b1ee](https://github.com/perplexityai/perplexity-node/commit/af8b1eee91c3ad2fa5f5f1adbb00d836e1560799)) + ## 0.27.0 (2026-04-14) Full Changelog: [v0.26.6...v0.27.0](https://github.com/perplexityai/perplexity-node/compare/v0.26.6...v0.27.0) diff --git a/package.json b/package.json index 70a8daa..83456ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@perplexity-ai/perplexity_ai", - "version": "0.27.0", + "version": "0.28.0", "description": "The official TypeScript library for the Perplexity API", "author": "Perplexity ", "types": "dist/index.d.ts", diff --git a/src/version.ts b/src/version.ts index 288031c..3e76cc4 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.27.0'; // x-release-please-version +export const VERSION = '0.28.0'; // x-release-please-version