diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 8ea34be9..00000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# syntax=docker/dockerfile:1 -FROM debian:bookworm-slim AS stainless - -RUN apt-get update && apt-get install -y \ - nodejs \ - npm \ - yarnpkg \ - && apt-get clean autoclean - -# Ensure UTF-8 encoding -ENV LANG=C.UTF-8 -ENV LC_ALL=C.UTF-8 - -# Yarn -RUN ln -sf /usr/bin/yarnpkg /usr/bin/yarn - -WORKDIR /workspace - -COPY package.json yarn.lock /workspace/ - -RUN yarn install - -COPY . /workspace diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d55fc4d6..763462fa 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,17 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/debian { - "name": "Debian", - "build": { - "dockerfile": "Dockerfile" + "name": "Development", + "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", + "features": { + "ghcr.io/devcontainers/features/node:1": {} + }, + "postCreateCommand": "yarn install", + "customizations": { + "vscode": { + "extensions": [ + "esbenp.prettier-vscode" + ] + } } - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Configure tool-specific properties. - // "customizations": {}, - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3530dcb..0312165a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,4 +63,3 @@ jobs: - name: Run tests run: ./scripts/test - diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d9d5699b..2e1c40ed 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.3" + ".": "0.8.2" } diff --git a/.stats.yml b/.stats.yml index 59ca7083..2f55224c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 10 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-7632a025f14cf4ef9630966e00cb47fd93e8b43f1e9111f3917eb5adf145f0dd.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/hyperspell%2Fhyperspell-c562e6864fc7607b8a6ff45ad2abaf22344660501695ee0270350b37bbbf3bdf.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7957907c..2b0e70e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,48 @@ # Changelog +## 0.8.2 (2025-03-26) + +Full Changelog: [v0.5.3...v0.8.2](https://github.com/hyperspell/node-sdk/compare/v0.5.3...v0.8.2) + +### Features + +* add SKIP_BREW env var to ./scripts/bootstrap ([#32](https://github.com/hyperspell/node-sdk/issues/32)) ([ecdef89](https://github.com/hyperspell/node-sdk/commit/ecdef891f2210522efe31e5120d26ad572432f3b)) +* **api:** api update ([a9f4767](https://github.com/hyperspell/node-sdk/commit/a9f47673364b5e8f8b2fcfee54b2c7a22eca9d2b)) +* **api:** api update ([#23](https://github.com/hyperspell/node-sdk/issues/23)) ([c9aaf54](https://github.com/hyperspell/node-sdk/commit/c9aaf54d0505676b9cc6a75af87a9994cca2f5b3)) +* **api:** api update ([#24](https://github.com/hyperspell/node-sdk/issues/24)) ([5326693](https://github.com/hyperspell/node-sdk/commit/53266933ad271b9f2f00b7c7e3607eb91f65b7f4)) +* **api:** api update ([#25](https://github.com/hyperspell/node-sdk/issues/25)) ([fdc83d1](https://github.com/hyperspell/node-sdk/commit/fdc83d13e6e6d4de12378b219a3ed6b790c66466)) +* **api:** api update ([#26](https://github.com/hyperspell/node-sdk/issues/26)) ([eef40b4](https://github.com/hyperspell/node-sdk/commit/eef40b4f33a39ad5a7887669414a4efdd3303f80)) +* **api:** api update ([#42](https://github.com/hyperspell/node-sdk/issues/42)) ([9e25c59](https://github.com/hyperspell/node-sdk/commit/9e25c59176277df1cd2999ed875968d68137f93d)) +* **api:** update via SDK Studio ([#20](https://github.com/hyperspell/node-sdk/issues/20)) ([4a2c34a](https://github.com/hyperspell/node-sdk/commit/4a2c34a97b3e2131ac1c0f6f392d54962bc50f62)) +* **api:** update via SDK Studio ([#38](https://github.com/hyperspell/node-sdk/issues/38)) ([61373c8](https://github.com/hyperspell/node-sdk/commit/61373c843629c169d69c4dd133d5b3a9899a230f)) +* **api:** update via SDK Studio ([#39](https://github.com/hyperspell/node-sdk/issues/39)) ([a0ce99a](https://github.com/hyperspell/node-sdk/commit/a0ce99aae41fa41ad8bde420f00870ce647ff5d1)) +* **api:** update via SDK Studio ([#40](https://github.com/hyperspell/node-sdk/issues/40)) ([5614b84](https://github.com/hyperspell/node-sdk/commit/5614b84d9d2f34d59ba1b61dc43dd7ce4a143d3a)) +* **api:** update via SDK Studio ([#41](https://github.com/hyperspell/node-sdk/issues/41)) ([6f9da54](https://github.com/hyperspell/node-sdk/commit/6f9da54a9104bbaab340cfb230f4217fdc8ec4ed)) +* **api:** update via SDK Studio ([#43](https://github.com/hyperspell/node-sdk/issues/43)) ([588ad3b](https://github.com/hyperspell/node-sdk/commit/588ad3b6267ca1509e01babedaa2ff89c830bbc0)) +* **client:** accept RFC6838 JSON content types ([#33](https://github.com/hyperspell/node-sdk/issues/33)) ([ca38adc](https://github.com/hyperspell/node-sdk/commit/ca38adc6b3125f68d682462e42f7c79ac0d65da1)) +* **client:** send `X-Stainless-Timeout` header ([#22](https://github.com/hyperspell/node-sdk/issues/22)) ([4ad8147](https://github.com/hyperspell/node-sdk/commit/4ad814769ef6503eb9b5a51c14d1ea3f74c736c5)) + + +### Bug Fixes + +* avoid type error in certain environments ([#37](https://github.com/hyperspell/node-sdk/issues/37)) ([42542b9](https://github.com/hyperspell/node-sdk/commit/42542b91e05ae3543112c21eae0c110158b753e5)) +* **client:** fix export map for index exports ([#27](https://github.com/hyperspell/node-sdk/issues/27)) ([5543d8e](https://github.com/hyperspell/node-sdk/commit/5543d8ea3804070de726997e8474deb01318eb68)) + + +### Chores + +* **exports:** cleaner resource index imports ([#35](https://github.com/hyperspell/node-sdk/issues/35)) ([641f5b3](https://github.com/hyperspell/node-sdk/commit/641f5b3a2311b4db0c16d4555e6073a502c94226)) +* **exports:** stop using path fallbacks ([#36](https://github.com/hyperspell/node-sdk/issues/36)) ([801d961](https://github.com/hyperspell/node-sdk/commit/801d961baa29194a1ecc3656305297e893fb2bb0)) +* **internal:** codegen related update ([#28](https://github.com/hyperspell/node-sdk/issues/28)) ([44c69e8](https://github.com/hyperspell/node-sdk/commit/44c69e887a6e32339a487e28e14e444e68ac32c5)) +* **internal:** codegen related update ([#31](https://github.com/hyperspell/node-sdk/issues/31)) ([2b286c1](https://github.com/hyperspell/node-sdk/commit/2b286c14f6545cfaf65259fabc051c40dbe336e7)) +* **internal:** fix devcontainers setup ([#29](https://github.com/hyperspell/node-sdk/issues/29)) ([26194ce](https://github.com/hyperspell/node-sdk/commit/26194ce3891b4f5e6bc89d13a7e8c85137dfe731)) +* **internal:** remove extra empty newlines ([#34](https://github.com/hyperspell/node-sdk/issues/34)) ([3677c0c](https://github.com/hyperspell/node-sdk/commit/3677c0c5673c2f49e7f37072be45aad49f1ee5d6)) + + +### Documentation + +* update URLs from stainlessapi.com to stainless.com ([#30](https://github.com/hyperspell/node-sdk/issues/30)) ([f9c0492](https://github.com/hyperspell/node-sdk/commit/f9c04926d82f1f863e6e111feb3b6e4ab33ff0bf)) + ## 0.5.3 (2025-02-04) Full Changelog: [v0.1.0-alpha.2...v0.5.3](https://github.com/hyperspell/node-sdk/compare/v0.1.0-alpha.2...v0.5.3) diff --git a/README.md b/README.md index 7e6295f8..cebc744b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This library provides convenient access to the Hyperspell REST API from server-s The REST API documentation can be found on [docs.hyperspell.com](https://docs.hyperspell.com/). The full API of this library can be found in [api.md](api.md). -It is generated with [Stainless](https://www.stainlessapi.com/). +It is generated with [Stainless](https://www.stainless.com/). ## Installation @@ -27,7 +27,7 @@ const client = new Hyperspell({ }); async function main() { - const documentStatus = await client.documents.add({ collection: 'collection', text: 'text' }); + const documentStatus = await client.documents.add({ text: 'text' }); console.log(documentStatus.id); } @@ -48,7 +48,7 @@ const client = new Hyperspell({ }); async function main() { - const params: Hyperspell.DocumentAddParams = { collection: 'collection', text: 'text' }; + const params: Hyperspell.DocumentAddParams = { text: 'text' }; const documentStatus: Hyperspell.DocumentStatus = await client.documents.add(params); } @@ -57,6 +57,42 @@ main(); Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. +## File uploads + +Request parameters that correspond to file uploads can be passed in many different forms: + +- `File` (or an object with the same structure) +- a `fetch` `Response` (or an object with the same structure) +- an `fs.ReadStream` +- the return value of our `toFile` helper + +```ts +import fs from 'fs'; +import fetch from 'node-fetch'; +import Hyperspell, { toFile } from 'hyperspell'; + +const client = new Hyperspell(); + +// If you have access to Node `fs` we recommend using `fs.createReadStream()`: +await client.documents.upload({ collection: 'collection', file: fs.createReadStream('/path/to/file') }); + +// Or if you have the web `File` API you can pass a `File` instance: +await client.documents.upload({ collection: 'collection', file: new File(['my bytes'], 'file') }); + +// You can also pass a `fetch` `Response`: +await client.documents.upload({ collection: 'collection', file: await fetch('https://somesite/file') }); + +// Finally, if none of the above are convenient, you can use our `toFile` helper: +await client.documents.upload({ + collection: 'collection', + file: await toFile(Buffer.from('my bytes'), 'file'), +}); +await client.documents.upload({ + collection: 'collection', + file: await toFile(new Uint8Array([0, 1, 2]), 'file'), +}); +``` + ## Handling errors When the library is unable to connect to the API, @@ -66,17 +102,15 @@ a subclass of `APIError` will be thrown: ```ts async function main() { - const documentStatus = await client.documents - .add({ collection: 'collection', text: 'text' }) - .catch(async (err) => { - if (err instanceof Hyperspell.APIError) { - console.log(err.status); // 400 - console.log(err.name); // BadRequestError - console.log(err.headers); // {server: 'nginx', ...} - } else { - throw err; - } - }); + const documentStatus = await client.documents.add({ text: 'text' }).catch(async (err) => { + if (err instanceof Hyperspell.APIError) { + console.log(err.status); // 400 + console.log(err.name); // BadRequestError + console.log(err.headers); // {server: 'nginx', ...} + } else { + throw err; + } + }); } main(); @@ -111,7 +145,7 @@ const client = new Hyperspell({ }); // Or, configure per-request: -await client.documents.add({ collection: 'collection', text: 'text' }, { +await client.documents.add({ text: 'text' }, { maxRetries: 5, }); ``` @@ -128,7 +162,7 @@ const client = new Hyperspell({ }); // Override per-request: -await client.documents.add({ collection: 'collection', text: 'text' }, { +await client.documents.add({ text: 'text' }, { timeout: 5 * 1000, }); ``` @@ -180,13 +214,11 @@ You can also use the `.withResponse()` method to get the raw `Response` along wi ```ts const client = new Hyperspell(); -const response = await client.documents.add({ collection: 'collection', text: 'text' }).asResponse(); +const response = await client.documents.add({ text: 'text' }).asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: documentStatus, response: raw } = await client.documents - .add({ collection: 'collection', text: 'text' }) - .withResponse(); +const { data: documentStatus, response: raw } = await client.documents.add({ text: 'text' }).withResponse(); console.log(raw.headers.get('X-My-Header')); console.log(documentStatus.id); ``` @@ -293,7 +325,7 @@ const client = new Hyperspell({ // Override per-request: await client.documents.add( - { collection: 'collection', text: 'text' }, + { text: 'text' }, { httpAgent: new http.Agent({ keepAlive: false }), }, diff --git a/SECURITY.md b/SECURITY.md index 19b33727..4b274355 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,9 +2,9 @@ ## Reporting Security Issues -This SDK is generated by [Stainless Software Inc](http://stainlessapi.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. -To report a security issue, please contact the Stainless team at security@stainlessapi.com. +To report a security issue, please contact the Stainless team at security@stainless.com. ## Responsible Disclosure diff --git a/api.md b/api.md index 8fb61c26..0f6cb222 100644 --- a/api.md +++ b/api.md @@ -4,6 +4,7 @@ Types: - Document - DocumentStatus +- Scores - DocumentListResponse Methods: diff --git a/package.json b/package.json index d8b338a9..22c4b6d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hyperspell", - "version": "0.5.3", + "version": "0.8.2", "description": "The official TypeScript library for the Hyperspell API", "author": "Hyperspell ", "types": "dist/index.d.ts", diff --git a/scripts/bootstrap b/scripts/bootstrap index 05dd47a6..0af58e25 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then brew bundle check >/dev/null 2>&1 || { echo "==> Installing Homebrew dependencies…" brew bundle diff --git a/src/core.ts b/src/core.ts index 62af19dc..5a2112d7 100644 --- a/src/core.ts +++ b/src/core.ts @@ -48,8 +48,8 @@ async function defaultParseResponse(props: APIResponseProps): Promise { } const contentType = response.headers.get('content-type'); - const isJSON = - contentType?.includes('application/json') || contentType?.includes('application/vnd.api+json'); + const mediaType = contentType?.split(';')[0]?.trim(); + const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json'); if (isJSON) { const json = await response.json(); @@ -280,6 +280,7 @@ export abstract class APIClient { options: FinalRequestOptions, { retryCount = 0 }: { retryCount?: number } = {}, ): { req: RequestInit; url: string; timeout: number } { + options = { ...options }; const { method, path, query, headers: headers = {} } = options; const body = @@ -292,9 +293,9 @@ export abstract class APIClient { const url = this.buildURL(path!, query); if ('timeout' in options) validatePositiveInteger('timeout', options.timeout); - const timeout = options.timeout ?? this.timeout; + options.timeout = options.timeout ?? this.timeout; const httpAgent = options.httpAgent ?? this.httpAgent ?? getDefaultAgent(url); - const minAgentTimeout = timeout + 1000; + const minAgentTimeout = options.timeout + 1000; if ( typeof (httpAgent as any)?.options?.timeout === 'number' && minAgentTimeout > ((httpAgent as any).options.timeout ?? 0) @@ -323,7 +324,7 @@ export abstract class APIClient { signal: options.signal ?? null, }; - return { req, url, timeout }; + return { req, url, timeout: options.timeout }; } private buildHeaders({ @@ -351,15 +352,22 @@ export abstract class APIClient { delete reqHeaders['content-type']; } - // Don't set the retry count header if it was already set or removed through default headers or by the - // caller. We check `defaultHeaders` and `headers`, which can contain nulls, instead of `reqHeaders` to - // account for the removal case. + // Don't set theses headers if they were already set or removed through default headers or by the caller. + // We check `defaultHeaders` and `headers`, which can contain nulls, instead of `reqHeaders` to account + // for the removal case. if ( getHeader(defaultHeaders, 'x-stainless-retry-count') === undefined && getHeader(headers, 'x-stainless-retry-count') === undefined ) { reqHeaders['x-stainless-retry-count'] = String(retryCount); } + if ( + getHeader(defaultHeaders, 'x-stainless-timeout') === undefined && + getHeader(headers, 'x-stainless-timeout') === undefined && + options.timeout + ) { + reqHeaders['x-stainless-timeout'] = String(options.timeout); + } this.validateHeaders(reqHeaders, headers); @@ -387,7 +395,7 @@ export abstract class APIClient { !headers ? {} : Symbol.iterator in headers ? Object.fromEntries(Array.from(headers as Iterable).map((header) => [...header])) - : { ...headers } + : { ...(headers as any as Record) } ); } diff --git a/src/index.ts b/src/index.ts index 195475e6..65d13647 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,6 +26,7 @@ import { DocumentStatus, DocumentUploadParams, Documents, + Scores, } from './resources/documents'; import { Query, QuerySearchParams, QuerySearchResponse } from './resources/query'; @@ -209,6 +210,7 @@ export declare namespace Hyperspell { Documents as Documents, type Document as Document, type DocumentStatus as DocumentStatus, + type Scores as Scores, type DocumentListResponse as DocumentListResponse, DocumentListResponsesCursorPage as DocumentListResponsesCursorPage, type DocumentListParams as DocumentListParams, diff --git a/src/pagination.ts b/src/pagination.ts index 09e20afb..1bf82aba 100644 --- a/src/pagination.ts +++ b/src/pagination.ts @@ -53,7 +53,7 @@ export class CursorPage extends AbstractPage implements CursorPageRe return { params: { - cursor: cursor, + cursor, }, }; } diff --git a/src/resources.ts b/src/resources.ts new file mode 100644 index 00000000..b283d578 --- /dev/null +++ b/src/resources.ts @@ -0,0 +1 @@ +export * from './resources/index'; diff --git a/src/resources/documents.ts b/src/resources/documents.ts index df7f83d7..c8470507 100644 --- a/src/resources/documents.ts +++ b/src/resources/documents.ts @@ -1,7 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../resource'; +import { isRequestOptions } from '../core'; import * as Core from '../core'; +import * as DocumentsAPI from './documents'; import { CursorPage, type CursorPageParams } from '../pagination'; export class Documents extends APIResource { @@ -10,9 +12,19 @@ export class Documents extends APIResource { * filter the documents by title, date, metadata, etc. */ list( - query: DocumentListParams, + query?: DocumentListParams, + options?: Core.RequestOptions, + ): Core.PagePromise; + list( + options?: Core.RequestOptions, + ): Core.PagePromise; + list( + query: DocumentListParams | Core.RequestOptions = {}, options?: Core.RequestOptions, ): Core.PagePromise { + if (isRequestOptions(query)) { + return this.list({}, query); + } return this._client.getAPIList('/documents/list', DocumentListResponsesCursorPage, { query, ...options }); } @@ -57,6 +69,16 @@ export class DocumentListResponsesCursorPage extends CursorPage; + + /** + * Summary of the document + */ + summary: string; + id?: number | null; created_at?: string | null; @@ -70,9 +92,13 @@ export interface Document { */ resource_id?: string; - sections?: Array; + source?: 'generic' | 'slack' | 's3' | 'gmail' | 'notion' | 'google_docs' | 'hubspot'; + + status?: 'pending' | 'processing' | 'completed' | 'failed'; + + title?: string | null; - source?: + type?: | 'generic' | 'markdown' | 'chat' @@ -83,107 +109,18 @@ export interface Document { | 'image' | 'pdf' | 'audio' - | 'slack' - | 's3' - | 'gmail' - | 'notion' - | 'google_docs'; - - status?: 'pending' | 'processing' | 'completed' | 'failed'; - - title?: string | null; -} - -export namespace Document { - export interface SectionResult { - id?: number | null; - - scores?: SectionResult.Scores; - - text?: string; - } - - export namespace SectionResult { - export interface Scores { - /** - * How relevant the section is based on full text search - */ - full_text_search?: number | null; - - /** - * How relevant the section is based on vector search - */ - semantic_search?: number | null; - - /** - * The final weighted score of the section - */ - weighted?: number | null; - } - } - - export interface SectionResultWithElements { - id?: number | null; - - elements?: Array; - - scores?: SectionResultWithElements.Scores; - - text?: string; - } - - export namespace SectionResultWithElements { - export interface Element { - text: string; - - type: 'text' | 'markdown' | 'image' | 'table' | 'title' | 'query'; - - id?: string; - - metadata?: Element.Metadata; - - summary?: string | null; - } - - export namespace Element { - export interface Metadata { - author?: string | null; - - /** - * The id of the element that this element is continued from if it had to be split - * during chunking - */ - continued_from?: string | null; - - filename?: string | null; - - languages?: Array; - - links?: Array; - - page_number?: number | null; - - title_level?: number | null; - } - } - - export interface Scores { - /** - * How relevant the section is based on full text search - */ - full_text_search?: number | null; - - /** - * How relevant the section is based on vector search - */ - semantic_search?: number | null; - - /** - * The final weighted score of the section - */ - weighted?: number | null; - } - } + | 'spreadsheet' + | 'archive' + | 'book' + | 'video' + | 'code' + | 'calendar' + | 'json' + | 'presentation' + | 'unsupported' + | 'person' + | 'company' + | 'crm_contact'; } export interface DocumentStatus { @@ -194,13 +131,42 @@ export interface DocumentStatus { status: 'pending' | 'processing' | 'completed' | 'failed'; } +export interface Scores { + /** + * How relevant the section is based on full text search + */ + full_text_search?: number | null; + + /** + * How relevant the section is based on vector search + */ + semantic_search?: number | null; + + /** + * The final weighted score of the section + */ + weighted?: number | null; +} + export interface DocumentListResponse { + /** + * Structured representation of the document + */ + data: unknown | Array; + + /** + * Summary of the document + */ + summary: string; + id?: number | null; collection?: string; created_at?: string | null; + events?: Array; + ingested_at?: string | null; metadata?: Record; @@ -214,7 +180,13 @@ export interface DocumentListResponse { sections_count?: number | null; - source?: + source?: 'generic' | 'slack' | 's3' | 'gmail' | 'notion' | 'google_docs' | 'hubspot'; + + status?: 'pending' | 'processing' | 'completed' | 'failed'; + + title?: string | null; + + type?: | 'generic' | 'markdown' | 'chat' @@ -225,105 +197,69 @@ export interface DocumentListResponse { | 'image' | 'pdf' | 'audio' - | 'slack' - | 's3' - | 'gmail' - | 'notion' - | 'google_docs'; - - status?: 'pending' | 'processing' | 'completed' | 'failed'; - - title?: string | null; + | 'spreadsheet' + | 'archive' + | 'book' + | 'video' + | 'code' + | 'calendar' + | 'json' + | 'presentation' + | 'unsupported' + | 'person' + | 'company' + | 'crm_contact'; } export namespace DocumentListResponse { - export interface Section { - document_id: number; + export interface Event { + message: string; - id?: number | null; - - elements?: Array; - - embedding_e5_large?: Array | null; - - embedding_ts?: string | null; - - metadata?: Record; + type: 'error' | 'warning' | 'info'; - scores?: Section.Scores; - - text?: string; + time?: string; } - export namespace Section { - export interface Element { - text: string; - - type: 'text' | 'markdown' | 'image' | 'table' | 'title' | 'query'; - - id?: string; - - metadata?: Element.Metadata; - - summary?: string | null; - } + export interface Section { + document_id: number; - export namespace Element { - export interface Metadata { - author?: string | null; + /** + * Summary of the section + */ + text: string; - /** - * The id of the element that this element is continued from if it had to be split - * during chunking - */ - continued_from?: string | null; + id?: number | null; - filename?: string | null; + content?: string | null; - languages?: Array; + elements?: Array; - links?: Array; + embedding_e5_large?: Array | null; - page_number?: number | null; + embedding_ts?: string | null; - title_level?: number | null; - } - } + metadata?: Record; - export interface Scores { - /** - * How relevant the section is based on full text search - */ - full_text_search?: number | null; - - /** - * How relevant the section is based on vector search - */ - semantic_search?: number | null; - - /** - * The final weighted score of the section - */ - weighted?: number | null; - } + scores?: DocumentsAPI.Scores; } } export interface DocumentListParams extends CursorPageParams { - collection: string; + collection?: string | null; } export interface DocumentAddParams { /** - * Name of the collection to add the document to. If the collection does not exist, - * it will be created. + * Full text of the document. */ - collection: string; + text: string; /** - * Full text of the document. + * Name of the collection to add the document to. If the collection does not exist, + * it will be created. If not given, the document will be added to the user's + * default collection. */ - text: string; + collection?: string | null; /** * Date of the document. Depending on the document, this could be the creation date @@ -337,22 +273,7 @@ export interface DocumentAddParams { * Source of the document. This helps in parsing the document. Note that some * sources require the document to be in a specific format. */ - source?: - | 'generic' - | 'markdown' - | 'chat' - | 'email' - | 'transcript' - | 'legal' - | 'website' - | 'image' - | 'pdf' - | 'audio' - | 'slack' - | 's3' - | 'gmail' - | 'notion' - | 'google_docs'; + source?: 'generic' | 'slack' | 's3' | 'gmail' | 'notion' | 'google_docs' | 'hubspot'; /** * Title of the document. @@ -362,21 +283,27 @@ export interface DocumentAddParams { export interface DocumentAddURLParams { /** - * Name of the collection to add the document to. If the collection does not exist, - * it will be created. + * Source URL of the document. */ - collection: string; + url: string; /** - * Source URL of the document. If text is not provided and URL is publicly - * accessible, Hyperspell will retrieve the document from this URL. + * Name of the collection to add the document to. If the collection does not exist, + * it will be created. If not given, the document will be added to the user's + * default collection. */ - url?: string | null; + collection?: string | null; } export interface DocumentUploadParams { + /** + * The collection to add the document to. + */ collection: string; + /** + * The file to ingest. + */ file: Core.Uploadable; } @@ -386,6 +313,7 @@ export declare namespace Documents { export { type Document as Document, type DocumentStatus as DocumentStatus, + type Scores as Scores, type DocumentListResponse as DocumentListResponse, DocumentListResponsesCursorPage as DocumentListResponsesCursorPage, type DocumentListParams as DocumentListParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index bf196d87..d6b05f12 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -14,6 +14,7 @@ export { Documents, type Document, type DocumentStatus, + type Scores, type DocumentListResponse, type DocumentListParams, type DocumentAddParams, diff --git a/src/resources/query.ts b/src/resources/query.ts index 9397ed5f..93b49c32 100644 --- a/src/resources/query.ts +++ b/src/resources/query.ts @@ -26,9 +26,10 @@ export interface QuerySearchParams { query: string; /** - * Only query documents in these collections. + * Only query documents in these collections. If not given, will query the user's + * default collection */ - collections?: Array; + collections?: string | Array | null; /** * Filter the query results. @@ -61,10 +62,20 @@ export namespace QuerySearchParams { */ end_date?: string | null; + /** + * Only query documents from these sources. + */ + source?: Array<'generic' | 'slack' | 's3' | 'gmail' | 'notion' | 'google_docs' | 'hubspot'>; + + /** + * Only query documents on or after this date. + */ + start_date?: string | null; + /** * Only query documents of these types. */ - source?: Array< + types?: Array< | 'generic' | 'markdown' | 'chat' @@ -75,17 +86,19 @@ export namespace QuerySearchParams { | 'image' | 'pdf' | 'audio' - | 'slack' - | 's3' - | 'gmail' - | 'notion' - | 'google_docs' + | 'spreadsheet' + | 'archive' + | 'book' + | 'video' + | 'code' + | 'calendar' + | 'json' + | 'presentation' + | 'unsupported' + | 'person' + | 'company' + | 'crm_contact' >; - - /** - * Only query documents on or after this date. - */ - start_date?: string | null; } } diff --git a/src/version.ts b/src/version.ts index 80cb290b..72b24dd1 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.5.3'; // x-release-please-version +export const VERSION = '0.8.2'; // x-release-please-version diff --git a/tests/api-resources/documents.test.ts b/tests/api-resources/documents.test.ts index 7bba8f9f..851cdebf 100644 --- a/tests/api-resources/documents.test.ts +++ b/tests/api-resources/documents.test.ts @@ -9,8 +9,8 @@ const client = new Hyperspell({ }); describe('resource documents', () => { - test('list: only required params', async () => { - const responsePromise = client.documents.list({ collection: 'collection' }); + test('list', async () => { + const responsePromise = client.documents.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -20,12 +20,25 @@ describe('resource documents', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - test('list: required and optional params', async () => { - const response = await client.documents.list({ collection: 'collection', cursor: 'cursor', size: 0 }); + test('list: request options instead of params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect(client.documents.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( + Hyperspell.NotFoundError, + ); + }); + + test('list: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.documents.list( + { collection: 'collection', cursor: 'cursor', size: 0 }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(Hyperspell.NotFoundError); }); test('add: only required params', async () => { - const responsePromise = client.documents.add({ collection: 'collection', text: 'text' }); + const responsePromise = client.documents.add({ text: 'text' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -37,8 +50,8 @@ describe('resource documents', () => { test('add: required and optional params', async () => { const response = await client.documents.add({ - collection: 'collection', text: 'text', + collection: 'collection', date: '2019-12-27T18:11:19.117Z', source: 'generic', title: 'title', @@ -46,7 +59,7 @@ describe('resource documents', () => { }); test('addURL: only required params', async () => { - const responsePromise = client.documents.addURL({ collection: 'collection' }); + const responsePromise = client.documents.addURL({ url: 'url' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -57,7 +70,7 @@ describe('resource documents', () => { }); test('addURL: required and optional params', async () => { - const response = await client.documents.addURL({ collection: 'collection', url: 'url' }); + const response = await client.documents.addURL({ url: 'url', collection: 'collection' }); }); test('get', async () => { diff --git a/tests/api-resources/query.test.ts b/tests/api-resources/query.test.ts index cad0704a..886dd8a3 100644 --- a/tests/api-resources/query.test.ts +++ b/tests/api-resources/query.test.ts @@ -23,11 +23,12 @@ describe('resource query', () => { test('search: required and optional params', async () => { const response = await client.query.search({ query: 'query', - collections: ['string'], + collections: 'string', filter: { end_date: '2019-12-27T18:11:19.117Z', source: ['generic'], start_date: '2019-12-27T18:11:19.117Z', + types: ['generic'], }, include_elements: true, max_results: 0,