├── .DS_Store ├── .devcontainer └── devcontainer.json ├── .eslintrc.js ├── .github └── workflows │ ├── ci.yml │ ├── publish-npm.yml │ └── release-doctor.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .release-please-manifest.json ├── .stats.yml ├── Brewfile ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── api.md ├── bin ├── check-release-environment └── publish-npm ├── examples ├── .keep ├── chat-completions.ts ├── coqa.jsonl ├── embedding.ts ├── files.ts ├── fine-tune.ts ├── image.ts ├── models.ts ├── sample_finetuning.jsonl ├── streaming.ts └── uploading-files.ts ├── jest.config.ts ├── package.json ├── release-please-config.json ├── scripts ├── bootstrap ├── build ├── format ├── lint ├── mock ├── test └── utils │ ├── check-is-in-git-install.sh │ ├── check-version.cjs │ ├── fix-index-exports.cjs │ ├── git-swap.sh │ ├── make-dist-package-json.cjs │ ├── postprocess-files.cjs │ └── upload-artifact.sh ├── src ├── _shims │ ├── MultipartBody.ts │ ├── README.md │ ├── auto │ │ ├── runtime-bun.ts │ │ ├── runtime-deno.ts │ │ ├── runtime-node.ts │ │ ├── runtime.ts │ │ ├── types-deno.ts │ │ ├── types-node.ts │ │ ├── types.d.ts │ │ ├── types.js │ │ └── types.mjs │ ├── bun-runtime.ts │ ├── index-deno.ts │ ├── index.d.ts │ ├── index.js │ ├── index.mjs │ ├── manual-types.d.ts │ ├── manual-types.js │ ├── manual-types.mjs │ ├── node-runtime.ts │ ├── node-types.d.ts │ ├── node-types.js │ ├── node-types.mjs │ ├── registry.ts │ ├── web-runtime.ts │ ├── web-types.d.ts │ ├── web-types.js │ └── web-types.mjs ├── core.ts ├── error.ts ├── index.ts ├── internal │ ├── decoders │ │ └── line.ts │ └── stream-utils.ts ├── lib │ ├── .keep │ ├── AbstractChatCompletionRunner.ts │ ├── ChatCompletionRunner.ts │ ├── ChatCompletionStream.ts │ ├── ChatCompletionStreamingRunner.ts │ ├── RunnableFunction.ts │ ├── chatCompletionUtils.ts │ ├── jsonschema.ts │ └── upload.ts ├── resource.ts ├── resources.ts ├── resources │ ├── audio.ts │ ├── chat.ts │ ├── chat │ │ ├── chat.ts │ │ ├── completions.ts │ │ └── index.ts │ ├── code-interpreter.ts │ ├── code-interpreter │ │ ├── code-interpreter.ts │ │ ├── index.ts │ │ └── sessions.ts │ ├── completions.ts │ ├── embeddings.ts │ ├── endpoints.ts │ ├── files.ts │ ├── fine-tune.ts │ ├── hardware.ts │ ├── images.ts │ ├── index.ts │ ├── jobs.ts │ ├── models.ts │ └── top-level.ts ├── shims │ ├── node.ts │ └── web.ts ├── streaming.ts ├── uploads.ts └── version.ts ├── tests ├── api-resources │ ├── audio.test.ts │ ├── chat │ │ └── completions.test.ts │ ├── code-interpreter │ │ ├── code-interpreter.test.ts │ │ └── sessions.test.ts │ ├── completions.test.ts │ ├── embeddings.test.ts │ ├── endpoints.test.ts │ ├── files.test.ts │ ├── fine-tune.test.ts │ ├── hardware.test.ts │ ├── images.test.ts │ ├── jobs.test.ts │ ├── models.test.ts │ └── top-level.test.ts ├── form.test.ts ├── index.test.ts ├── internal │ └── decoders │ │ └── line.test.ts ├── responses.test.ts ├── streaming.test.ts ├── stringifyQuery.test.ts └── uploads.test.ts ├── tsc-multi.json ├── tsconfig.build.json ├── tsconfig.deno.json ├── tsconfig.dist-src.json ├── tsconfig.json └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/togethercomputer/together-typescript/c92d34bc8262bff01856bb5ba5b23e3b6c562774/.DS_Store -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/debian 3 | { 4 | "name": "Development", 5 | "image": "mcr.microsoft.com/devcontainers/typescript-node:latest", 6 | "features": { 7 | "ghcr.io/devcontainers/features/node:1": {} 8 | }, 9 | "postCreateCommand": "yarn install", 10 | "customizations": { 11 | "vscode": { 12 | "extensions": [ 13 | "esbenp.prettier-vscode" 14 | ] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['@typescript-eslint', 'unused-imports', 'prettier'], 4 | rules: { 5 | 'no-unused-vars': 'off', 6 | 'prettier/prettier': 'error', 7 | 'unused-imports/no-unused-imports': 'error', 8 | }, 9 | root: true, 10 | }; 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches-ignore: 5 | - 'generated' 6 | - 'codegen/**' 7 | - 'integrated/**' 8 | - 'stl-preview-head/**' 9 | - 'stl-preview-base/**' 10 | 11 | jobs: 12 | lint: 13 | timeout-minutes: 10 14 | name: lint 15 | runs-on: ${{ github.repository == 'stainless-sdks/togetherai-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Set up Node 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: '18' 23 | 24 | - name: Bootstrap 25 | run: ./scripts/bootstrap 26 | 27 | - name: Check types 28 | run: ./scripts/lint 29 | 30 | build: 31 | timeout-minutes: 5 32 | name: build 33 | runs-on: ${{ github.repository == 'stainless-sdks/togetherai-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 34 | permissions: 35 | contents: read 36 | id-token: write 37 | steps: 38 | - uses: actions/checkout@v4 39 | 40 | - name: Set up Node 41 | uses: actions/setup-node@v4 42 | with: 43 | node-version: '18' 44 | 45 | - name: Bootstrap 46 | run: ./scripts/bootstrap 47 | 48 | - name: Check build 49 | run: ./scripts/build 50 | 51 | - name: Get GitHub OIDC Token 52 | if: github.repository == 'stainless-sdks/togetherai-node' 53 | id: github-oidc 54 | uses: actions/github-script@v6 55 | with: 56 | script: core.setOutput('github_token', await core.getIDToken()); 57 | 58 | - name: Upload tarball 59 | if: github.repository == 'stainless-sdks/togetherai-node' 60 | env: 61 | URL: https://pkg.stainless.com/s 62 | AUTH: ${{ steps.github-oidc.outputs.github_token }} 63 | SHA: ${{ github.sha }} 64 | run: ./scripts/utils/upload-artifact.sh 65 | test: 66 | timeout-minutes: 10 67 | name: test 68 | runs-on: ${{ github.repository == 'stainless-sdks/togetherai-node' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} 69 | steps: 70 | - uses: actions/checkout@v4 71 | 72 | - name: Set up Node 73 | uses: actions/setup-node@v4 74 | with: 75 | node-version: '18' 76 | 77 | - name: Bootstrap 78 | run: ./scripts/bootstrap 79 | 80 | - name: Run tests 81 | run: ./scripts/test 82 | -------------------------------------------------------------------------------- /.github/workflows/publish-npm.yml: -------------------------------------------------------------------------------- 1 | # This workflow is triggered when a GitHub release is created. 2 | # It can also be run manually to re-publish to NPM in case it failed for some reason. 3 | # You can run this workflow by navigating to https://www.github.com/togethercomputer/together-typescript/actions/workflows/publish-npm.yml 4 | name: Publish NPM 5 | on: 6 | workflow_dispatch: 7 | 8 | release: 9 | types: [published] 10 | 11 | jobs: 12 | publish: 13 | name: publish 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Set up Node 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: '18' 23 | 24 | - name: Install dependencies 25 | run: | 26 | yarn install 27 | 28 | - name: Publish to NPM 29 | run: | 30 | bash ./bin/publish-npm 31 | env: 32 | NPM_TOKEN: ${{ secrets.TOGETHER_NPM_TOKEN || secrets.NPM_TOKEN }} 33 | -------------------------------------------------------------------------------- /.github/workflows/release-doctor.yml: -------------------------------------------------------------------------------- 1 | name: Release Doctor 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | release_doctor: 10 | name: release doctor 11 | runs-on: ubuntu-latest 12 | if: github.repository == 'togethercomputer/together-typescript' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Check release environment 18 | run: | 19 | bash ./bin/check-release-environment 20 | env: 21 | NPM_TOKEN: ${{ secrets.TOGETHER_NPM_TOKEN || secrets.NPM_TOKEN }} 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .prism.log 2 | node_modules 3 | yarn-error.log 4 | codegen.log 5 | Brewfile.lock.json 6 | dist 7 | dist-deno 8 | /*.tgz 9 | .idea/ 10 | 11 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | /ecosystem-tests/*/** 3 | /node_modules 4 | /deno 5 | 6 | # don't format tsc output, will break source maps 7 | /dist 8 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "experimentalTernaries": true, 4 | "printWidth": 110, 5 | "singleQuote": true, 6 | "trailingComma": "all" 7 | } 8 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.16.0" 3 | } 4 | -------------------------------------------------------------------------------- /.stats.yml: -------------------------------------------------------------------------------- 1 | configured_endpoints: 28 2 | openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/togetherai%2Ftogetherai-c949fc43297a5155ea4c433179ee6f0822e25a351f180a5539871687daead7ad.yml 3 | openapi_spec_hash: ca24d10b37e987becfd16b30ea342459 4 | config_hash: a60b100624e80dc8d9144e7bc306f5ce 5 | -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | brew "node" 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Setting up the environment 2 | 3 | This repository uses [`yarn@v1`](https://classic.yarnpkg.com/lang/en/docs/install). 4 | Other package managers may work but are not officially supported for development. 5 | 6 | To set up the repository, run: 7 | 8 | ```sh 9 | $ yarn 10 | $ yarn build 11 | ``` 12 | 13 | This will install all the required dependencies and build output files to `dist/`. 14 | 15 | ## Modifying/Adding code 16 | 17 | Most of the SDK is generated code. Modifications to code will be persisted between generations, but may 18 | result in merge conflicts between manual patches and changes from the generator. The generator will never 19 | modify the contents of the `src/lib/` and `examples/` directories. 20 | 21 | ## Adding and running examples 22 | 23 | All files in the `examples/` directory are not modified by the generator and can be freely edited or added to. 24 | 25 | ```ts 26 | // add an example to examples/.ts 27 | 28 | #!/usr/bin/env -S npm run tsn -T 29 | … 30 | ``` 31 | 32 | ```sh 33 | $ chmod +x examples/.ts 34 | # run the example against your api 35 | $ yarn tsn -T examples/.ts 36 | ``` 37 | 38 | ## Using the repository from source 39 | 40 | If you’d like to use the repository from source, you can either install from git or link to a cloned repository: 41 | 42 | To install via git: 43 | 44 | ```sh 45 | $ npm install git+ssh://git@github.com:togethercomputer/together-typescript.git 46 | ``` 47 | 48 | Alternatively, to link a local copy of the repo: 49 | 50 | ```sh 51 | # Clone 52 | $ git clone https://www.github.com/togethercomputer/together-typescript 53 | $ cd together-typescript 54 | 55 | # With yarn 56 | $ yarn link 57 | $ cd ../my-package 58 | $ yarn link together-ai 59 | 60 | # With pnpm 61 | $ pnpm link --global 62 | $ cd ../my-package 63 | $ pnpm link -—global together-ai 64 | ``` 65 | 66 | ## Running tests 67 | 68 | Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. 69 | 70 | ```sh 71 | $ npx prism mock path/to/your/openapi.yml 72 | ``` 73 | 74 | ```sh 75 | $ yarn run test 76 | ``` 77 | 78 | ## Linting and formatting 79 | 80 | This repository uses [prettier](https://www.npmjs.com/package/prettier) and 81 | [eslint](https://www.npmjs.com/package/eslint) to format the code in the repository. 82 | 83 | To lint: 84 | 85 | ```sh 86 | $ yarn lint 87 | ``` 88 | 89 | To format and fix all lint issues automatically: 90 | 91 | ```sh 92 | $ yarn fix 93 | ``` 94 | 95 | ## Publishing and releases 96 | 97 | Changes made to this repository via the automated release PR pipeline should publish to npm automatically. If 98 | the changes aren't made through the automated pipeline, you may want to make releases manually. 99 | 100 | ### Publish with a GitHub workflow 101 | 102 | You can release to package managers by using [the `Publish NPM` GitHub action](https://www.github.com/togethercomputer/together-typescript/actions/workflows/publish-npm.yml). This requires a setup organization or repository secret to be set up. 103 | 104 | ### Publish manually 105 | 106 | If you need to manually release a package, you can run the `bin/publish-npm` script with an `NPM_TOKEN` set on 107 | the environment. 108 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting Security Issues 4 | 5 | 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. 6 | 7 | To report a security issue, please contact the Stainless team at security@stainless.com. 8 | 9 | ## Responsible Disclosure 10 | 11 | We appreciate the efforts of security researchers and individuals who help us maintain the security of 12 | SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible 13 | disclosure practices by allowing us a reasonable amount of time to investigate and address the issue 14 | before making any information public. 15 | 16 | ## Reporting Non-SDK Related Security Issues 17 | 18 | If you encounter security issues that are not directly related to SDKs but pertain to the services 19 | or products provided by Together please follow the respective company's security reporting guidelines. 20 | 21 | ### Together Terms and Policies 22 | 23 | Please contact dev-feedback@TogetherAI.com for any questions or concerns regarding security of our services. 24 | 25 | --- 26 | 27 | Thank you for helping us keep the SDKs and systems they interact with secure. 28 | -------------------------------------------------------------------------------- /api.md: -------------------------------------------------------------------------------- 1 | # Together 2 | 3 | Types: 4 | 5 | - RerankResponse 6 | 7 | Methods: 8 | 9 | - client.rerank({ ...params }) -> RerankResponse 10 | 11 | # Chat 12 | 13 | ## Completions 14 | 15 | Types: 16 | 17 | - ChatCompletion 18 | - ChatCompletionAssistantMessageParam 19 | - ChatCompletionChunk 20 | - ChatCompletionFunctionMessageParam 21 | - ChatCompletionMessage 22 | - ChatCompletionMessageParam 23 | - ChatCompletionSystemMessageParam 24 | - ChatCompletionTool 25 | - ChatCompletionToolMessageParam 26 | - ChatCompletionStructuredMessageImageURL 27 | - ChatCompletionStructuredMessageText 28 | - ChatCompletionUsage 29 | - ChatCompletionUserMessageParam 30 | 31 | Methods: 32 | 33 | - client.chat.completions.create({ ...params }) -> ChatCompletion 34 | 35 | # Completions 36 | 37 | Types: 38 | 39 | - Completion 40 | - LogProbs 41 | - ToolChoice 42 | - Tools 43 | 44 | Methods: 45 | 46 | - client.completions.create({ ...params }) -> Completion 47 | 48 | # Embeddings 49 | 50 | Types: 51 | 52 | - Embedding 53 | 54 | Methods: 55 | 56 | - client.embeddings.create({ ...params }) -> Embedding 57 | 58 | # Files 59 | 60 | Types: 61 | 62 | - FileObject 63 | - FileRetrieveResponse 64 | - FileListResponse 65 | - FileDeleteResponse 66 | 67 | Methods: 68 | 69 | - client.files.retrieve(id) -> FileRetrieveResponse 70 | - client.files.list() -> FileListResponse 71 | - client.files.delete(id) -> FileDeleteResponse 72 | - client.files.content(id) -> Response 73 | 74 | # FineTune 75 | 76 | Types: 77 | 78 | - FineTune 79 | - FineTuneEvent 80 | - FineTuneListResponse 81 | - FineTuneDownloadResponse 82 | 83 | Methods: 84 | 85 | - client.fineTune.create({ ...params }) -> FineTune 86 | - client.fineTune.retrieve(id) -> FineTune 87 | - client.fineTune.list() -> FineTuneListResponse 88 | - client.fineTune.cancel(id) -> FineTune 89 | - client.fineTune.download({ ...params }) -> FineTuneDownloadResponse 90 | - client.fineTune.listEvents(id) -> FineTuneEvent 91 | 92 | # CodeInterpreter 93 | 94 | Types: 95 | 96 | - ExecuteResponse 97 | 98 | Methods: 99 | 100 | - client.codeInterpreter.execute({ ...params }) -> ExecuteResponse 101 | 102 | ## Sessions 103 | 104 | Types: 105 | 106 | - SessionListResponse 107 | 108 | Methods: 109 | 110 | - client.codeInterpreter.sessions.list() -> SessionListResponse 111 | 112 | # Images 113 | 114 | Types: 115 | 116 | - ImageFile 117 | 118 | Methods: 119 | 120 | - client.images.create({ ...params }) -> ImageFile 121 | 122 | # Audio 123 | 124 | Types: 125 | 126 | - AudioFile 127 | 128 | Methods: 129 | 130 | - client.audio.create({ ...params }) -> Response 131 | 132 | # Models 133 | 134 | Types: 135 | 136 | - ModelListResponse 137 | - ModelUploadResponse 138 | 139 | Methods: 140 | 141 | - client.models.list() -> ModelListResponse 142 | - client.models.upload({ ...params }) -> ModelUploadResponse 143 | 144 | # Jobs 145 | 146 | Types: 147 | 148 | - JobRetrieveResponse 149 | - JobListResponse 150 | 151 | Methods: 152 | 153 | - client.jobs.retrieve(jobId) -> JobRetrieveResponse 154 | - client.jobs.list() -> JobListResponse 155 | 156 | # Endpoints 157 | 158 | Types: 159 | 160 | - EndpointCreateResponse 161 | - EndpointRetrieveResponse 162 | - EndpointUpdateResponse 163 | - EndpointListResponse 164 | 165 | Methods: 166 | 167 | - client.endpoints.create({ ...params }) -> EndpointCreateResponse 168 | - client.endpoints.retrieve(endpointId) -> EndpointRetrieveResponse 169 | - client.endpoints.update(endpointId, { ...params }) -> EndpointUpdateResponse 170 | - client.endpoints.list({ ...params }) -> EndpointListResponse 171 | - client.endpoints.delete(endpointId) -> void 172 | 173 | # Hardware 174 | 175 | Types: 176 | 177 | - HardwareListResponse 178 | 179 | Methods: 180 | 181 | - client.hardware.list({ ...params }) -> HardwareListResponse 182 | -------------------------------------------------------------------------------- /bin/check-release-environment: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | errors=() 4 | 5 | if [ -z "${NPM_TOKEN}" ]; then 6 | errors+=("The TOGETHER_NPM_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets") 7 | fi 8 | 9 | lenErrors=${#errors[@]} 10 | 11 | if [[ lenErrors -gt 0 ]]; then 12 | echo -e "Found the following errors in the release environment:\n" 13 | 14 | for error in "${errors[@]}"; do 15 | echo -e "- $error\n" 16 | done 17 | 18 | exit 1 19 | fi 20 | 21 | echo "The environment is ready to push releases!" 22 | 23 | -------------------------------------------------------------------------------- /bin/publish-npm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eux 4 | 5 | npm config set '//registry.npmjs.org/:_authToken' "$NPM_TOKEN" 6 | 7 | # Build the project 8 | yarn build 9 | 10 | # Navigate to the dist directory 11 | cd dist 12 | 13 | # Get the version from package.json 14 | VERSION="$(node -p "require('./package.json').version")" 15 | 16 | # Extract the pre-release tag if it exists 17 | if [[ "$VERSION" =~ -([a-zA-Z]+) ]]; then 18 | # Extract the part before any dot in the pre-release identifier 19 | TAG="${BASH_REMATCH[1]}" 20 | else 21 | TAG="latest" 22 | fi 23 | 24 | # Publish with the appropriate tag 25 | yarn publish --access public --tag "$TAG" 26 | -------------------------------------------------------------------------------- /examples/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store example files demonstrating usage of this SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. 5 | -------------------------------------------------------------------------------- /examples/chat-completions.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | import Together from 'together-ai'; 4 | 5 | const together = new Together(); 6 | async function main() { 7 | const runner = together.chat.completions 8 | .stream({ 9 | model: 'mistralai/Mixtral-8x7B-Instruct-v0.1', 10 | messages: [{ role: 'user', content: 'Say this is a test' }], 11 | logprobs: 1, 12 | }) 13 | .on('message', (msg) => console.log(msg)) 14 | .on('content', (diff) => process.stdout.write(diff)); 15 | 16 | for await (const chunk of runner) { 17 | // Note: comment out the next line to print chunks as they are streamed from the API 18 | console.log('chunk', chunk); 19 | } 20 | 21 | const result = await runner.finalMessage(); 22 | console.log({ result }); 23 | } 24 | 25 | main(); 26 | -------------------------------------------------------------------------------- /examples/embedding.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | import Together from 'together-ai'; 4 | 5 | const together = new Together(); 6 | 7 | async function main() { 8 | const embeddings = await together.embeddings.create({ 9 | input: 'A cat', 10 | model: 'togethercomputer/m2-bert-80M-8k-retrieval', 11 | }); 12 | 13 | if (embeddings.data && embeddings.data[0]) { 14 | console.log(embeddings.data[0].embedding); 15 | } 16 | } 17 | 18 | main(); 19 | -------------------------------------------------------------------------------- /examples/files.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | // Example of listing and retrieving files 4 | 5 | import Together from 'together-ai'; 6 | 7 | const together = new Together(); 8 | 9 | async function main() { 10 | console.log('Listing all files'); 11 | 12 | //Print all files 13 | const files = await together.files.list(); 14 | for (const file of files.data) { 15 | console.log(file); 16 | } 17 | 18 | //Retrieve a file 19 | if (files.data && files.data[0]) { 20 | console.log('Retrieving a file'); 21 | 22 | const fileId = files.data[0].id; 23 | 24 | const file = await together.files.retrieve(fileId); 25 | 26 | console.log(file); 27 | } 28 | } 29 | 30 | main(); 31 | -------------------------------------------------------------------------------- /examples/fine-tune.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | import Together from 'together-ai'; 4 | 5 | const together = new Together(); 6 | 7 | async function main() { 8 | //These files need to be uploaded separately. See the files example. 9 | const fileId = 'file-bf72b951-fa1a-41af-a152-fe385dca0201'; 10 | 11 | // Create a model 12 | const fineTuneModel = await together.fineTune.create({ 13 | model: 'meta-llama/Meta-Llama-3-8B', 14 | training_file: fileId, 15 | }); 16 | 17 | console.log(fineTuneModel); 18 | 19 | const fineTuneId = fineTuneModel.id; 20 | 21 | //Wait for completion 22 | while (true) { 23 | const fineTuneStatus = await together.fineTune.retrieve(fineTuneId); 24 | if (fineTuneStatus.status === 'completed') { 25 | break; 26 | } else { 27 | await new Promise((resolve) => setTimeout(resolve, 1000)); 28 | } 29 | } 30 | 31 | //List the model events 32 | const modelEvents = await together.fineTune.listEvents(fineTuneId); 33 | for (const e of modelEvents.data) { 34 | console.log(e); 35 | } 36 | 37 | //Download the model 38 | const down = await together.fineTune.download({ 39 | ft_id: fineTuneId, 40 | }); 41 | console.log(JSON.stringify(down)); 42 | } 43 | 44 | main(); 45 | -------------------------------------------------------------------------------- /examples/image.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | //An example to generate an image and save to a file 4 | 5 | import Together from 'together-ai'; 6 | import fs from 'fs'; 7 | 8 | const together = new Together(); 9 | 10 | async function main() { 11 | //Request the image generation 12 | const image = await together.images.create({ 13 | model: 'runwayml/stable-diffusion-v1-5', 14 | prompt: 'space robots', 15 | n: 1, 16 | }); 17 | 18 | //Write the image to a file 19 | if (image.data && image.data[0] && image.data[0].b64_json) { 20 | let image_data = image.data[0].b64_json; 21 | 22 | const buffer = Buffer.from(image_data, 'base64'); 23 | fs.writeFileSync('image.jpg', buffer, { encoding: 'base64' }); 24 | } 25 | } 26 | 27 | main(); 28 | -------------------------------------------------------------------------------- /examples/models.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | //An example to request a list of models and print them. 4 | 5 | import Together from 'together-ai'; 6 | 7 | const together = new Together(); 8 | 9 | async function main() { 10 | //Request the list of all models and print them 11 | const models = await together.models.list(); 12 | for (const model of models) { 13 | console.log(model); 14 | } 15 | } 16 | 17 | main(); 18 | -------------------------------------------------------------------------------- /examples/streaming.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | import Together from 'together-ai'; 4 | 5 | const together = new Together(); 6 | 7 | async function main() { 8 | const stream = await together.chat.completions.create({ 9 | messages: [{ role: 'user', content: 'Say this is a test' }], 10 | model: 'mistralai/Mixtral-8x7B-Instruct-v0.1', 11 | stream: true, 12 | }); 13 | for await (const chunk of stream) { 14 | const choice = chunk.choices?.[0]; 15 | if (choice && choice.delta.content) { 16 | process.stdout.write(choice.delta.content); 17 | } 18 | } 19 | console.log(); 20 | } 21 | 22 | main(); 23 | -------------------------------------------------------------------------------- /examples/uploading-files.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S npm run tsn -T 2 | 3 | // Example of uploading a file 4 | import { upload, ErrorResponse, FileResponse } from 'together-ai/lib/upload'; 5 | import fetch from 'node-fetch'; 6 | import * as core from 'together-ai/core'; 7 | 8 | async function main() { 9 | // Upload a file 10 | const file: ErrorResponse | FileResponse = await upload('./examples/coqa.jsonl'); 11 | console.log('Uploaded file'); 12 | console.log(file); 13 | 14 | if ('message' in file) { 15 | console.error(file.message); 16 | return; 17 | } 18 | 19 | // Check if the file has any contents (https://docs.together.ai/reference/get_files-id-content) 20 | // @ts-ignore 21 | const baseUrl = core.readEnv('TOGETHER_API_BASE_URL') || 'https://api.together.ai/v1'; 22 | const url = `${baseUrl}/files/${file.id}/content`; 23 | const options = { 24 | method: 'GET', 25 | headers: { 26 | accept: 'application/json', 27 | authorization: `Bearer ${process.env['TOGETHER_API_KEY']}`, 28 | }, 29 | }; 30 | 31 | const res = await fetch(url, options); 32 | console.log(await res.text()); 33 | } 34 | 35 | main(); 36 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { JestConfigWithTsJest } from 'ts-jest'; 2 | 3 | const config: JestConfigWithTsJest = { 4 | preset: 'ts-jest/presets/default-esm', 5 | testEnvironment: 'node', 6 | transform: { 7 | '^.+\\.(t|j)sx?$': ['@swc/jest', { sourceMaps: 'inline' }], 8 | }, 9 | moduleNameMapper: { 10 | '^together-ai$': '/src/index.ts', 11 | '^together-ai/_shims/auto/(.*)$': '/src/_shims/auto/$1-node', 12 | '^together-ai/(.*)$': '/src/$1', 13 | }, 14 | modulePathIgnorePatterns: [ 15 | '/ecosystem-tests/', 16 | '/dist/', 17 | '/deno/', 18 | '/deno_tests/', 19 | ], 20 | testPathIgnorePatterns: ['scripts'], 21 | }; 22 | 23 | export default config; 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "together-ai", 3 | "version": "0.16.0", 4 | "description": "The official TypeScript library for the Together API", 5 | "author": "Together ", 6 | "types": "dist/index.d.ts", 7 | "main": "dist/index.js", 8 | "type": "commonjs", 9 | "repository": "github:togethercomputer/together-typescript", 10 | "license": "Apache-2.0", 11 | "packageManager": "yarn@1.22.22", 12 | "files": [ 13 | "**/*" 14 | ], 15 | "private": false, 16 | "scripts": { 17 | "test": "./scripts/test", 18 | "build": "./scripts/build", 19 | "prepublishOnly": "echo 'to publish, run yarn build && (cd dist; yarn publish)' && exit 1", 20 | "format": "prettier --write --cache --cache-strategy metadata . !dist", 21 | "prepare": "if ./scripts/utils/check-is-in-git-install.sh; then ./scripts/build && ./scripts/utils/git-swap.sh; fi", 22 | "tsn": "ts-node -r tsconfig-paths/register", 23 | "lint": "./scripts/lint", 24 | "fix": "./scripts/format" 25 | }, 26 | "dependencies": { 27 | "@types/node": "^18.11.18", 28 | "@types/node-fetch": "^2.6.4", 29 | "@types/parquetjs": "^0.10.6", 30 | "@types/progress-stream": "^2.0.5", 31 | "abort-controller": "^3.0.0", 32 | "agentkeepalive": "^4.2.1", 33 | "axios": "^1.7.7", 34 | "form-data-encoder": "1.7.2", 35 | "formdata-node": "^4.3.2", 36 | "node-fetch": "^2.6.7", 37 | "parquetjs": "^0.11.2", 38 | "progress-stream": "^2.0.0" 39 | }, 40 | "devDependencies": { 41 | "@swc/core": "^1.3.102", 42 | "@swc/jest": "^0.2.29", 43 | "@types/jest": "^29.4.0", 44 | "@typescript-eslint/eslint-plugin": "^6.7.0", 45 | "@typescript-eslint/parser": "^6.7.0", 46 | "eslint": "^8.49.0", 47 | "eslint-plugin-prettier": "^5.0.1", 48 | "eslint-plugin-unused-imports": "^3.0.0", 49 | "iconv-lite": "^0.6.3", 50 | "jest": "^29.4.0", 51 | "prettier": "^3.0.0", 52 | "ts-jest": "^29.1.0", 53 | "ts-node": "^10.5.0", 54 | "tsc-multi": "^1.1.0", 55 | "tsconfig-paths": "^4.0.0", 56 | "typescript": "^4.8.2" 57 | }, 58 | "sideEffects": [ 59 | "./_shims/index.js", 60 | "./_shims/index.mjs", 61 | "./shims/node.js", 62 | "./shims/node.mjs", 63 | "./shims/web.js", 64 | "./shims/web.mjs" 65 | ], 66 | "imports": { 67 | "together-ai": ".", 68 | "together-ai/*": "./src/*" 69 | }, 70 | "exports": { 71 | "./_shims/auto/*": { 72 | "deno": { 73 | "types": "./dist/_shims/auto/*.d.ts", 74 | "require": "./dist/_shims/auto/*.js", 75 | "default": "./dist/_shims/auto/*.mjs" 76 | }, 77 | "bun": { 78 | "types": "./dist/_shims/auto/*.d.ts", 79 | "require": "./dist/_shims/auto/*-bun.js", 80 | "default": "./dist/_shims/auto/*-bun.mjs" 81 | }, 82 | "browser": { 83 | "types": "./dist/_shims/auto/*.d.ts", 84 | "require": "./dist/_shims/auto/*.js", 85 | "default": "./dist/_shims/auto/*.mjs" 86 | }, 87 | "worker": { 88 | "types": "./dist/_shims/auto/*.d.ts", 89 | "require": "./dist/_shims/auto/*.js", 90 | "default": "./dist/_shims/auto/*.mjs" 91 | }, 92 | "workerd": { 93 | "types": "./dist/_shims/auto/*.d.ts", 94 | "require": "./dist/_shims/auto/*.js", 95 | "default": "./dist/_shims/auto/*.mjs" 96 | }, 97 | "node": { 98 | "types": "./dist/_shims/auto/*-node.d.ts", 99 | "require": "./dist/_shims/auto/*-node.js", 100 | "default": "./dist/_shims/auto/*-node.mjs" 101 | }, 102 | "types": "./dist/_shims/auto/*.d.ts", 103 | "require": "./dist/_shims/auto/*.js", 104 | "default": "./dist/_shims/auto/*.mjs" 105 | }, 106 | ".": { 107 | "require": { 108 | "types": "./dist/index.d.ts", 109 | "default": "./dist/index.js" 110 | }, 111 | "types": "./dist/index.d.mts", 112 | "default": "./dist/index.mjs" 113 | }, 114 | "./*.mjs": { 115 | "types": "./dist/*.d.ts", 116 | "default": "./dist/*.mjs" 117 | }, 118 | "./*.js": { 119 | "types": "./dist/*.d.ts", 120 | "default": "./dist/*.js" 121 | }, 122 | "./*": { 123 | "types": "./dist/*.d.ts", 124 | "require": "./dist/*.js", 125 | "default": "./dist/*.mjs" 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /release-please-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": { 3 | ".": {} 4 | }, 5 | "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", 6 | "include-v-in-tag": true, 7 | "include-component-in-tag": false, 8 | "versioning": "prerelease", 9 | "prerelease": true, 10 | "bump-minor-pre-major": true, 11 | "bump-patch-for-minor-pre-major": false, 12 | "pull-request-header": "Automated Release PR", 13 | "pull-request-title-pattern": "release: ${version}", 14 | "changelog-sections": [ 15 | { 16 | "type": "feat", 17 | "section": "Features" 18 | }, 19 | { 20 | "type": "fix", 21 | "section": "Bug Fixes" 22 | }, 23 | { 24 | "type": "perf", 25 | "section": "Performance Improvements" 26 | }, 27 | { 28 | "type": "revert", 29 | "section": "Reverts" 30 | }, 31 | { 32 | "type": "chore", 33 | "section": "Chores" 34 | }, 35 | { 36 | "type": "docs", 37 | "section": "Documentation" 38 | }, 39 | { 40 | "type": "style", 41 | "section": "Styles" 42 | }, 43 | { 44 | "type": "refactor", 45 | "section": "Refactors" 46 | }, 47 | { 48 | "type": "test", 49 | "section": "Tests", 50 | "hidden": true 51 | }, 52 | { 53 | "type": "build", 54 | "section": "Build System" 55 | }, 56 | { 57 | "type": "ci", 58 | "section": "Continuous Integration", 59 | "hidden": true 60 | } 61 | ], 62 | "release-type": "node", 63 | "extra-files": [ 64 | "src/version.ts", 65 | "README.md" 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /scripts/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ]; then 8 | brew bundle check >/dev/null 2>&1 || { 9 | echo "==> Installing Homebrew dependencies…" 10 | brew bundle 11 | } 12 | fi 13 | 14 | echo "==> Installing Node dependencies…" 15 | 16 | PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm") 17 | 18 | $PACKAGE_MANAGER install 19 | -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -exuo pipefail 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | node scripts/utils/check-version.cjs 8 | 9 | # Build into dist and will publish the package from there, 10 | # so that src/resources/foo.ts becomes /resources/foo.js 11 | # This way importing from `"together-ai/resources/foo"` works 12 | # even with `"moduleResolution": "node"` 13 | 14 | rm -rf dist; mkdir dist 15 | # Copy src to dist/src and build from dist/src into dist, so that 16 | # the source map for index.js.map will refer to ./src/index.ts etc 17 | cp -rp src README.md dist 18 | rm dist/src/_shims/*-deno.ts dist/src/_shims/auto/*-deno.ts 19 | for file in LICENSE CHANGELOG.md; do 20 | if [ -e "${file}" ]; then cp "${file}" dist; fi 21 | done 22 | if [ -e "bin/cli" ]; then 23 | mkdir dist/bin 24 | cp -p "bin/cli" dist/bin/; 25 | fi 26 | # this converts the export map paths for the dist directory 27 | # and does a few other minor things 28 | node scripts/utils/make-dist-package-json.cjs > dist/package.json 29 | 30 | # build to .js/.mjs/.d.ts files 31 | npm exec tsc-multi 32 | # copy over handwritten .js/.mjs/.d.ts files 33 | cp src/_shims/*.{d.ts,js,mjs,md} dist/_shims 34 | cp src/_shims/auto/*.{d.ts,js,mjs} dist/_shims/auto 35 | # we need to add exports = module.exports = Together to index.js; 36 | # No way to get that from index.ts because it would cause compile errors 37 | # when building .mjs 38 | node scripts/utils/fix-index-exports.cjs 39 | # with "moduleResolution": "nodenext", if ESM resolves to index.d.ts, 40 | # it'll have TS errors on the default import. But if it resolves to 41 | # index.d.mts the default import will work (even though both files have 42 | # the same export default statement) 43 | cp dist/index.d.ts dist/index.d.mts 44 | cp tsconfig.dist-src.json dist/src/tsconfig.json 45 | 46 | node scripts/utils/postprocess-files.cjs 47 | 48 | # make sure that nothing crashes when we require the output CJS or 49 | # import the output ESM 50 | (cd dist && node -e 'require("together-ai")') 51 | (cd dist && node -e 'import("together-ai")' --input-type=module) 52 | 53 | if [ -e ./scripts/build-deno ] 54 | then 55 | ./scripts/build-deno 56 | fi 57 | -------------------------------------------------------------------------------- /scripts/format: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running eslint --fix" 8 | ESLINT_USE_FLAT_CONFIG="false" ./node_modules/.bin/eslint --fix --ext ts,js . 9 | -------------------------------------------------------------------------------- /scripts/lint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | echo "==> Running eslint" 8 | ESLINT_USE_FLAT_CONFIG="false" ./node_modules/.bin/eslint --ext ts,js . 9 | 10 | echo "==> Running tsc" 11 | ./node_modules/.bin/tsc --noEmit 12 | -------------------------------------------------------------------------------- /scripts/mock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | if [[ -n "$1" && "$1" != '--'* ]]; then 8 | URL="$1" 9 | shift 10 | else 11 | URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" 12 | fi 13 | 14 | # Check if the URL is empty 15 | if [ -z "$URL" ]; then 16 | echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" 17 | exit 1 18 | fi 19 | 20 | echo "==> Starting mock server with URL ${URL}" 21 | 22 | # Run prism mock on the given spec 23 | if [ "$1" == "--daemon" ]; then 24 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" &> .prism.log & 25 | 26 | # Wait for server to come online 27 | echo -n "Waiting for server" 28 | while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do 29 | echo -n "." 30 | sleep 0.1 31 | done 32 | 33 | if grep -q "✖ fatal" ".prism.log"; then 34 | cat .prism.log 35 | exit 1 36 | fi 37 | 38 | echo 39 | else 40 | npm exec --package=@stainless-api/prism-cli@5.8.5 -- prism mock "$URL" 41 | fi 42 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | RED='\033[0;31m' 8 | GREEN='\033[0;32m' 9 | YELLOW='\033[0;33m' 10 | NC='\033[0m' # No Color 11 | 12 | function prism_is_running() { 13 | curl --silent "http://localhost:4010" >/dev/null 2>&1 14 | } 15 | 16 | kill_server_on_port() { 17 | pids=$(lsof -t -i tcp:"$1" || echo "") 18 | if [ "$pids" != "" ]; then 19 | kill "$pids" 20 | echo "Stopped $pids." 21 | fi 22 | } 23 | 24 | function is_overriding_api_base_url() { 25 | [ -n "$TEST_API_BASE_URL" ] 26 | } 27 | 28 | if ! is_overriding_api_base_url && ! prism_is_running ; then 29 | # When we exit this script, make sure to kill the background mock server process 30 | trap 'kill_server_on_port 4010' EXIT 31 | 32 | # Start the dev server 33 | ./scripts/mock --daemon 34 | fi 35 | 36 | if is_overriding_api_base_url ; then 37 | echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" 38 | echo 39 | elif ! prism_is_running ; then 40 | echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" 41 | echo -e "running against your OpenAPI spec." 42 | echo 43 | echo -e "To run the server, pass in the path or url of your OpenAPI" 44 | echo -e "spec to the prism command:" 45 | echo 46 | echo -e " \$ ${YELLOW}npm exec --package=@stoplight/prism-cli@~5.3.2 -- prism mock path/to/your.openapi.yml${NC}" 47 | echo 48 | 49 | exit 1 50 | else 51 | echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" 52 | echo 53 | fi 54 | 55 | echo "==> Running tests" 56 | ./node_modules/.bin/jest "$@" 57 | -------------------------------------------------------------------------------- /scripts/utils/check-is-in-git-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Check if you happen to call prepare for a repository that's already in node_modules. 3 | [ "$(basename "$(dirname "$PWD")")" = 'node_modules' ] || 4 | # The name of the containing directory that 'npm` uses, which looks like 5 | # $HOME/.npm/_cacache/git-cloneXXXXXX 6 | [ "$(basename "$(dirname "$PWD")")" = 'tmp' ] || 7 | # The name of the containing directory that 'yarn` uses, which looks like 8 | # $(yarn cache dir)/.tmp/XXXXX 9 | [ "$(basename "$(dirname "$PWD")")" = '.tmp' ] 10 | -------------------------------------------------------------------------------- /scripts/utils/check-version.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const main = () => { 5 | const pkg = require('../../package.json'); 6 | const version = pkg['version']; 7 | if (!version) throw 'The version property is not set in the package.json file'; 8 | if (typeof version !== 'string') { 9 | throw `Unexpected type for the package.json version field; got ${typeof version}, expected string`; 10 | } 11 | 12 | const versionFile = path.resolve(__dirname, '..', '..', 'src', 'version.ts'); 13 | const contents = fs.readFileSync(versionFile, 'utf8'); 14 | const output = contents.replace(/(export const VERSION = ')(.*)(')/g, `$1${version}$3`); 15 | fs.writeFileSync(versionFile, output); 16 | }; 17 | 18 | if (require.main === module) { 19 | main(); 20 | } 21 | -------------------------------------------------------------------------------- /scripts/utils/fix-index-exports.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const indexJs = 5 | process.env['DIST_PATH'] ? 6 | path.resolve(process.env['DIST_PATH'], 'index.js') 7 | : path.resolve(__dirname, '..', '..', 'dist', 'index.js'); 8 | 9 | let before = fs.readFileSync(indexJs, 'utf8'); 10 | let after = before.replace( 11 | /^\s*exports\.default\s*=\s*(\w+)/m, 12 | 'exports = module.exports = $1;\nexports.default = $1', 13 | ); 14 | fs.writeFileSync(indexJs, after, 'utf8'); 15 | -------------------------------------------------------------------------------- /scripts/utils/git-swap.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exuo pipefail 3 | # the package is published to NPM from ./dist 4 | # we want the final file structure for git installs to match the npm installs, so we 5 | 6 | # delete everything except ./dist and ./node_modules 7 | find . -maxdepth 1 -mindepth 1 ! -name 'dist' ! -name 'node_modules' -exec rm -rf '{}' + 8 | 9 | # move everything from ./dist to . 10 | mv dist/* . 11 | 12 | # delete the now-empty ./dist 13 | rmdir dist 14 | -------------------------------------------------------------------------------- /scripts/utils/make-dist-package-json.cjs: -------------------------------------------------------------------------------- 1 | const pkgJson = require(process.env['PKG_JSON_PATH'] || '../../package.json'); 2 | 3 | function processExportMap(m) { 4 | for (const key in m) { 5 | const value = m[key]; 6 | if (typeof value === 'string') m[key] = value.replace(/^\.\/dist\//, './'); 7 | else processExportMap(value); 8 | } 9 | } 10 | processExportMap(pkgJson.exports); 11 | 12 | for (const key of ['types', 'main', 'module']) { 13 | if (typeof pkgJson[key] === 'string') pkgJson[key] = pkgJson[key].replace(/^(\.\/)?dist\//, './'); 14 | } 15 | 16 | delete pkgJson.devDependencies; 17 | delete pkgJson.scripts.prepack; 18 | delete pkgJson.scripts.prepublishOnly; 19 | delete pkgJson.scripts.prepare; 20 | 21 | console.log(JSON.stringify(pkgJson, null, 2)); 22 | -------------------------------------------------------------------------------- /scripts/utils/postprocess-files.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { parse } = require('@typescript-eslint/parser'); 4 | 5 | const pkgImportPath = process.env['PKG_IMPORT_PATH'] ?? 'together-ai/'; 6 | 7 | const distDir = 8 | process.env['DIST_PATH'] ? 9 | path.resolve(process.env['DIST_PATH']) 10 | : path.resolve(__dirname, '..', '..', 'dist'); 11 | const distSrcDir = path.join(distDir, 'src'); 12 | 13 | /** 14 | * Quick and dirty AST traversal 15 | */ 16 | function traverse(node, visitor) { 17 | if (!node || typeof node.type !== 'string') return; 18 | visitor.node?.(node); 19 | visitor[node.type]?.(node); 20 | for (const key in node) { 21 | const value = node[key]; 22 | if (Array.isArray(value)) { 23 | for (const elem of value) traverse(elem, visitor); 24 | } else if (value instanceof Object) { 25 | traverse(value, visitor); 26 | } 27 | } 28 | } 29 | 30 | /** 31 | * Helper method for replacing arbitrary ranges of text in input code. 32 | * 33 | * The `replacer` is a function that will be called with a mini-api. For example: 34 | * 35 | * replaceRanges('foobar', ({ replace }) => replace([0, 3], 'baz')) // 'bazbar' 36 | * 37 | * The replaced ranges must not be overlapping. 38 | */ 39 | function replaceRanges(code, replacer) { 40 | const replacements = []; 41 | replacer({ replace: (range, replacement) => replacements.push({ range, replacement }) }); 42 | 43 | if (!replacements.length) return code; 44 | replacements.sort((a, b) => a.range[0] - b.range[0]); 45 | const overlapIndex = replacements.findIndex( 46 | (r, index) => index > 0 && replacements[index - 1].range[1] > r.range[0], 47 | ); 48 | if (overlapIndex >= 0) { 49 | throw new Error( 50 | `replacements overlap: ${JSON.stringify(replacements[overlapIndex - 1])} and ${JSON.stringify( 51 | replacements[overlapIndex], 52 | )}`, 53 | ); 54 | } 55 | 56 | const parts = []; 57 | let end = 0; 58 | for (const { 59 | range: [from, to], 60 | replacement, 61 | } of replacements) { 62 | if (from > end) parts.push(code.substring(end, from)); 63 | parts.push(replacement); 64 | end = to; 65 | } 66 | if (end < code.length) parts.push(code.substring(end)); 67 | return parts.join(''); 68 | } 69 | 70 | /** 71 | * Like calling .map(), where the iteratee is called on the path in every import or export from statement. 72 | * @returns the transformed code 73 | */ 74 | function mapModulePaths(code, iteratee) { 75 | const ast = parse(code, { range: true }); 76 | return replaceRanges(code, ({ replace }) => 77 | traverse(ast, { 78 | node(node) { 79 | switch (node.type) { 80 | case 'ImportDeclaration': 81 | case 'ExportNamedDeclaration': 82 | case 'ExportAllDeclaration': 83 | case 'ImportExpression': 84 | if (node.source) { 85 | const { range, value } = node.source; 86 | const transformed = iteratee(value); 87 | if (transformed !== value) { 88 | replace(range, JSON.stringify(transformed)); 89 | } 90 | } 91 | } 92 | }, 93 | }), 94 | ); 95 | } 96 | 97 | async function* walk(dir) { 98 | for await (const d of await fs.promises.opendir(dir)) { 99 | const entry = path.join(dir, d.name); 100 | if (d.isDirectory()) yield* walk(entry); 101 | else if (d.isFile()) yield entry; 102 | } 103 | } 104 | 105 | async function postprocess() { 106 | for await (const file of walk(path.resolve(__dirname, '..', '..', 'dist'))) { 107 | if (!/\.([cm]?js|(\.d)?[cm]?ts)$/.test(file)) continue; 108 | 109 | const code = await fs.promises.readFile(file, 'utf8'); 110 | 111 | let transformed = mapModulePaths(code, (importPath) => { 112 | if (file.startsWith(distSrcDir)) { 113 | if (importPath.startsWith(pkgImportPath)) { 114 | // convert self-references in dist/src to relative paths 115 | let relativePath = path.relative( 116 | path.dirname(file), 117 | path.join(distSrcDir, importPath.substring(pkgImportPath.length)), 118 | ); 119 | if (!relativePath.startsWith('.')) relativePath = `./${relativePath}`; 120 | return relativePath; 121 | } 122 | return importPath; 123 | } 124 | if (importPath.startsWith('.')) { 125 | // add explicit file extensions to relative imports 126 | const { dir, name } = path.parse(importPath); 127 | const ext = /\.mjs$/.test(file) ? '.mjs' : '.js'; 128 | return `${dir}/${name}${ext}`; 129 | } 130 | return importPath; 131 | }); 132 | 133 | if (file.startsWith(distSrcDir) && !file.endsWith('_shims/index.d.ts')) { 134 | // strip out `unknown extends Foo ? never :` shim guards in dist/src 135 | // to prevent errors from appearing in Go To Source 136 | transformed = transformed.replace( 137 | new RegExp('unknown extends (typeof )?\\S+ \\? \\S+ :\\s*'.replace(/\s+/, '\\s+'), 'gm'), 138 | // replace with same number of characters to avoid breaking source maps 139 | (match) => ' '.repeat(match.length), 140 | ); 141 | } 142 | 143 | if (file.endsWith('.d.ts')) { 144 | // work around bad tsc behavior 145 | // if we have `import { type Readable } from 'together-ai/_shims/index'`, 146 | // tsc sometimes replaces `Readable` with `import("stream").Readable` inline 147 | // in the output .d.ts 148 | transformed = transformed.replace(/import\("stream"\).Readable/g, 'Readable'); 149 | } 150 | 151 | // strip out lib="dom" and types="node" references; these are needed at build time, 152 | // but would pollute the user's TS environment 153 | transformed = transformed.replace( 154 | /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', 157 | ); 158 | 159 | if (transformed !== code) { 160 | await fs.promises.writeFile(file, transformed, 'utf8'); 161 | console.error(`wrote ${path.relative(process.cwd(), file)}`); 162 | } 163 | } 164 | } 165 | postprocess(); 166 | -------------------------------------------------------------------------------- /scripts/utils/upload-artifact.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exuo pipefail 3 | 4 | RESPONSE=$(curl -X POST "$URL" \ 5 | -H "Authorization: Bearer $AUTH" \ 6 | -H "Content-Type: application/json") 7 | 8 | SIGNED_URL=$(echo "$RESPONSE" | jq -r '.url') 9 | 10 | if [[ "$SIGNED_URL" == "null" ]]; then 11 | echo -e "\033[31mFailed to get signed URL.\033[0m" 12 | exit 1 13 | fi 14 | 15 | UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \ 16 | -H "Content-Type: application/gzip" \ 17 | --data-binary @- "$SIGNED_URL" 2>&1) 18 | 19 | if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then 20 | echo -e "\033[32mUploaded build to Stainless storage.\033[0m" 21 | echo -e "\033[32mInstallation: npm install 'https://pkg.stainless.com/s/togetherai-node/$SHA'\033[0m" 22 | else 23 | echo -e "\033[31mFailed to upload artifact.\033[0m" 24 | exit 1 25 | fi 26 | -------------------------------------------------------------------------------- /src/_shims/MultipartBody.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export class MultipartBody { 5 | constructor(public body: any) {} 6 | get [Symbol.toStringTag](): string { 7 | return 'MultipartBody'; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/_shims/README.md: -------------------------------------------------------------------------------- 1 | # 👋 Wondering what everything in here does? 2 | 3 | `together-ai` supports a wide variety of runtime environments like Node.js, Deno, Bun, browsers, and various 4 | edge runtimes, as well as both CommonJS (CJS) and EcmaScript Modules (ESM). 5 | 6 | To do this, `together-ai` provides shims for either using `node-fetch` when in Node (because `fetch` is still experimental there) or the global `fetch` API built into the environment when not in Node. 7 | 8 | It uses [conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to 9 | automatically select the correct shims for each environment. However, conditional exports are a fairly new 10 | feature and not supported everywhere. For instance, the TypeScript `"moduleResolution": "node"` 11 | 12 | setting doesn't consult the `exports` map, compared to `"moduleResolution": "nodeNext"`, which does. 13 | Unfortunately that's still the default setting, and it can result in errors like 14 | getting the wrong raw `Response` type from `.asResponse()`, for example. 15 | 16 | The user can work around these issues by manually importing one of: 17 | 18 | - `import 'together-ai/shims/node'` 19 | - `import 'together-ai/shims/web'` 20 | 21 | All of the code here in `_shims` handles selecting the automatic default shims or manual overrides. 22 | 23 | ### How it works - Runtime 24 | 25 | Runtime shims get installed by calling `setShims` exported by `together-ai/_shims/registry`. 26 | 27 | Manually importing `together-ai/shims/node` or `together-ai/shims/web`, calls `setShims` with the respective runtime shims. 28 | 29 | All client code imports shims from `together-ai/_shims/index`, which: 30 | 31 | - checks if shims have been set manually 32 | - if not, calls `setShims` with the shims from `together-ai/_shims/auto/runtime` 33 | - re-exports the installed shims from `together-ai/_shims/registry`. 34 | 35 | `together-ai/_shims/auto/runtime` exports web runtime shims. 36 | If the `node` export condition is set, the export map replaces it with `together-ai/_shims/auto/runtime-node`. 37 | 38 | ### How it works - Type time 39 | 40 | All client code imports shim types from `together-ai/_shims/index`, which selects the manual types from `together-ai/_shims/manual-types` if they have been declared, otherwise it exports the auto types from `together-ai/_shims/auto/types`. 41 | 42 | `together-ai/_shims/manual-types` exports an empty namespace. 43 | Manually importing `together-ai/shims/node` or `together-ai/shims/web` merges declarations into this empty namespace, so they get picked up by `together-ai/_shims/index`. 44 | 45 | `together-ai/_shims/auto/types` exports web type definitions. 46 | If the `node` export condition is set, the export map replaces it with `together-ai/_shims/auto/types-node`, though TS only picks this up if `"moduleResolution": "nodenext"` or `"moduleResolution": "bundler"`. 47 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime-bun.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../bun-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime-deno.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../web-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime-node.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../node-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../web-runtime'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/types-deno.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../web-types'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/types-node.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export * from '../node-types'; 5 | -------------------------------------------------------------------------------- /src/_shims/auto/types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export type Agent = any; 5 | 6 | // @ts-ignore 7 | declare const _fetch: unknown extends typeof fetch ? never : typeof fetch; 8 | export { _fetch as fetch }; 9 | 10 | // @ts-ignore 11 | type _Request = unknown extends Request ? never : Request; 12 | export { _Request as Request }; 13 | 14 | // @ts-ignore 15 | type _RequestInfo = unknown extends RequestInfo ? never : RequestInfo; 16 | export { type _RequestInfo as RequestInfo }; 17 | 18 | // @ts-ignore 19 | type _RequestInit = unknown extends RequestInit ? never : RequestInit; 20 | export { type _RequestInit as RequestInit }; 21 | 22 | // @ts-ignore 23 | type _Response = unknown extends Response ? never : Response; 24 | export { _Response as Response }; 25 | 26 | // @ts-ignore 27 | type _ResponseInit = unknown extends ResponseInit ? never : ResponseInit; 28 | export { type _ResponseInit as ResponseInit }; 29 | 30 | // @ts-ignore 31 | type _ResponseType = unknown extends ResponseType ? never : ResponseType; 32 | export { type _ResponseType as ResponseType }; 33 | 34 | // @ts-ignore 35 | type _BodyInit = unknown extends BodyInit ? never : BodyInit; 36 | export { type _BodyInit as BodyInit }; 37 | 38 | // @ts-ignore 39 | type _Headers = unknown extends Headers ? never : Headers; 40 | export { _Headers as Headers }; 41 | 42 | // @ts-ignore 43 | type _HeadersInit = unknown extends HeadersInit ? never : HeadersInit; 44 | export { type _HeadersInit as HeadersInit }; 45 | 46 | type EndingType = 'native' | 'transparent'; 47 | 48 | export interface BlobPropertyBag { 49 | endings?: EndingType; 50 | type?: string; 51 | } 52 | 53 | export interface FilePropertyBag extends BlobPropertyBag { 54 | lastModified?: number; 55 | } 56 | 57 | export type FileFromPathOptions = Omit; 58 | 59 | // @ts-ignore 60 | type _FormData = unknown extends FormData ? never : FormData; 61 | // @ts-ignore 62 | declare const _FormData: unknown extends typeof FormData ? never : typeof FormData; 63 | export { _FormData as FormData }; 64 | 65 | // @ts-ignore 66 | type _File = unknown extends File ? never : File; 67 | // @ts-ignore 68 | declare const _File: unknown extends typeof File ? never : typeof File; 69 | export { _File as File }; 70 | 71 | // @ts-ignore 72 | type _Blob = unknown extends Blob ? never : Blob; 73 | // @ts-ignore 74 | declare const _Blob: unknown extends typeof Blob ? never : typeof Blob; 75 | export { _Blob as Blob }; 76 | 77 | export declare class Readable { 78 | readable: boolean; 79 | readonly readableEnded: boolean; 80 | readonly readableFlowing: boolean | null; 81 | readonly readableHighWaterMark: number; 82 | readonly readableLength: number; 83 | readonly readableObjectMode: boolean; 84 | destroyed: boolean; 85 | read(size?: number): any; 86 | pause(): this; 87 | resume(): this; 88 | isPaused(): boolean; 89 | destroy(error?: Error): this; 90 | [Symbol.asyncIterator](): AsyncIterableIterator; 91 | } 92 | 93 | export declare class FsReadStream extends Readable { 94 | path: {}; // node type is string | Buffer 95 | } 96 | 97 | // @ts-ignore 98 | type _ReadableStream = unknown extends ReadableStream ? never : ReadableStream; 99 | // @ts-ignore 100 | declare const _ReadableStream: unknown extends typeof ReadableStream ? never : typeof ReadableStream; 101 | export { _ReadableStream as ReadableStream }; 102 | -------------------------------------------------------------------------------- /src/_shims/auto/types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/auto/types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/bun-runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { type Shims } from './registry'; 5 | import { getRuntime as getWebRuntime } from './web-runtime'; 6 | import { ReadStream as FsReadStream } from 'node:fs'; 7 | 8 | export function getRuntime(): Shims { 9 | const runtime = getWebRuntime(); 10 | function isFsReadStream(value: any): value is FsReadStream { 11 | return value instanceof FsReadStream; 12 | } 13 | return { ...runtime, isFsReadStream }; 14 | } 15 | -------------------------------------------------------------------------------- /src/_shims/index-deno.ts: -------------------------------------------------------------------------------- 1 | import { MultipartBody } from './MultipartBody'; 2 | import { type RequestOptions } from '../core'; 3 | 4 | export const kind: string = 'web'; 5 | 6 | export type Agent = any; 7 | 8 | const _fetch = fetch; 9 | type _fetch = typeof fetch; 10 | export { _fetch as fetch }; 11 | 12 | const _Request = Request; 13 | type _Request = Request; 14 | export { _Request as Request }; 15 | 16 | type _RequestInfo = RequestInfo; 17 | export { type _RequestInfo as RequestInfo }; 18 | 19 | type _RequestInit = RequestInit; 20 | export { type _RequestInit as RequestInit }; 21 | 22 | const _Response = Response; 23 | type _Response = Response; 24 | export { _Response as Response }; 25 | 26 | type _ResponseInit = ResponseInit; 27 | export { type _ResponseInit as ResponseInit }; 28 | 29 | type _ResponseType = ResponseType; 30 | export { type _ResponseType as ResponseType }; 31 | 32 | type _BodyInit = BodyInit; 33 | export { type _BodyInit as BodyInit }; 34 | 35 | const _Headers = Headers; 36 | type _Headers = Headers; 37 | export { _Headers as Headers }; 38 | 39 | type _HeadersInit = HeadersInit; 40 | export { type _HeadersInit as HeadersInit }; 41 | 42 | type EndingType = 'native' | 'transparent'; 43 | 44 | export interface BlobPropertyBag { 45 | endings?: EndingType; 46 | type?: string; 47 | } 48 | 49 | export interface FilePropertyBag extends BlobPropertyBag { 50 | lastModified?: number; 51 | } 52 | 53 | export type FileFromPathOptions = Omit; 54 | 55 | const _FormData = FormData; 56 | type _FormData = FormData; 57 | export { _FormData as FormData }; 58 | 59 | const _File = File; 60 | type _File = File; 61 | export { _File as File }; 62 | 63 | const _Blob = Blob; 64 | type _Blob = Blob; 65 | export { _Blob as Blob }; 66 | 67 | export async function getMultipartRequestOptions>( 68 | form: FormData, 69 | opts: RequestOptions, 70 | ): Promise> { 71 | return { 72 | ...opts, 73 | body: new MultipartBody(form) as any, 74 | }; 75 | } 76 | 77 | export function getDefaultAgent(url: string) { 78 | return undefined; 79 | } 80 | export function fileFromPath() { 81 | throw new Error( 82 | 'The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/togethercomputer/together-typescript#file-uploads', 83 | ); 84 | } 85 | 86 | export const isFsReadStream = (value: any) => false; 87 | 88 | export declare class Readable { 89 | readable: boolean; 90 | readonly readableEnded: boolean; 91 | readonly readableFlowing: boolean | null; 92 | readonly readableHighWaterMark: number; 93 | readonly readableLength: number; 94 | readonly readableObjectMode: boolean; 95 | destroyed: boolean; 96 | read(size?: number): any; 97 | pause(): this; 98 | resume(): this; 99 | isPaused(): boolean; 100 | destroy(error?: Error): this; 101 | [Symbol.asyncIterator](): AsyncIterableIterator; 102 | } 103 | 104 | export declare class FsReadStream extends Readable { 105 | path: {}; // node type is string | Buffer 106 | } 107 | 108 | const _ReadableStream = ReadableStream; 109 | type _ReadableStream = ReadableStream; 110 | export { _ReadableStream as ReadableStream }; 111 | 112 | export const init = () => {}; 113 | -------------------------------------------------------------------------------- /src/_shims/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { manual } from './manual-types'; 5 | import * as auto from 'together-ai/_shims/auto/types'; 6 | import { type RequestOptions } from '../core'; 7 | 8 | type SelectType = unknown extends Manual ? Auto : Manual; 9 | 10 | export const kind: string; 11 | 12 | // @ts-ignore 13 | export type Agent = SelectType; 14 | 15 | // @ts-ignore 16 | export const fetch: SelectType; 17 | 18 | // @ts-ignore 19 | export type Request = SelectType; 20 | // @ts-ignore 21 | export type RequestInfo = SelectType; 22 | // @ts-ignore 23 | export type RequestInit = SelectType; 24 | 25 | // @ts-ignore 26 | export type Response = SelectType; 27 | // @ts-ignore 28 | export type ResponseInit = SelectType; 29 | // @ts-ignore 30 | export type ResponseType = SelectType; 31 | // @ts-ignore 32 | export type BodyInit = SelectType; 33 | // @ts-ignore 34 | export type Headers = SelectType; 35 | // @ts-ignore 36 | export const Headers: SelectType; 37 | // @ts-ignore 38 | export type HeadersInit = SelectType; 39 | 40 | // @ts-ignore 41 | export type BlobPropertyBag = SelectType; 42 | // @ts-ignore 43 | export type FilePropertyBag = SelectType; 44 | // @ts-ignore 45 | export type FileFromPathOptions = SelectType; 46 | // @ts-ignore 47 | export type FormData = SelectType; 48 | // @ts-ignore 49 | export const FormData: SelectType; 50 | // @ts-ignore 51 | export type File = SelectType; 52 | // @ts-ignore 53 | export const File: SelectType; 54 | // @ts-ignore 55 | export type Blob = SelectType; 56 | // @ts-ignore 57 | export const Blob: SelectType; 58 | 59 | // @ts-ignore 60 | export type Readable = SelectType; 61 | // @ts-ignore 62 | export type FsReadStream = SelectType; 63 | // @ts-ignore 64 | export type ReadableStream = SelectType; 65 | // @ts-ignore 66 | export const ReadableStream: SelectType; 67 | 68 | export function getMultipartRequestOptions>( 69 | form: FormData, 70 | opts: RequestOptions, 71 | ): Promise>; 72 | 73 | export function getDefaultAgent(url: string): any; 74 | 75 | // @ts-ignore 76 | export type FileFromPathOptions = SelectType; 77 | 78 | export function fileFromPath(path: string, options?: FileFromPathOptions): Promise; 79 | export function fileFromPath(path: string, filename?: string, options?: FileFromPathOptions): Promise; 80 | 81 | export function isFsReadStream(value: any): value is FsReadStream; 82 | 83 | export const init: () => void; 84 | -------------------------------------------------------------------------------- /src/_shims/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | const shims = require('./registry'); 5 | const auto = require('together-ai/_shims/auto/runtime'); 6 | exports.init = () => { 7 | if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); 8 | }; 9 | for (const property of Object.keys(shims)) { 10 | Object.defineProperty(exports, property, { 11 | get() { 12 | return shims[property]; 13 | }, 14 | }); 15 | } 16 | 17 | exports.init(); 18 | -------------------------------------------------------------------------------- /src/_shims/index.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import * as shims from './registry.mjs'; 5 | import * as auto from 'together-ai/_shims/auto/runtime'; 6 | export const init = () => { 7 | if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); 8 | }; 9 | export * from './registry.mjs'; 10 | 11 | init(); 12 | -------------------------------------------------------------------------------- /src/_shims/manual-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | /** 5 | * Types will get added to this namespace when you import one of the following: 6 | * 7 | * import 'together-ai/shims/node' 8 | * import 'together-ai/shims/web' 9 | * 10 | * Importing more than one will cause type and runtime errors. 11 | */ 12 | export namespace manual {} 13 | -------------------------------------------------------------------------------- /src/_shims/manual-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/manual-types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/node-runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import * as nf from 'node-fetch'; 5 | import * as fd from 'formdata-node'; 6 | import { type File, type FilePropertyBag } from 'formdata-node'; 7 | import KeepAliveAgent from 'agentkeepalive'; 8 | import { AbortController as AbortControllerPolyfill } from 'abort-controller'; 9 | import { ReadStream as FsReadStream } from 'node:fs'; 10 | import { type Agent } from 'node:http'; 11 | import { FormDataEncoder } from 'form-data-encoder'; 12 | import { Readable } from 'node:stream'; 13 | import { type RequestOptions } from '../core'; 14 | import { MultipartBody } from './MultipartBody'; 15 | import { type Shims } from './registry'; 16 | import { ReadableStream } from 'node:stream/web'; 17 | 18 | type FileFromPathOptions = Omit; 19 | 20 | let fileFromPathWarned = false; 21 | 22 | /** 23 | * @deprecated use fs.createReadStream('./my/file.txt') instead 24 | */ 25 | async function fileFromPath(path: string): Promise; 26 | async function fileFromPath(path: string, filename?: string): Promise; 27 | async function fileFromPath(path: string, options?: FileFromPathOptions): Promise; 28 | async function fileFromPath(path: string, filename?: string, options?: FileFromPathOptions): Promise; 29 | async function fileFromPath(path: string, ...args: any[]): Promise { 30 | // this import fails in environments that don't handle export maps correctly, like old versions of Jest 31 | const { fileFromPath: _fileFromPath } = await import('formdata-node/file-from-path'); 32 | 33 | if (!fileFromPathWarned) { 34 | console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path)}) instead`); 35 | fileFromPathWarned = true; 36 | } 37 | // @ts-ignore 38 | return await _fileFromPath(path, ...args); 39 | } 40 | 41 | const defaultHttpAgent: Agent = new KeepAliveAgent({ keepAlive: true, timeout: 5 * 60 * 1000 }); 42 | const defaultHttpsAgent: Agent = new KeepAliveAgent.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1000 }); 43 | 44 | async function getMultipartRequestOptions>( 45 | form: fd.FormData, 46 | opts: RequestOptions, 47 | ): Promise> { 48 | const encoder = new FormDataEncoder(form); 49 | const readable = Readable.from(encoder); 50 | const body = new MultipartBody(readable); 51 | const headers = { 52 | ...opts.headers, 53 | ...encoder.headers, 54 | 'Content-Length': encoder.contentLength, 55 | }; 56 | 57 | return { ...opts, body: body as any, headers }; 58 | } 59 | 60 | export function getRuntime(): Shims { 61 | // Polyfill global object if needed. 62 | if (typeof AbortController === 'undefined') { 63 | // @ts-expect-error (the types are subtly different, but compatible in practice) 64 | globalThis.AbortController = AbortControllerPolyfill; 65 | } 66 | return { 67 | kind: 'node', 68 | fetch: nf.default, 69 | Request: nf.Request, 70 | Response: nf.Response, 71 | Headers: nf.Headers, 72 | FormData: fd.FormData, 73 | Blob: fd.Blob, 74 | File: fd.File, 75 | ReadableStream, 76 | getMultipartRequestOptions, 77 | getDefaultAgent: (url: string): Agent => (url.startsWith('https') ? defaultHttpsAgent : defaultHttpAgent), 78 | fileFromPath, 79 | isFsReadStream: (value: any): value is FsReadStream => value instanceof FsReadStream, 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/_shims/node-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import * as nf from 'node-fetch'; 5 | import * as fd from 'formdata-node'; 6 | 7 | export { type Agent } from 'node:http'; 8 | export { type Readable } from 'node:stream'; 9 | export { type ReadStream as FsReadStream } from 'node:fs'; 10 | export { ReadableStream } from 'node:stream/web'; 11 | 12 | export const fetch: typeof nf.default; 13 | 14 | export type Request = nf.Request; 15 | export type RequestInfo = nf.RequestInfo; 16 | export type RequestInit = nf.RequestInit; 17 | 18 | export type Response = nf.Response; 19 | export type ResponseInit = nf.ResponseInit; 20 | export type ResponseType = nf.ResponseType; 21 | export type BodyInit = nf.BodyInit; 22 | export type Headers = nf.Headers; 23 | export type HeadersInit = nf.HeadersInit; 24 | 25 | type EndingType = 'native' | 'transparent'; 26 | export interface BlobPropertyBag { 27 | endings?: EndingType; 28 | type?: string; 29 | } 30 | 31 | export interface FilePropertyBag extends BlobPropertyBag { 32 | lastModified?: number; 33 | } 34 | 35 | export type FileFromPathOptions = Omit; 36 | 37 | export type FormData = fd.FormData; 38 | export const FormData: typeof fd.FormData; 39 | export type File = fd.File; 40 | export const File: typeof fd.File; 41 | export type Blob = fd.Blob; 42 | export const Blob: typeof fd.Blob; 43 | -------------------------------------------------------------------------------- /src/_shims/node-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/node-types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/registry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { type RequestOptions } from '../core'; 5 | 6 | export interface Shims { 7 | kind: string; 8 | fetch: any; 9 | Request: any; 10 | Response: any; 11 | Headers: any; 12 | FormData: any; 13 | Blob: any; 14 | File: any; 15 | ReadableStream: any; 16 | getMultipartRequestOptions: >( 17 | form: Shims['FormData'], 18 | opts: RequestOptions, 19 | ) => Promise>; 20 | getDefaultAgent: (url: string) => any; 21 | fileFromPath: 22 | | ((path: string, filename?: string, options?: {}) => Promise) 23 | | ((path: string, options?: {}) => Promise); 24 | isFsReadStream: (value: any) => boolean; 25 | } 26 | 27 | export let auto = false; 28 | export let kind: Shims['kind'] | undefined = undefined; 29 | export let fetch: Shims['fetch'] | undefined = undefined; 30 | export let Request: Shims['Request'] | undefined = undefined; 31 | export let Response: Shims['Response'] | undefined = undefined; 32 | export let Headers: Shims['Headers'] | undefined = undefined; 33 | export let FormData: Shims['FormData'] | undefined = undefined; 34 | export let Blob: Shims['Blob'] | undefined = undefined; 35 | export let File: Shims['File'] | undefined = undefined; 36 | export let ReadableStream: Shims['ReadableStream'] | undefined = undefined; 37 | export let getMultipartRequestOptions: Shims['getMultipartRequestOptions'] | undefined = undefined; 38 | export let getDefaultAgent: Shims['getDefaultAgent'] | undefined = undefined; 39 | export let fileFromPath: Shims['fileFromPath'] | undefined = undefined; 40 | export let isFsReadStream: Shims['isFsReadStream'] | undefined = undefined; 41 | 42 | export function setShims(shims: Shims, options: { auto: boolean } = { auto: false }) { 43 | if (auto) { 44 | throw new Error( 45 | `you must \`import 'together-ai/shims/${shims.kind}'\` before importing anything else from together-ai`, 46 | ); 47 | } 48 | if (kind) { 49 | throw new Error( 50 | `can't \`import 'together-ai/shims/${shims.kind}'\` after \`import 'together-ai/shims/${kind}'\``, 51 | ); 52 | } 53 | auto = options.auto; 54 | kind = shims.kind; 55 | fetch = shims.fetch; 56 | Request = shims.Request; 57 | Response = shims.Response; 58 | Headers = shims.Headers; 59 | FormData = shims.FormData; 60 | Blob = shims.Blob; 61 | File = shims.File; 62 | ReadableStream = shims.ReadableStream; 63 | getMultipartRequestOptions = shims.getMultipartRequestOptions; 64 | getDefaultAgent = shims.getDefaultAgent; 65 | fileFromPath = shims.fileFromPath; 66 | isFsReadStream = shims.isFsReadStream; 67 | } 68 | -------------------------------------------------------------------------------- /src/_shims/web-runtime.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | import { MultipartBody } from './MultipartBody'; 5 | import { type RequestOptions } from '../core'; 6 | import { type Shims } from './registry'; 7 | 8 | export function getRuntime({ manuallyImported }: { manuallyImported?: boolean } = {}): Shims { 9 | const recommendation = 10 | manuallyImported ? 11 | `You may need to use polyfills` 12 | : `Add one of these imports before your first \`import … from 'together-ai'\`: 13 | - \`import 'together-ai/shims/node'\` (if you're running on Node) 14 | - \`import 'together-ai/shims/web'\` (otherwise) 15 | `; 16 | 17 | let _fetch, _Request, _Response, _Headers; 18 | try { 19 | // @ts-ignore 20 | _fetch = fetch; 21 | // @ts-ignore 22 | _Request = Request; 23 | // @ts-ignore 24 | _Response = Response; 25 | // @ts-ignore 26 | _Headers = Headers; 27 | } catch (error) { 28 | throw new Error( 29 | `this environment is missing the following Web Fetch API type: ${ 30 | (error as any).message 31 | }. ${recommendation}`, 32 | ); 33 | } 34 | 35 | return { 36 | kind: 'web', 37 | fetch: _fetch, 38 | Request: _Request, 39 | Response: _Response, 40 | Headers: _Headers, 41 | FormData: 42 | // @ts-ignore 43 | typeof FormData !== 'undefined' ? FormData : ( 44 | class FormData { 45 | // @ts-ignore 46 | constructor() { 47 | throw new Error( 48 | `file uploads aren't supported in this environment yet as 'FormData' is undefined. ${recommendation}`, 49 | ); 50 | } 51 | } 52 | ), 53 | Blob: 54 | typeof Blob !== 'undefined' ? Blob : ( 55 | class Blob { 56 | constructor() { 57 | throw new Error( 58 | `file uploads aren't supported in this environment yet as 'Blob' is undefined. ${recommendation}`, 59 | ); 60 | } 61 | } 62 | ), 63 | File: 64 | // @ts-ignore 65 | typeof File !== 'undefined' ? File : ( 66 | class File { 67 | // @ts-ignore 68 | constructor() { 69 | throw new Error( 70 | `file uploads aren't supported in this environment yet as 'File' is undefined. ${recommendation}`, 71 | ); 72 | } 73 | } 74 | ), 75 | ReadableStream: 76 | // @ts-ignore 77 | typeof ReadableStream !== 'undefined' ? ReadableStream : ( 78 | class ReadableStream { 79 | // @ts-ignore 80 | constructor() { 81 | throw new Error( 82 | `streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`, 83 | ); 84 | } 85 | } 86 | ), 87 | getMultipartRequestOptions: async >( 88 | // @ts-ignore 89 | form: FormData, 90 | opts: RequestOptions, 91 | ): Promise> => ({ 92 | ...opts, 93 | body: new MultipartBody(form) as any, 94 | }), 95 | getDefaultAgent: (url: string) => undefined, 96 | fileFromPath: () => { 97 | throw new Error( 98 | 'The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/togethercomputer/together-typescript#file-uploads', 99 | ); 100 | }, 101 | isFsReadStream: (value: any) => false, 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /src/_shims/web-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | export type Agent = any; 5 | 6 | declare const _fetch: typeof fetch; 7 | export { _fetch as fetch }; 8 | 9 | type _Request = Request; 10 | export { _Request as Request }; 11 | 12 | type _RequestInfo = RequestInfo; 13 | export { type _RequestInfo as RequestInfo }; 14 | 15 | type _RequestInit = RequestInit; 16 | export { type _RequestInit as RequestInit }; 17 | 18 | type _Response = Response; 19 | export { _Response as Response }; 20 | 21 | type _ResponseInit = ResponseInit; 22 | export { type _ResponseInit as ResponseInit }; 23 | 24 | type _ResponseType = ResponseType; 25 | export { type _ResponseType as ResponseType }; 26 | 27 | type _BodyInit = BodyInit; 28 | export { type _BodyInit as BodyInit }; 29 | 30 | type _Headers = Headers; 31 | export { _Headers as Headers }; 32 | 33 | type _HeadersInit = HeadersInit; 34 | export { type _HeadersInit as HeadersInit }; 35 | 36 | type EndingType = 'native' | 'transparent'; 37 | 38 | export interface BlobPropertyBag { 39 | endings?: EndingType; 40 | type?: string; 41 | } 42 | 43 | export interface FilePropertyBag extends BlobPropertyBag { 44 | lastModified?: number; 45 | } 46 | 47 | export type FileFromPathOptions = Omit; 48 | 49 | type _FormData = FormData; 50 | declare const _FormData: typeof FormData; 51 | export { _FormData as FormData }; 52 | 53 | type _File = File; 54 | declare const _File: typeof File; 55 | export { _File as File }; 56 | 57 | type _Blob = Blob; 58 | declare const _Blob: typeof Blob; 59 | export { _Blob as Blob }; 60 | 61 | export declare class Readable { 62 | readable: boolean; 63 | readonly readableEnded: boolean; 64 | readonly readableFlowing: boolean | null; 65 | readonly readableHighWaterMark: number; 66 | readonly readableLength: number; 67 | readonly readableObjectMode: boolean; 68 | destroyed: boolean; 69 | read(size?: number): any; 70 | pause(): this; 71 | resume(): this; 72 | isPaused(): boolean; 73 | destroy(error?: Error): this; 74 | [Symbol.asyncIterator](): AsyncIterableIterator; 75 | } 76 | 77 | export declare class FsReadStream extends Readable { 78 | path: {}; // node type is string | Buffer 79 | } 80 | 81 | type _ReadableStream = ReadableStream; 82 | declare const _ReadableStream: typeof ReadableStream; 83 | export { _ReadableStream as ReadableStream }; 84 | -------------------------------------------------------------------------------- /src/_shims/web-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/_shims/web-types.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Disclaimer: modules in _shims aren't intended to be imported by SDK users. 3 | */ 4 | -------------------------------------------------------------------------------- /src/error.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { castToError, Headers } from './core'; 4 | 5 | export class TogetherError extends Error {} 6 | 7 | export class APIError< 8 | TStatus extends number | undefined = number | undefined, 9 | THeaders extends Headers | undefined = Headers | undefined, 10 | TError extends Object | undefined = Object | undefined, 11 | > extends TogetherError { 12 | /** HTTP status for the response that caused the error */ 13 | readonly status: TStatus; 14 | /** HTTP headers for the response that caused the error */ 15 | readonly headers: THeaders; 16 | /** JSON body of the response that caused the error */ 17 | readonly error: TError; 18 | 19 | constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) { 20 | super(`${APIError.makeMessage(status, error, message)}`); 21 | this.status = status; 22 | this.headers = headers; 23 | this.error = error; 24 | } 25 | 26 | private static makeMessage(status: number | undefined, error: any, message: string | undefined) { 27 | const msg = 28 | error?.message ? 29 | typeof error.message === 'string' ? 30 | error.message 31 | : JSON.stringify(error.message) 32 | : error ? JSON.stringify(error) 33 | : message; 34 | 35 | if (status && msg) { 36 | return `${status} ${msg}`; 37 | } 38 | if (status) { 39 | return `${status} status code (no body)`; 40 | } 41 | if (msg) { 42 | return msg; 43 | } 44 | return '(no status code or body)'; 45 | } 46 | 47 | static generate( 48 | status: number | undefined, 49 | errorResponse: Object | undefined, 50 | message: string | undefined, 51 | headers: Headers | undefined, 52 | ): APIError { 53 | if (!status || !headers) { 54 | return new APIConnectionError({ message, cause: castToError(errorResponse) }); 55 | } 56 | 57 | const error = errorResponse as Record; 58 | 59 | if (status === 400) { 60 | return new BadRequestError(status, error, message, headers); 61 | } 62 | 63 | if (status === 401) { 64 | return new AuthenticationError(status, error, message, headers); 65 | } 66 | 67 | if (status === 403) { 68 | return new PermissionDeniedError(status, error, message, headers); 69 | } 70 | 71 | if (status === 404) { 72 | return new NotFoundError(status, error, message, headers); 73 | } 74 | 75 | if (status === 409) { 76 | return new ConflictError(status, error, message, headers); 77 | } 78 | 79 | if (status === 422) { 80 | return new UnprocessableEntityError(status, error, message, headers); 81 | } 82 | 83 | if (status === 429) { 84 | return new RateLimitError(status, error, message, headers); 85 | } 86 | 87 | if (status >= 500) { 88 | return new InternalServerError(status, error, message, headers); 89 | } 90 | 91 | return new APIError(status, error, message, headers); 92 | } 93 | } 94 | 95 | export class APIUserAbortError extends APIError { 96 | constructor({ message }: { message?: string } = {}) { 97 | super(undefined, undefined, message || 'Request was aborted.', undefined); 98 | } 99 | } 100 | 101 | export class APIConnectionError extends APIError { 102 | constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) { 103 | super(undefined, undefined, message || 'Connection error.', undefined); 104 | // in some environments the 'cause' property is already declared 105 | // @ts-ignore 106 | if (cause) this.cause = cause; 107 | } 108 | } 109 | 110 | export class APIConnectionTimeoutError extends APIConnectionError { 111 | constructor({ message }: { message?: string } = {}) { 112 | super({ message: message ?? 'Request timed out.' }); 113 | } 114 | } 115 | 116 | export class BadRequestError extends APIError<400, Headers> {} 117 | 118 | export class AuthenticationError extends APIError<401, Headers> {} 119 | 120 | export class PermissionDeniedError extends APIError<403, Headers> {} 121 | 122 | export class NotFoundError extends APIError<404, Headers> {} 123 | 124 | export class ConflictError extends APIError<409, Headers> {} 125 | 126 | export class UnprocessableEntityError extends APIError<422, Headers> {} 127 | 128 | export class RateLimitError extends APIError<429, Headers> {} 129 | 130 | export class InternalServerError extends APIError {} 131 | -------------------------------------------------------------------------------- /src/internal/decoders/line.ts: -------------------------------------------------------------------------------- 1 | import { TogetherError } from '../../error'; 2 | 3 | export type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined; 4 | 5 | /** 6 | * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally 7 | * reading lines from text. 8 | * 9 | * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 10 | */ 11 | export class LineDecoder { 12 | // prettier-ignore 13 | static NEWLINE_CHARS = new Set(['\n', '\r']); 14 | static NEWLINE_REGEXP = /\r\n|[\n\r]/g; 15 | 16 | buffer: Uint8Array; 17 | #carriageReturnIndex: number | null; 18 | textDecoder: any; // TextDecoder found in browsers; not typed to avoid pulling in either "dom" or "node" types. 19 | 20 | constructor() { 21 | this.buffer = new Uint8Array(); 22 | this.#carriageReturnIndex = null; 23 | } 24 | 25 | decode(chunk: Bytes): string[] { 26 | if (chunk == null) { 27 | return []; 28 | } 29 | 30 | const binaryChunk = 31 | chunk instanceof ArrayBuffer ? new Uint8Array(chunk) 32 | : typeof chunk === 'string' ? new TextEncoder().encode(chunk) 33 | : chunk; 34 | 35 | let newData = new Uint8Array(this.buffer.length + binaryChunk.length); 36 | newData.set(this.buffer); 37 | newData.set(binaryChunk, this.buffer.length); 38 | this.buffer = newData; 39 | 40 | const lines: string[] = []; 41 | let patternIndex; 42 | while ((patternIndex = findNewlineIndex(this.buffer, this.#carriageReturnIndex)) != null) { 43 | if (patternIndex.carriage && this.#carriageReturnIndex == null) { 44 | // skip until we either get a corresponding `\n`, a new `\r` or nothing 45 | this.#carriageReturnIndex = patternIndex.index; 46 | continue; 47 | } 48 | 49 | // we got double \r or \rtext\n 50 | if ( 51 | this.#carriageReturnIndex != null && 52 | (patternIndex.index !== this.#carriageReturnIndex + 1 || patternIndex.carriage) 53 | ) { 54 | lines.push(this.decodeText(this.buffer.slice(0, this.#carriageReturnIndex - 1))); 55 | this.buffer = this.buffer.slice(this.#carriageReturnIndex); 56 | this.#carriageReturnIndex = null; 57 | continue; 58 | } 59 | 60 | const endIndex = 61 | this.#carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding; 62 | 63 | const line = this.decodeText(this.buffer.slice(0, endIndex)); 64 | lines.push(line); 65 | 66 | this.buffer = this.buffer.slice(patternIndex.index); 67 | this.#carriageReturnIndex = null; 68 | } 69 | 70 | return lines; 71 | } 72 | 73 | decodeText(bytes: Bytes): string { 74 | if (bytes == null) return ''; 75 | if (typeof bytes === 'string') return bytes; 76 | 77 | // Node: 78 | if (typeof Buffer !== 'undefined') { 79 | if (bytes instanceof Buffer) { 80 | return bytes.toString(); 81 | } 82 | if (bytes instanceof Uint8Array) { 83 | return Buffer.from(bytes).toString(); 84 | } 85 | 86 | throw new TogetherError( 87 | `Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.`, 88 | ); 89 | } 90 | 91 | // Browser 92 | if (typeof TextDecoder !== 'undefined') { 93 | if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) { 94 | this.textDecoder ??= new TextDecoder('utf8'); 95 | return this.textDecoder.decode(bytes); 96 | } 97 | 98 | throw new TogetherError( 99 | `Unexpected: received non-Uint8Array/ArrayBuffer (${ 100 | (bytes as any).constructor.name 101 | }) in a web platform. Please report this error.`, 102 | ); 103 | } 104 | 105 | throw new TogetherError( 106 | `Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`, 107 | ); 108 | } 109 | 110 | flush(): string[] { 111 | if (!this.buffer.length) { 112 | return []; 113 | } 114 | return this.decode('\n'); 115 | } 116 | } 117 | 118 | /** 119 | * This function searches the buffer for the end patterns, (\r or \n) 120 | * and returns an object with the index preceding the matched newline and the 121 | * index after the newline char. `null` is returned if no new line is found. 122 | * 123 | * ```ts 124 | * findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 } 125 | * ``` 126 | */ 127 | function findNewlineIndex( 128 | buffer: Uint8Array, 129 | startIndex: number | null, 130 | ): { preceding: number; index: number; carriage: boolean } | null { 131 | const newline = 0x0a; // \n 132 | const carriage = 0x0d; // \r 133 | 134 | for (let i = startIndex ?? 0; i < buffer.length; i++) { 135 | if (buffer[i] === newline) { 136 | return { preceding: i, index: i + 1, carriage: false }; 137 | } 138 | 139 | if (buffer[i] === carriage) { 140 | return { preceding: i, index: i + 1, carriage: true }; 141 | } 142 | } 143 | 144 | return null; 145 | } 146 | 147 | export function findDoubleNewlineIndex(buffer: Uint8Array): number { 148 | // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) 149 | // and returns the index right after the first occurrence of any pattern, 150 | // or -1 if none of the patterns are found. 151 | const newline = 0x0a; // \n 152 | const carriage = 0x0d; // \r 153 | 154 | for (let i = 0; i < buffer.length - 1; i++) { 155 | if (buffer[i] === newline && buffer[i + 1] === newline) { 156 | // \n\n 157 | return i + 2; 158 | } 159 | if (buffer[i] === carriage && buffer[i + 1] === carriage) { 160 | // \r\r 161 | return i + 2; 162 | } 163 | if ( 164 | buffer[i] === carriage && 165 | buffer[i + 1] === newline && 166 | i + 3 < buffer.length && 167 | buffer[i + 2] === carriage && 168 | buffer[i + 3] === newline 169 | ) { 170 | // \r\n\r\n 171 | return i + 4; 172 | } 173 | } 174 | 175 | return -1; 176 | } 177 | -------------------------------------------------------------------------------- /src/internal/stream-utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Most browsers don't yet have async iterable support for ReadableStream, 3 | * and Node has a very different way of reading bytes from its "ReadableStream". 4 | * 5 | * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 6 | */ 7 | export function ReadableStreamToAsyncIterable(stream: any): AsyncIterableIterator { 8 | if (stream[Symbol.asyncIterator]) return stream; 9 | 10 | const reader = stream.getReader(); 11 | return { 12 | async next() { 13 | try { 14 | const result = await reader.read(); 15 | if (result?.done) reader.releaseLock(); // release lock when stream becomes closed 16 | return result; 17 | } catch (e) { 18 | reader.releaseLock(); // release lock when stream becomes errored 19 | throw e; 20 | } 21 | }, 22 | async return() { 23 | const cancelPromise = reader.cancel(); 24 | reader.releaseLock(); 25 | await cancelPromise; 26 | return { done: true, value: undefined }; 27 | }, 28 | [Symbol.asyncIterator]() { 29 | return this; 30 | }, 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/lib/.keep: -------------------------------------------------------------------------------- 1 | File generated from our OpenAPI spec by Stainless. 2 | 3 | This directory can be used to store custom files to expand the SDK. 4 | It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. 5 | -------------------------------------------------------------------------------- /src/lib/ChatCompletionRunner.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type Completions, 3 | type ChatCompletionMessageParam, 4 | type CompletionCreateParamsNonStreaming, 5 | } from 'together-ai/resources/chat/completions'; 6 | import { type RunnableFunctions, type BaseFunctionsArgs, RunnableTools } from './RunnableFunction'; 7 | import { 8 | AbstractChatCompletionRunner, 9 | AbstractChatCompletionRunnerEvents, 10 | RunnerOptions, 11 | } from './AbstractChatCompletionRunner'; 12 | import { isAssistantMessage } from './chatCompletionUtils'; 13 | 14 | export interface ChatCompletionRunnerEvents extends AbstractChatCompletionRunnerEvents { 15 | content: (content: string) => void; 16 | } 17 | 18 | export type ChatCompletionFunctionRunnerParams = Omit< 19 | CompletionCreateParamsNonStreaming, 20 | 'functions' 21 | > & { 22 | functions: RunnableFunctions; 23 | }; 24 | 25 | export type ChatCompletionToolRunnerParams = Omit< 26 | CompletionCreateParamsNonStreaming, 27 | 'tools' 28 | > & { 29 | tools: RunnableTools; 30 | }; 31 | 32 | export class ChatCompletionRunner extends AbstractChatCompletionRunner { 33 | /** @deprecated - please use `runTools` instead. */ 34 | static runFunctions( 35 | completions: Completions, 36 | params: ChatCompletionFunctionRunnerParams, 37 | options?: RunnerOptions, 38 | ): ChatCompletionRunner { 39 | const runner = new ChatCompletionRunner(); 40 | const opts = { 41 | ...options, 42 | headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runFunctions' }, 43 | }; 44 | runner._run(() => runner._runFunctions(completions, params, opts)); 45 | return runner; 46 | } 47 | 48 | static runTools( 49 | completions: Completions, 50 | params: ChatCompletionToolRunnerParams, 51 | options?: RunnerOptions, 52 | ): ChatCompletionRunner { 53 | const runner = new ChatCompletionRunner(); 54 | const opts = { 55 | ...options, 56 | headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runTools' }, 57 | }; 58 | runner._run(() => runner._runTools(completions, params, opts)); 59 | return runner; 60 | } 61 | 62 | override _addMessage(message: ChatCompletionMessageParam) { 63 | super._addMessage(message); 64 | if (isAssistantMessage(message) && message.content) { 65 | this._emit('content', message.content as string); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/lib/ChatCompletionStreamingRunner.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Completions, 3 | type ChatCompletionChunk, 4 | type CompletionCreateParamsStreaming, 5 | } from 'together-ai/resources/chat/completions'; 6 | import { RunnerOptions, type AbstractChatCompletionRunnerEvents } from './AbstractChatCompletionRunner'; 7 | import { type ReadableStream } from 'together-ai/_shims/index'; 8 | import { RunnableTools, type BaseFunctionsArgs, type RunnableFunctions } from './RunnableFunction'; 9 | import { ChatCompletionSnapshot, ChatCompletionStream } from './ChatCompletionStream'; 10 | 11 | export interface ChatCompletionStreamEvents extends AbstractChatCompletionRunnerEvents { 12 | content: (contentDelta: string, contentSnapshot: string) => void; 13 | chunk: (chunk: ChatCompletionChunk, snapshot: ChatCompletionSnapshot) => void; 14 | } 15 | 16 | export type ChatCompletionStreamingFunctionRunnerParams = Omit< 17 | CompletionCreateParamsStreaming, 18 | 'functions' 19 | > & { 20 | functions: RunnableFunctions; 21 | }; 22 | 23 | export type ChatCompletionStreamingToolRunnerParams = Omit< 24 | CompletionCreateParamsStreaming, 25 | 'tools' 26 | > & { 27 | tools: RunnableTools; 28 | }; 29 | 30 | export class ChatCompletionStreamingRunner 31 | extends ChatCompletionStream 32 | implements AsyncIterable 33 | { 34 | static override fromReadableStream(stream: ReadableStream): ChatCompletionStreamingRunner { 35 | const runner = new ChatCompletionStreamingRunner(); 36 | runner._run(() => runner._fromReadableStream(stream)); 37 | return runner; 38 | } 39 | 40 | /** @deprecated - please use `runTools` instead. */ 41 | static runFunctions( 42 | completions: Completions, 43 | params: ChatCompletionStreamingFunctionRunnerParams, 44 | options?: RunnerOptions, 45 | ): ChatCompletionStreamingRunner { 46 | const runner = new ChatCompletionStreamingRunner(); 47 | const opts = { 48 | ...options, 49 | headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runFunctions' }, 50 | }; 51 | runner._run(() => runner._runFunctions(completions, params, opts)); 52 | return runner; 53 | } 54 | 55 | static runTools( 56 | completions: Completions, 57 | params: ChatCompletionStreamingToolRunnerParams, 58 | options?: RunnerOptions, 59 | ): ChatCompletionStreamingRunner { 60 | const runner = new ChatCompletionStreamingRunner(); 61 | const opts = { 62 | ...options, 63 | headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runTools' }, 64 | }; 65 | runner._run(() => runner._runTools(completions, params, opts)); 66 | return runner; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/lib/RunnableFunction.ts: -------------------------------------------------------------------------------- 1 | import { type ChatCompletionRunner } from './ChatCompletionRunner'; 2 | import { type ChatCompletionStreamingRunner } from './ChatCompletionStreamingRunner'; 3 | import { JSONSchema } from './jsonschema'; 4 | 5 | type PromiseOrValue = T | Promise; 6 | 7 | export type RunnableFunctionWithParse = { 8 | /** 9 | * @param args the return value from `parse`. 10 | * @param runner the runner evaluating this callback. 11 | * @returns a string to send back. 12 | */ 13 | function: ( 14 | args: Args, 15 | runner: ChatCompletionRunner | ChatCompletionStreamingRunner, 16 | ) => PromiseOrValue; 17 | /** 18 | * @param input the raw args from the function call. 19 | * @returns the parsed arguments to pass to `function` 20 | */ 21 | parse: (input: string) => PromiseOrValue; 22 | /** 23 | * The parameters the function accepts, describes as a JSON Schema object. 24 | */ 25 | parameters: JSONSchema; 26 | /** 27 | * A description of what the function does, used by the model to choose when and how to call the function. 28 | */ 29 | description: string; 30 | /** 31 | * The name of the function to be called. Will default to function.name if omitted. 32 | */ 33 | name?: string | undefined; 34 | }; 35 | 36 | export type RunnableFunctionWithoutParse = { 37 | /** 38 | * @param args the raw args from the function call. 39 | * @returns a string to send back 40 | */ 41 | function: ( 42 | args: string, 43 | runner: ChatCompletionRunner | ChatCompletionStreamingRunner, 44 | ) => PromiseOrValue; 45 | /** 46 | * The parameters the function accepts, describes as a JSON Schema object. 47 | */ 48 | parameters: JSONSchema; 49 | /** 50 | * A description of what the function does, used by the model to choose when and how to call the function. 51 | */ 52 | description: string; 53 | /** 54 | * The name of the function to be called. Will default to function.name if omitted. 55 | */ 56 | name?: string | undefined; 57 | }; 58 | 59 | export type RunnableFunction = 60 | Args extends string ? RunnableFunctionWithoutParse 61 | : Args extends object ? RunnableFunctionWithParse 62 | : never; 63 | 64 | export type RunnableToolFunction = 65 | Args extends string ? RunnableToolFunctionWithoutParse 66 | : Args extends object ? RunnableToolFunctionWithParse 67 | : never; 68 | 69 | export type RunnableToolFunctionWithoutParse = { 70 | type: 'function'; 71 | function: RunnableFunctionWithoutParse; 72 | }; 73 | export type RunnableToolFunctionWithParse = { 74 | type: 'function'; 75 | function: RunnableFunctionWithParse; 76 | }; 77 | 78 | export function isRunnableFunctionWithParse( 79 | fn: any, 80 | ): fn is RunnableFunctionWithParse { 81 | return typeof (fn as any).parse === 'function'; 82 | } 83 | 84 | export type BaseFunctionsArgs = readonly (object | string)[]; 85 | 86 | export type RunnableFunctions = 87 | [any[]] extends [FunctionsArgs] ? readonly RunnableFunction[] 88 | : { 89 | [Index in keyof FunctionsArgs]: Index extends number ? RunnableFunction 90 | : FunctionsArgs[Index]; 91 | }; 92 | 93 | export type RunnableTools = 94 | [any[]] extends [FunctionsArgs] ? readonly RunnableToolFunction[] 95 | : { 96 | [Index in keyof FunctionsArgs]: Index extends number ? RunnableToolFunction 97 | : FunctionsArgs[Index]; 98 | }; 99 | 100 | /** 101 | * This is helper class for passing a `function` and `parse` where the `function` 102 | * argument type matches the `parse` return type. 103 | * 104 | * @deprecated - please use ParsingToolFunction instead. 105 | */ 106 | export class ParsingFunction { 107 | function: RunnableFunctionWithParse['function']; 108 | parse: RunnableFunctionWithParse['parse']; 109 | parameters: RunnableFunctionWithParse['parameters']; 110 | description: RunnableFunctionWithParse['description']; 111 | name?: RunnableFunctionWithParse['name']; 112 | 113 | constructor(input: RunnableFunctionWithParse) { 114 | this.function = input.function; 115 | this.parse = input.parse; 116 | this.parameters = input.parameters; 117 | this.description = input.description; 118 | this.name = input.name; 119 | } 120 | } 121 | 122 | /** 123 | * This is helper class for passing a `function` and `parse` where the `function` 124 | * argument type matches the `parse` return type. 125 | */ 126 | export class ParsingToolFunction { 127 | type: 'function'; 128 | function: RunnableFunctionWithParse; 129 | 130 | constructor(input: RunnableFunctionWithParse) { 131 | this.type = 'function'; 132 | this.function = input; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/lib/chatCompletionUtils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | type ChatCompletionAssistantMessageParam, 3 | type ChatCompletionFunctionMessageParam, 4 | type ChatCompletionMessageParam, 5 | type ChatCompletionToolMessageParam, 6 | } from 'together-ai/resources/chat'; 7 | 8 | export const isAssistantMessage = ( 9 | message: ChatCompletionMessageParam | null | undefined, 10 | ): message is ChatCompletionAssistantMessageParam => { 11 | return message?.role === 'assistant'; 12 | }; 13 | 14 | export const isFunctionMessage = ( 15 | message: ChatCompletionMessageParam | null | undefined, 16 | ): message is ChatCompletionFunctionMessageParam => { 17 | return message?.role === 'function'; 18 | }; 19 | 20 | export const isToolMessage = ( 21 | message: ChatCompletionMessageParam | null | undefined, 22 | ): message is ChatCompletionToolMessageParam => { 23 | return message?.role === 'tool'; 24 | }; 25 | 26 | export function isPresent(obj: T | null | undefined): obj is T { 27 | return obj != null; 28 | } 29 | -------------------------------------------------------------------------------- /src/lib/jsonschema.ts: -------------------------------------------------------------------------------- 1 | // File mostly copied from @types/json-schema, but stripped down a bit for brevity 2 | // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/817274f3280152ba2929a6067c93df8b34c4c9aa/types/json-schema/index.d.ts 3 | // 4 | // ================================================================================================== 5 | // JSON Schema Draft 07 6 | // ================================================================================================== 7 | // https://tools.ietf.org/html/draft-handrews-json-schema-validation-01 8 | // -------------------------------------------------------------------------------------------------- 9 | 10 | /** 11 | * Primitive type 12 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1 13 | */ 14 | export type JSONSchemaTypeName = 15 | | ({} & string) 16 | | 'string' 17 | | 'number' 18 | | 'integer' 19 | | 'boolean' 20 | | 'object' 21 | | 'array' 22 | | 'null'; 23 | 24 | /** 25 | * Primitive type 26 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1 27 | */ 28 | export type JSONSchemaType = 29 | | string // 30 | | number 31 | | boolean 32 | | JSONSchemaObject 33 | | JSONSchemaArray 34 | | null; 35 | 36 | // Workaround for infinite type recursion 37 | export interface JSONSchemaObject { 38 | [key: string]: JSONSchemaType; 39 | } 40 | 41 | // Workaround for infinite type recursion 42 | // https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540 43 | export interface JSONSchemaArray extends Array {} 44 | 45 | /** 46 | * Meta schema 47 | * 48 | * Recommended values: 49 | * - 'http://json-schema.org/schema#' 50 | * - 'http://json-schema.org/hyper-schema#' 51 | * - 'http://json-schema.org/draft-07/schema#' 52 | * - 'http://json-schema.org/draft-07/hyper-schema#' 53 | * 54 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-5 55 | */ 56 | export type JSONSchemaVersion = string; 57 | 58 | /** 59 | * JSON Schema v7 60 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01 61 | */ 62 | export type JSONSchemaDefinition = JSONSchema | boolean; 63 | export interface JSONSchema { 64 | $id?: string | undefined; 65 | $comment?: string | undefined; 66 | 67 | /** 68 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1 69 | */ 70 | type?: JSONSchemaTypeName | JSONSchemaTypeName[] | undefined; 71 | enum?: JSONSchemaType[] | undefined; 72 | const?: JSONSchemaType | undefined; 73 | 74 | /** 75 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.2 76 | */ 77 | multipleOf?: number | undefined; 78 | maximum?: number | undefined; 79 | exclusiveMaximum?: number | undefined; 80 | minimum?: number | undefined; 81 | exclusiveMinimum?: number | undefined; 82 | 83 | /** 84 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.3 85 | */ 86 | maxLength?: number | undefined; 87 | minLength?: number | undefined; 88 | pattern?: string | undefined; 89 | 90 | /** 91 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4 92 | */ 93 | items?: JSONSchemaDefinition | JSONSchemaDefinition[] | undefined; 94 | additionalItems?: JSONSchemaDefinition | undefined; 95 | maxItems?: number | undefined; 96 | minItems?: number | undefined; 97 | uniqueItems?: boolean | undefined; 98 | contains?: JSONSchemaDefinition | undefined; 99 | 100 | /** 101 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.5 102 | */ 103 | maxProperties?: number | undefined; 104 | minProperties?: number | undefined; 105 | required?: string[] | undefined; 106 | properties?: 107 | | { 108 | [key: string]: JSONSchemaDefinition; 109 | } 110 | | undefined; 111 | patternProperties?: 112 | | { 113 | [key: string]: JSONSchemaDefinition; 114 | } 115 | | undefined; 116 | additionalProperties?: JSONSchemaDefinition | undefined; 117 | propertyNames?: JSONSchemaDefinition | undefined; 118 | 119 | /** 120 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.6 121 | */ 122 | if?: JSONSchemaDefinition | undefined; 123 | then?: JSONSchemaDefinition | undefined; 124 | else?: JSONSchemaDefinition | undefined; 125 | 126 | /** 127 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.7 128 | */ 129 | allOf?: JSONSchemaDefinition[] | undefined; 130 | anyOf?: JSONSchemaDefinition[] | undefined; 131 | oneOf?: JSONSchemaDefinition[] | undefined; 132 | not?: JSONSchemaDefinition | undefined; 133 | 134 | /** 135 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-7 136 | */ 137 | format?: string | undefined; 138 | 139 | /** 140 | * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-10 141 | */ 142 | title?: string | undefined; 143 | description?: string | undefined; 144 | default?: JSONSchemaType | undefined; 145 | readOnly?: boolean | undefined; 146 | writeOnly?: boolean | undefined; 147 | examples?: JSONSchemaType | undefined; 148 | } 149 | -------------------------------------------------------------------------------- /src/resource.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import type { Together } from './index'; 4 | 5 | export class APIResource { 6 | protected _client: Together; 7 | 8 | constructor(client: Together) { 9 | this._client = client; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/resources.ts: -------------------------------------------------------------------------------- 1 | export * from './resources/index'; 2 | -------------------------------------------------------------------------------- /src/resources/audio.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import * as Core from '../core'; 5 | import { type Response } from '../_shims/index'; 6 | 7 | export class Audio extends APIResource { 8 | /** 9 | * Generate audio from input text 10 | */ 11 | create(body: AudioCreateParams, options?: Core.RequestOptions): Core.APIPromise { 12 | return this._client.post('/audio/speech', { 13 | body, 14 | ...options, 15 | headers: { Accept: 'application/octet-stream', ...options?.headers }, 16 | __binaryResponse: true, 17 | }); 18 | } 19 | } 20 | 21 | export type AudioFile = AudioFile.AudioSpeechStreamEvent | AudioFile.StreamSentinel; 22 | 23 | export namespace AudioFile { 24 | export interface AudioSpeechStreamEvent { 25 | data: AudioSpeechStreamEvent.Data; 26 | } 27 | 28 | export namespace AudioSpeechStreamEvent { 29 | export interface Data { 30 | /** 31 | * base64 encoded audio stream 32 | */ 33 | b64: string; 34 | 35 | model: string; 36 | 37 | object: 'audio.tts.chunk'; 38 | } 39 | } 40 | 41 | export interface StreamSentinel { 42 | data: '[DONE]'; 43 | } 44 | } 45 | 46 | export interface AudioCreateParams { 47 | /** 48 | * Input text to generate the audio for 49 | */ 50 | input: string; 51 | 52 | /** 53 | * The name of the model to query. 54 | * 55 | * [See all of Together AI's chat models](https://docs.together.ai/docs/serverless-models#audio-models) 56 | */ 57 | model: 'cartesia/sonic' | (string & {}); 58 | 59 | /** 60 | * The voice to use for generating the audio. 61 | * [View all supported voices here](https://docs.together.ai/docs/text-to-speech#voices-available). 62 | */ 63 | voice: 'laidback woman' | 'polite man' | 'storyteller lady' | 'friendly sidekick' | (string & {}); 64 | 65 | /** 66 | * Language of input text 67 | */ 68 | language?: 69 | | 'en' 70 | | 'de' 71 | | 'fr' 72 | | 'es' 73 | | 'hi' 74 | | 'it' 75 | | 'ja' 76 | | 'ko' 77 | | 'nl' 78 | | 'pl' 79 | | 'pt' 80 | | 'ru' 81 | | 'sv' 82 | | 'tr' 83 | | 'zh'; 84 | 85 | /** 86 | * Audio encoding of response 87 | */ 88 | response_encoding?: 'pcm_f32le' | 'pcm_s16le' | 'pcm_mulaw' | 'pcm_alaw'; 89 | 90 | /** 91 | * The format of audio output 92 | */ 93 | response_format?: 'mp3' | 'wav' | 'raw'; 94 | 95 | /** 96 | * Sampling rate to use for the output audio 97 | */ 98 | sample_rate?: number; 99 | 100 | /** 101 | * If true, output is streamed for several characters at a time instead of waiting 102 | * for the full response. The stream terminates with `data: [DONE]`. If false, 103 | * return the encoded audio as octet stream 104 | */ 105 | stream?: boolean; 106 | } 107 | 108 | export declare namespace Audio { 109 | export { type AudioFile as AudioFile, type AudioCreateParams as AudioCreateParams }; 110 | } 111 | -------------------------------------------------------------------------------- /src/resources/chat.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './chat/index'; 4 | -------------------------------------------------------------------------------- /src/resources/chat/chat.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import * as CompletionsAPI from './completions'; 5 | import { 6 | ChatCompletion, 7 | ChatCompletionAssistantMessageParam, 8 | ChatCompletionChunk, 9 | ChatCompletionFunctionMessageParam, 10 | ChatCompletionMessage, 11 | ChatCompletionMessageParam, 12 | ChatCompletionSystemMessageParam, 13 | ChatCompletionTool, 14 | ChatCompletionToolMessageParam, 15 | ChatCompletionStructuredMessageImageURL, 16 | ChatCompletionStructuredMessageText, 17 | ChatCompletionUsage, 18 | ChatCompletionUserMessageParam, 19 | CompletionCreateParams, 20 | CompletionCreateParamsNonStreaming, 21 | CompletionCreateParamsStreaming, 22 | Completions, 23 | } from './completions'; 24 | 25 | export class Chat extends APIResource { 26 | completions: CompletionsAPI.Completions = new CompletionsAPI.Completions(this._client); 27 | } 28 | 29 | Chat.Completions = Completions; 30 | 31 | export declare namespace Chat { 32 | export { 33 | Completions as Completions, 34 | type ChatCompletion as ChatCompletion, 35 | type ChatCompletionAssistantMessageParam as ChatCompletionAssistantMessageParam, 36 | type ChatCompletionChunk as ChatCompletionChunk, 37 | type ChatCompletionFunctionMessageParam as ChatCompletionFunctionMessageParam, 38 | type ChatCompletionMessage as ChatCompletionMessage, 39 | type ChatCompletionMessageParam as ChatCompletionMessageParam, 40 | type ChatCompletionSystemMessageParam as ChatCompletionSystemMessageParam, 41 | type ChatCompletionTool as ChatCompletionTool, 42 | type ChatCompletionToolMessageParam as ChatCompletionToolMessageParam, 43 | type ChatCompletionStructuredMessageImageURL as ChatCompletionStructuredMessageImageURL, 44 | type ChatCompletionStructuredMessageText as ChatCompletionStructuredMessageText, 45 | type ChatCompletionUsage as ChatCompletionUsage, 46 | type ChatCompletionUserMessageParam as ChatCompletionUserMessageParam, 47 | type CompletionCreateParams as CompletionCreateParams, 48 | type CompletionCreateParamsNonStreaming as CompletionCreateParamsNonStreaming, 49 | type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming, 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /src/resources/chat/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { Chat } from './chat'; 4 | export { 5 | ChatCompletionAssistantMessageParam, 6 | ChatCompletionFunctionMessageParam, 7 | ChatCompletionMessage, 8 | ChatCompletionMessageParam, 9 | ChatCompletionSystemMessageParam, 10 | ChatCompletionTool, 11 | ChatCompletionToolMessageParam, 12 | ChatCompletionUserMessageParam, 13 | Completions, 14 | type ChatCompletion, 15 | type ChatCompletionChunk, 16 | type ChatCompletionStructuredMessageImageURL, 17 | type ChatCompletionStructuredMessageText, 18 | type ChatCompletionUsage, 19 | type CompletionCreateParams, 20 | type CompletionCreateParamsNonStreaming, 21 | type CompletionCreateParamsStreaming, 22 | } from './completions'; 23 | -------------------------------------------------------------------------------- /src/resources/code-interpreter.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export * from './code-interpreter/index'; 4 | -------------------------------------------------------------------------------- /src/resources/code-interpreter/code-interpreter.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import * as Core from '../../core'; 5 | import * as SessionsAPI from './sessions'; 6 | import { SessionListResponse, Sessions } from './sessions'; 7 | 8 | export class CodeInterpreter extends APIResource { 9 | sessions: SessionsAPI.Sessions = new SessionsAPI.Sessions(this._client); 10 | 11 | /** 12 | * Executes the given code snippet and returns the output. Without a session_id, a 13 | * new session will be created to run the code. If you do pass in a valid 14 | * session_id, the code will be run in that session. This is useful for running 15 | * multiple code snippets in the same environment, because dependencies and similar 16 | * things are persisted between calls to the same session. 17 | */ 18 | execute( 19 | body: CodeInterpreterExecuteParams, 20 | options?: Core.RequestOptions, 21 | ): Core.APIPromise { 22 | return this._client.post('/tci/execute', { body, ...options }); 23 | } 24 | } 25 | 26 | /** 27 | * The result of the execution. If successful, `data` contains the result and 28 | * `errors` will be null. If unsuccessful, `data` will be null and `errors` will 29 | * contain the errors. 30 | */ 31 | export type ExecuteResponse = ExecuteResponse.SuccessfulExecution | ExecuteResponse.FailedExecution; 32 | 33 | export namespace ExecuteResponse { 34 | export interface SuccessfulExecution { 35 | data: SuccessfulExecution.Data; 36 | 37 | errors: null; 38 | } 39 | 40 | export namespace SuccessfulExecution { 41 | export interface Data { 42 | outputs: Array; 43 | 44 | /** 45 | * Identifier of the current session. Used to make follow-up calls. 46 | */ 47 | session_id: string; 48 | } 49 | 50 | export namespace Data { 51 | /** 52 | * Outputs that were printed to stdout or stderr 53 | */ 54 | export interface StreamOutput { 55 | data: string; 56 | 57 | type: 'stdout' | 'stderr'; 58 | } 59 | 60 | /** 61 | * Errors and exceptions that occurred. If this output type is present, your code 62 | * did not execute successfully. 63 | */ 64 | export interface Error { 65 | data: string; 66 | 67 | type: 'error'; 68 | } 69 | 70 | export interface DisplayorExecuteOutput { 71 | data: DisplayorExecuteOutput.Data; 72 | 73 | type: 'display_data' | 'execute_result'; 74 | } 75 | 76 | export namespace DisplayorExecuteOutput { 77 | export interface Data { 78 | 'application/geo+json'?: Record; 79 | 80 | 'application/javascript'?: string; 81 | 82 | 'application/json'?: Record; 83 | 84 | 'application/pdf'?: string; 85 | 86 | 'application/vnd.vega.v5+json'?: Record; 87 | 88 | 'application/vnd.vegalite.v4+json'?: Record; 89 | 90 | 'image/gif'?: string; 91 | 92 | 'image/jpeg'?: string; 93 | 94 | 'image/png'?: string; 95 | 96 | 'image/svg+xml'?: string; 97 | 98 | 'text/html'?: string; 99 | 100 | 'text/latex'?: string; 101 | 102 | 'text/markdown'?: string; 103 | 104 | 'text/plain'?: string; 105 | } 106 | } 107 | } 108 | } 109 | 110 | export interface FailedExecution { 111 | data: null; 112 | 113 | errors: Array>; 114 | } 115 | } 116 | 117 | export interface CodeInterpreterExecuteParams { 118 | /** 119 | * Code snippet to execute. 120 | */ 121 | code: string; 122 | 123 | /** 124 | * Programming language for the code to execute. Currently only supports Python, 125 | * but more will be added. 126 | */ 127 | language: 'python'; 128 | 129 | /** 130 | * Files to upload to the session. If present, files will be uploaded before 131 | * executing the given code. 132 | */ 133 | files?: Array; 134 | 135 | /** 136 | * Identifier of the current session. Used to make follow-up calls. Requests will 137 | * return an error if the session does not belong to the caller or has expired. 138 | */ 139 | session_id?: string; 140 | } 141 | 142 | export namespace CodeInterpreterExecuteParams { 143 | export interface File { 144 | content: string; 145 | 146 | /** 147 | * Encoding of the file content. Use `string` for text files such as code, and 148 | * `base64` for binary files, such as images. 149 | */ 150 | encoding: 'string' | 'base64'; 151 | 152 | name: string; 153 | } 154 | } 155 | 156 | CodeInterpreter.Sessions = Sessions; 157 | 158 | export declare namespace CodeInterpreter { 159 | export { 160 | type ExecuteResponse as ExecuteResponse, 161 | type CodeInterpreterExecuteParams as CodeInterpreterExecuteParams, 162 | }; 163 | 164 | export { Sessions as Sessions, type SessionListResponse as SessionListResponse }; 165 | } 166 | -------------------------------------------------------------------------------- /src/resources/code-interpreter/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { CodeInterpreter, type ExecuteResponse, type CodeInterpreterExecuteParams } from './code-interpreter'; 4 | export { Sessions, type SessionListResponse } from './sessions'; 5 | -------------------------------------------------------------------------------- /src/resources/code-interpreter/sessions.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../../resource'; 4 | import * as Core from '../../core'; 5 | 6 | export class Sessions extends APIResource { 7 | /** 8 | * Lists all your currently active sessions. 9 | */ 10 | list(options?: Core.RequestOptions): Core.APIPromise { 11 | return this._client.get('/tci/sessions', options); 12 | } 13 | } 14 | 15 | export interface SessionListResponse { 16 | data?: SessionListResponse.Data; 17 | 18 | errors?: Array>; 19 | } 20 | 21 | export namespace SessionListResponse { 22 | export interface Data { 23 | sessions: Array; 24 | } 25 | 26 | export namespace Data { 27 | export interface Session { 28 | /** 29 | * Session Identifier. Used to make follow-up calls. 30 | */ 31 | id: string; 32 | 33 | execute_count: number; 34 | 35 | expires_at: string; 36 | 37 | last_execute_at: string; 38 | 39 | started_at: string; 40 | } 41 | } 42 | } 43 | 44 | export declare namespace Sessions { 45 | export { type SessionListResponse as SessionListResponse }; 46 | } 47 | -------------------------------------------------------------------------------- /src/resources/completions.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import { APIPromise } from '../core'; 5 | import * as Core from '../core'; 6 | import * as CompletionsAPI from './completions'; 7 | import * as ChatCompletionsAPI from './chat/completions'; 8 | import { Stream } from '../streaming'; 9 | 10 | export class Completions extends APIResource { 11 | /** 12 | * Query a language, code, or image model. 13 | */ 14 | create(body: CompletionCreateParamsNonStreaming, options?: Core.RequestOptions): APIPromise; 15 | create( 16 | body: CompletionCreateParamsStreaming, 17 | options?: Core.RequestOptions, 18 | ): APIPromise>; 19 | create( 20 | body: CompletionCreateParamsBase, 21 | options?: Core.RequestOptions, 22 | ): APIPromise | Completion>; 23 | create( 24 | body: CompletionCreateParams, 25 | options?: Core.RequestOptions, 26 | ): APIPromise | APIPromise> { 27 | return this._client.post('/completions', { body, ...options, stream: body.stream ?? false }) as 28 | | APIPromise 29 | | APIPromise>; 30 | } 31 | } 32 | 33 | export interface Completion { 34 | id: string; 35 | 36 | choices: Array; 37 | 38 | created: number; 39 | 40 | model: string; 41 | 42 | object: 'text_completion'; 43 | 44 | usage: ChatCompletionsAPI.ChatCompletionUsage | null; 45 | 46 | prompt?: Array; 47 | } 48 | 49 | export namespace Completion { 50 | export interface Choice { 51 | finish_reason?: 'stop' | 'eos' | 'length' | 'tool_calls' | 'function_call'; 52 | 53 | logprobs?: CompletionsAPI.LogProbs; 54 | 55 | seed?: number; 56 | 57 | text?: string; 58 | } 59 | 60 | export interface Prompt { 61 | logprobs?: CompletionsAPI.LogProbs; 62 | 63 | text?: string; 64 | } 65 | } 66 | 67 | export interface LogProbs { 68 | /** 69 | * List of token IDs corresponding to the logprobs 70 | */ 71 | token_ids?: Array; 72 | 73 | /** 74 | * List of token log probabilities 75 | */ 76 | token_logprobs?: Array; 77 | 78 | /** 79 | * List of token strings 80 | */ 81 | tokens?: Array; 82 | } 83 | 84 | export interface ToolChoice { 85 | id: string; 86 | 87 | function: ToolChoice.Function; 88 | 89 | index: number; 90 | 91 | type: 'function'; 92 | } 93 | 94 | export namespace ToolChoice { 95 | export interface Function { 96 | arguments: string; 97 | 98 | name: string; 99 | } 100 | } 101 | 102 | export interface Tools { 103 | function?: Tools.Function; 104 | 105 | type?: string; 106 | } 107 | 108 | export namespace Tools { 109 | export interface Function { 110 | description?: string; 111 | 112 | name?: string; 113 | 114 | /** 115 | * A map of parameter names to their values. 116 | */ 117 | parameters?: Record; 118 | } 119 | } 120 | 121 | export type CompletionCreateParams = CompletionCreateParamsNonStreaming | CompletionCreateParamsStreaming; 122 | 123 | export interface CompletionCreateParamsBase { 124 | /** 125 | * The name of the model to query. 126 | * 127 | * [See all of Together AI's chat models](https://docs.together.ai/docs/serverless-models#chat-models) 128 | */ 129 | model: 130 | | 'meta-llama/Llama-2-70b-hf' 131 | | 'mistralai/Mistral-7B-v0.1' 132 | | 'mistralai/Mixtral-8x7B-v0.1' 133 | | 'Meta-Llama/Llama-Guard-7b' 134 | | (string & {}); 135 | 136 | /** 137 | * A string providing context for the model to complete. 138 | */ 139 | prompt: string; 140 | 141 | /** 142 | * If true, the response will contain the prompt. Can be used with `logprobs` to 143 | * return prompt logprobs. 144 | */ 145 | echo?: boolean; 146 | 147 | /** 148 | * A number between -2.0 and 2.0 where a positive value decreases the likelihood of 149 | * repeating tokens that have already been mentioned. 150 | */ 151 | frequency_penalty?: number; 152 | 153 | /** 154 | * Adjusts the likelihood of specific tokens appearing in the generated output. 155 | */ 156 | logit_bias?: Record; 157 | 158 | /** 159 | * Integer (0 or 1) that controls whether log probabilities of generated tokens are 160 | * returned. Log probabilities help assess model confidence in token predictions. 161 | */ 162 | logprobs?: number; 163 | 164 | /** 165 | * The maximum number of tokens to generate. 166 | */ 167 | max_tokens?: number; 168 | 169 | /** 170 | * A number between 0 and 1 that can be used as an alternative to top-p and top-k. 171 | */ 172 | min_p?: number; 173 | 174 | /** 175 | * The number of completions to generate for each prompt. 176 | */ 177 | n?: number; 178 | 179 | /** 180 | * A number between -2.0 and 2.0 where a positive value increases the likelihood of 181 | * a model talking about new topics. 182 | */ 183 | presence_penalty?: number; 184 | 185 | /** 186 | * A number that controls the diversity of generated text by reducing the 187 | * likelihood of repeated sequences. Higher values decrease repetition. 188 | */ 189 | repetition_penalty?: number; 190 | 191 | /** 192 | * The name of the moderation model used to validate tokens. Choose from the 193 | * available moderation models found 194 | * [here](https://docs.together.ai/docs/inference-models#moderation-models). 195 | */ 196 | safety_model?: 'Meta-Llama/Llama-Guard-7b' | (string & {}); 197 | 198 | /** 199 | * Seed value for reproducibility. 200 | */ 201 | seed?: number; 202 | 203 | /** 204 | * A list of string sequences that will truncate (stop) inference text output. For 205 | * example, "" will stop generation as soon as the model generates the given 206 | * token. 207 | */ 208 | stop?: Array; 209 | 210 | /** 211 | * If true, stream tokens as Server-Sent Events as the model generates them instead 212 | * of waiting for the full model response. The stream terminates with 213 | * `data: [DONE]`. If false, return a single JSON object containing the results. 214 | */ 215 | stream?: boolean; 216 | 217 | /** 218 | * A decimal number from 0-1 that determines the degree of randomness in the 219 | * response. A temperature less than 1 favors more correctness and is appropriate 220 | * for question answering or summarization. A value closer to 1 introduces more 221 | * randomness in the output. 222 | */ 223 | temperature?: number; 224 | 225 | /** 226 | * An integer that's used to limit the number of choices for the next predicted 227 | * word or token. It specifies the maximum number of tokens to consider at each 228 | * step, based on their probability of occurrence. This technique helps to speed up 229 | * the generation process and can improve the quality of the generated text by 230 | * focusing on the most likely options. 231 | */ 232 | top_k?: number; 233 | 234 | /** 235 | * A percentage (also called the nucleus parameter) that's used to dynamically 236 | * adjust the number of choices for each predicted token based on the cumulative 237 | * probabilities. It specifies a probability threshold below which all less likely 238 | * tokens are filtered out. This technique helps maintain diversity and generate 239 | * more fluent and natural-sounding text. 240 | */ 241 | top_p?: number; 242 | } 243 | 244 | export namespace CompletionCreateParams { 245 | export type CompletionCreateParamsNonStreaming = CompletionsAPI.CompletionCreateParamsNonStreaming; 246 | export type CompletionCreateParamsStreaming = CompletionsAPI.CompletionCreateParamsStreaming; 247 | } 248 | 249 | export interface CompletionCreateParamsNonStreaming extends CompletionCreateParamsBase { 250 | /** 251 | * If true, stream tokens as Server-Sent Events as the model generates them instead 252 | * of waiting for the full model response. The stream terminates with 253 | * `data: [DONE]`. If false, return a single JSON object containing the results. 254 | */ 255 | stream?: false; 256 | } 257 | 258 | export interface CompletionCreateParamsStreaming extends CompletionCreateParamsBase { 259 | /** 260 | * If true, stream tokens as Server-Sent Events as the model generates them instead 261 | * of waiting for the full model response. The stream terminates with 262 | * `data: [DONE]`. If false, return a single JSON object containing the results. 263 | */ 264 | stream: true; 265 | } 266 | 267 | export declare namespace Completions { 268 | export { 269 | type Completion as Completion, 270 | type LogProbs as LogProbs, 271 | type ToolChoice as ToolChoice, 272 | type Tools as Tools, 273 | type CompletionCreateParams as CompletionCreateParams, 274 | type CompletionCreateParamsNonStreaming as CompletionCreateParamsNonStreaming, 275 | type CompletionCreateParamsStreaming as CompletionCreateParamsStreaming, 276 | }; 277 | } 278 | -------------------------------------------------------------------------------- /src/resources/embeddings.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import * as Core from '../core'; 5 | 6 | export class Embeddings extends APIResource { 7 | /** 8 | * Query an embedding model for a given string of text. 9 | */ 10 | create(body: EmbeddingCreateParams, options?: Core.RequestOptions): Core.APIPromise { 11 | return this._client.post('/embeddings', { body, ...options }); 12 | } 13 | } 14 | 15 | export interface Embedding { 16 | data: Array; 17 | 18 | model: string; 19 | 20 | object: 'list'; 21 | } 22 | 23 | export namespace Embedding { 24 | export interface Data { 25 | embedding: Array; 26 | 27 | index: number; 28 | 29 | object: 'embedding'; 30 | } 31 | } 32 | 33 | export interface EmbeddingCreateParams { 34 | /** 35 | * A string providing the text for the model to embed. 36 | */ 37 | input: string | Array; 38 | 39 | /** 40 | * The name of the embedding model to use. 41 | * 42 | * [See all of Together AI's embedding models](https://docs.together.ai/docs/serverless-models#embedding-models) 43 | */ 44 | model: 45 | | 'WhereIsAI/UAE-Large-V1' 46 | | 'BAAI/bge-large-en-v1.5' 47 | | 'BAAI/bge-base-en-v1.5' 48 | | 'togethercomputer/m2-bert-80M-8k-retrieval' 49 | | (string & {}); 50 | } 51 | 52 | export declare namespace Embeddings { 53 | export { type Embedding as Embedding, type EmbeddingCreateParams as EmbeddingCreateParams }; 54 | } 55 | -------------------------------------------------------------------------------- /src/resources/files.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import * as Core from '../core'; 5 | import { type Response } from '../_shims/index'; 6 | 7 | export class Files extends APIResource { 8 | /** 9 | * List the metadata for a single uploaded data file. 10 | */ 11 | retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise { 12 | return this._client.get(`/files/${id}`, options); 13 | } 14 | 15 | /** 16 | * List the metadata for all uploaded data files. 17 | */ 18 | list(options?: Core.RequestOptions): Core.APIPromise { 19 | return this._client.get('/files', options); 20 | } 21 | 22 | /** 23 | * Delete a previously uploaded data file. 24 | */ 25 | delete(id: string, options?: Core.RequestOptions): Core.APIPromise { 26 | return this._client.delete(`/files/${id}`, options); 27 | } 28 | 29 | /** 30 | * Get the contents of a single uploaded data file. 31 | */ 32 | content(id: string, options?: Core.RequestOptions): Core.APIPromise { 33 | return this._client.get(`/files/${id}/content`, { 34 | ...options, 35 | headers: { Accept: 'application/binary', ...options?.headers }, 36 | __binaryResponse: true, 37 | }); 38 | } 39 | 40 | /** 41 | * Upload a file. 42 | */ 43 | upload(_: string): Promise { 44 | throw 'please use together-ai/lib/upload'; 45 | } 46 | } 47 | 48 | export interface FileObject { 49 | id?: string; 50 | 51 | filename?: string; 52 | 53 | object?: string; 54 | 55 | size?: number; 56 | } 57 | 58 | export interface FileRetrieveResponse { 59 | id: string; 60 | 61 | bytes: number; 62 | 63 | created_at: number; 64 | 65 | filename: string; 66 | 67 | FileType: 'jsonl' | 'parquet'; 68 | 69 | LineCount: number; 70 | 71 | object: string; 72 | 73 | Processed: boolean; 74 | 75 | purpose: 'fine-tune'; 76 | } 77 | 78 | export interface FileListResponse { 79 | data: Array; 80 | } 81 | 82 | export namespace FileListResponse { 83 | export interface Data { 84 | id: string; 85 | 86 | bytes: number; 87 | 88 | created_at: number; 89 | 90 | filename: string; 91 | 92 | FileType: 'jsonl' | 'parquet'; 93 | 94 | LineCount: number; 95 | 96 | object: string; 97 | 98 | Processed: boolean; 99 | 100 | purpose: 'fine-tune'; 101 | } 102 | } 103 | 104 | export interface FileDeleteResponse { 105 | id?: string; 106 | 107 | deleted?: boolean; 108 | } 109 | 110 | export declare namespace Files { 111 | export { 112 | type FileObject as FileObject, 113 | type FileRetrieveResponse as FileRetrieveResponse, 114 | type FileListResponse as FileListResponse, 115 | type FileDeleteResponse as FileDeleteResponse, 116 | }; 117 | } 118 | -------------------------------------------------------------------------------- /src/resources/hardware.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import { isRequestOptions } from '../core'; 5 | import * as Core from '../core'; 6 | 7 | export class Hardware extends APIResource { 8 | /** 9 | * Returns a list of available hardware configurations for deploying models. When a 10 | * model parameter is provided, it returns only hardware configurations compatible 11 | * with that model, including their current availability status. 12 | */ 13 | list(query?: HardwareListParams, options?: Core.RequestOptions): Core.APIPromise; 14 | list(options?: Core.RequestOptions): Core.APIPromise; 15 | list( 16 | query: HardwareListParams | Core.RequestOptions = {}, 17 | options?: Core.RequestOptions, 18 | ): Core.APIPromise { 19 | if (isRequestOptions(query)) { 20 | return this.list({}, query); 21 | } 22 | return this._client.get('/hardware', { query, ...options }); 23 | } 24 | } 25 | 26 | export interface HardwareListResponse { 27 | data: Array; 28 | 29 | object: 'list'; 30 | } 31 | 32 | export namespace HardwareListResponse { 33 | /** 34 | * Hardware configuration details with optional availability status 35 | */ 36 | export interface Data { 37 | /** 38 | * Unique identifier for the hardware configuration 39 | */ 40 | id: string; 41 | 42 | object: 'hardware'; 43 | 44 | /** 45 | * Pricing details for using an endpoint 46 | */ 47 | pricing: Data.Pricing; 48 | 49 | /** 50 | * Detailed specifications of a hardware configuration 51 | */ 52 | specs: Data.Specs; 53 | 54 | /** 55 | * Timestamp of when the hardware status was last updated 56 | */ 57 | updated_at: string; 58 | 59 | /** 60 | * Indicates the current availability status of a hardware configuration 61 | */ 62 | availability?: Data.Availability; 63 | } 64 | 65 | export namespace Data { 66 | /** 67 | * Pricing details for using an endpoint 68 | */ 69 | export interface Pricing { 70 | /** 71 | * Cost per minute of endpoint uptime in cents 72 | */ 73 | cents_per_minute: number; 74 | } 75 | 76 | /** 77 | * Detailed specifications of a hardware configuration 78 | */ 79 | export interface Specs { 80 | /** 81 | * Number of GPUs in this configuration 82 | */ 83 | gpu_count: number; 84 | 85 | /** 86 | * The GPU interconnect technology 87 | */ 88 | gpu_link: string; 89 | 90 | /** 91 | * Amount of GPU memory in GB 92 | */ 93 | gpu_memory: number; 94 | 95 | /** 96 | * The type/model of GPU 97 | */ 98 | gpu_type: string; 99 | } 100 | 101 | /** 102 | * Indicates the current availability status of a hardware configuration 103 | */ 104 | export interface Availability { 105 | /** 106 | * The availability status of the hardware configuration 107 | */ 108 | status: 'available' | 'unavailable' | 'insufficient'; 109 | } 110 | } 111 | } 112 | 113 | export interface HardwareListParams { 114 | /** 115 | * Filter hardware configurations by model compatibility. When provided, the 116 | * response includes availability status for each compatible configuration. 117 | */ 118 | model?: string; 119 | } 120 | 121 | export declare namespace Hardware { 122 | export { type HardwareListResponse as HardwareListResponse, type HardwareListParams as HardwareListParams }; 123 | } 124 | -------------------------------------------------------------------------------- /src/resources/images.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import * as Core from '../core'; 5 | 6 | export class Images extends APIResource { 7 | /** 8 | * Use an image model to generate an image for a given prompt. 9 | */ 10 | create(body: ImageCreateParams, options?: Core.RequestOptions): Core.APIPromise { 11 | return this._client.post('/images/generations', { body, ...options }); 12 | } 13 | } 14 | 15 | export interface ImageFile { 16 | id: string; 17 | 18 | data: Array; 19 | 20 | model: string; 21 | 22 | object: 'list'; 23 | } 24 | 25 | export namespace ImageFile { 26 | export interface Data { 27 | index: number; 28 | 29 | b64_json?: string; 30 | 31 | url?: string; 32 | } 33 | } 34 | 35 | export interface ImageCreateParams { 36 | /** 37 | * The model to use for image generation. 38 | * 39 | * [See all of Together AI's image models](https://docs.together.ai/docs/serverless-models#image-models) 40 | */ 41 | model: 42 | | 'black-forest-labs/FLUX.1-schnell-Free' 43 | | 'black-forest-labs/FLUX.1-schnell' 44 | | 'black-forest-labs/FLUX.1.1-pro' 45 | | (string & {}); 46 | 47 | /** 48 | * A description of the desired images. Maximum length varies by model. 49 | */ 50 | prompt: string; 51 | 52 | /** 53 | * Adjusts the alignment of the generated image with the input prompt. Higher 54 | * values (e.g., 8-10) make the output more faithful to the prompt, while lower 55 | * values (e.g., 1-5) encourage more creative freedom. 56 | */ 57 | guidance?: number; 58 | 59 | /** 60 | * Height of the image to generate in number of pixels. 61 | */ 62 | height?: number; 63 | 64 | /** 65 | * An array of objects that define LoRAs (Low-Rank Adaptations) to influence the 66 | * generated image. 67 | */ 68 | image_loras?: Array; 69 | 70 | /** 71 | * URL of an image to use for image models that support it. 72 | */ 73 | image_url?: string; 74 | 75 | /** 76 | * Number of image results to generate. 77 | */ 78 | n?: number; 79 | 80 | /** 81 | * The prompt or prompts not to guide the image generation. 82 | */ 83 | negative_prompt?: string; 84 | 85 | /** 86 | * The format of the image response. Can be either be `jpeg` or `png`. Defaults to 87 | * `jpeg`. 88 | */ 89 | output_format?: 'jpeg' | 'png'; 90 | 91 | /** 92 | * Format of the image response. Can be either a base64 string or a URL. 93 | */ 94 | response_format?: 'base64' | 'url'; 95 | 96 | /** 97 | * Seed used for generation. Can be used to reproduce image generations. 98 | */ 99 | seed?: number; 100 | 101 | /** 102 | * Number of generation steps. 103 | */ 104 | steps?: number; 105 | 106 | /** 107 | * Width of the image to generate in number of pixels. 108 | */ 109 | width?: number; 110 | } 111 | 112 | export namespace ImageCreateParams { 113 | export interface ImageLora { 114 | /** 115 | * The URL of the LoRA to apply (e.g. 116 | * https://huggingface.co/strangerzonehf/Flux-Midjourney-Mix2-LoRA). 117 | */ 118 | path: string; 119 | 120 | /** 121 | * The strength of the LoRA's influence. Most LoRA's recommend a value of 1. 122 | */ 123 | scale: number; 124 | } 125 | } 126 | 127 | export declare namespace Images { 128 | export { type ImageFile as ImageFile, type ImageCreateParams as ImageCreateParams }; 129 | } 130 | -------------------------------------------------------------------------------- /src/resources/index.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | export { Audio, type AudioFile, type AudioCreateParams } from './audio'; 4 | export { Chat } from './chat/chat'; 5 | export { 6 | CodeInterpreter, 7 | type ExecuteResponse, 8 | type CodeInterpreterExecuteParams, 9 | } from './code-interpreter/code-interpreter'; 10 | export { 11 | Completions, 12 | type Completion, 13 | type LogProbs, 14 | type ToolChoice, 15 | type Tools, 16 | type CompletionCreateParams, 17 | type CompletionCreateParamsNonStreaming, 18 | type CompletionCreateParamsStreaming, 19 | } from './completions'; 20 | export { Embeddings, type Embedding, type EmbeddingCreateParams } from './embeddings'; 21 | export { 22 | Endpoints, 23 | type EndpointCreateResponse, 24 | type EndpointRetrieveResponse, 25 | type EndpointUpdateResponse, 26 | type EndpointListResponse, 27 | type EndpointCreateParams, 28 | type EndpointUpdateParams, 29 | type EndpointListParams, 30 | } from './endpoints'; 31 | export { 32 | Files, 33 | type FileObject, 34 | type FileRetrieveResponse, 35 | type FileListResponse, 36 | type FileDeleteResponse, 37 | } from './files'; 38 | export { 39 | FineTuneResource, 40 | type FineTune, 41 | type FineTuneEvent, 42 | type FineTuneListResponse, 43 | type FineTuneDownloadResponse, 44 | type FineTuneCreateParams, 45 | type FineTuneDownloadParams, 46 | } from './fine-tune'; 47 | export { Hardware, type HardwareListResponse, type HardwareListParams } from './hardware'; 48 | export { Images, type ImageFile, type ImageCreateParams } from './images'; 49 | export { Jobs, type JobRetrieveResponse, type JobListResponse } from './jobs'; 50 | export { Models, type ModelListResponse, type ModelUploadResponse, type ModelUploadParams } from './models'; 51 | export { type RerankResponse, type RerankParams } from './top-level'; 52 | -------------------------------------------------------------------------------- /src/resources/jobs.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import * as Core from '../core'; 5 | 6 | export class Jobs extends APIResource { 7 | /** 8 | * Get the status of a specific job 9 | */ 10 | retrieve(jobId: string, options?: Core.RequestOptions): Core.APIPromise { 11 | return this._client.get(`/jobs/${jobId}`, options); 12 | } 13 | 14 | /** 15 | * List all jobs and their statuses 16 | */ 17 | list(options?: Core.RequestOptions): Core.APIPromise { 18 | return this._client.get('/jobs', options); 19 | } 20 | } 21 | 22 | export interface JobRetrieveResponse { 23 | args: JobRetrieveResponse.Args; 24 | 25 | created_at: string; 26 | 27 | job_id: string; 28 | 29 | status: 'Queued' | 'Running' | 'Complete' | 'Failed'; 30 | 31 | status_updates: Array; 32 | 33 | type: string; 34 | 35 | updated_at: string; 36 | } 37 | 38 | export namespace JobRetrieveResponse { 39 | export interface Args { 40 | description?: string; 41 | 42 | modelName?: string; 43 | 44 | modelSource?: string; 45 | } 46 | 47 | export interface StatusUpdate { 48 | message: string; 49 | 50 | status: string; 51 | 52 | timestamp: string; 53 | } 54 | } 55 | 56 | export interface JobListResponse { 57 | data: Array; 58 | } 59 | 60 | export namespace JobListResponse { 61 | export interface Data { 62 | args: Data.Args; 63 | 64 | created_at: string; 65 | 66 | job_id: string; 67 | 68 | status: 'Queued' | 'Running' | 'Complete' | 'Failed'; 69 | 70 | status_updates: Array; 71 | 72 | type: string; 73 | 74 | updated_at: string; 75 | } 76 | 77 | export namespace Data { 78 | export interface Args { 79 | description?: string; 80 | 81 | modelName?: string; 82 | 83 | modelSource?: string; 84 | } 85 | 86 | export interface StatusUpdate { 87 | message: string; 88 | 89 | status: string; 90 | 91 | timestamp: string; 92 | } 93 | } 94 | } 95 | 96 | export declare namespace Jobs { 97 | export { type JobRetrieveResponse as JobRetrieveResponse, type JobListResponse as JobListResponse }; 98 | } 99 | -------------------------------------------------------------------------------- /src/resources/models.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { APIResource } from '../resource'; 4 | import * as Core from '../core'; 5 | 6 | export class Models extends APIResource { 7 | /** 8 | * Lists all of Together's open-source models 9 | */ 10 | list(options?: Core.RequestOptions): Core.APIPromise { 11 | return this._client.get('/models', options); 12 | } 13 | 14 | /** 15 | * Upload a custom model from Hugging Face or S3 16 | */ 17 | upload(body: ModelUploadParams, options?: Core.RequestOptions): Core.APIPromise { 18 | return this._client.post('/models', { body, ...options }); 19 | } 20 | } 21 | 22 | export type ModelListResponse = Array; 23 | 24 | export namespace ModelListResponse { 25 | export interface ModelListResponseItem { 26 | id: string; 27 | 28 | created: number; 29 | 30 | object: string; 31 | 32 | type: 'chat' | 'language' | 'code' | 'image' | 'embedding' | 'moderation' | 'rerank'; 33 | 34 | context_length?: number; 35 | 36 | display_name?: string; 37 | 38 | license?: string; 39 | 40 | link?: string; 41 | 42 | organization?: string; 43 | 44 | pricing?: ModelListResponseItem.Pricing; 45 | } 46 | 47 | export namespace ModelListResponseItem { 48 | export interface Pricing { 49 | base: number; 50 | 51 | finetune: number; 52 | 53 | hourly: number; 54 | 55 | input: number; 56 | 57 | output: number; 58 | } 59 | } 60 | } 61 | 62 | export interface ModelUploadResponse { 63 | data: ModelUploadResponse.Data; 64 | 65 | message: string; 66 | } 67 | 68 | export namespace ModelUploadResponse { 69 | export interface Data { 70 | job_id: string; 71 | 72 | model_id: string; 73 | 74 | model_name: string; 75 | 76 | model_source: string; 77 | } 78 | } 79 | 80 | export interface ModelUploadParams { 81 | /** 82 | * The name to give to your uploaded model 83 | */ 84 | model_name: string; 85 | 86 | /** 87 | * The source location of the model (Hugging Face repo or S3 path) 88 | */ 89 | model_source: string; 90 | 91 | /** 92 | * A description of your model 93 | */ 94 | description?: string; 95 | 96 | /** 97 | * Hugging Face token (if uploading from Hugging Face) 98 | */ 99 | hf_token?: string; 100 | } 101 | 102 | export declare namespace Models { 103 | export { 104 | type ModelListResponse as ModelListResponse, 105 | type ModelUploadResponse as ModelUploadResponse, 106 | type ModelUploadParams as ModelUploadParams, 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /src/resources/top-level.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import * as CompletionsAPI from './chat/completions'; 4 | 5 | export interface RerankResponse { 6 | /** 7 | * The model to be used for the rerank request. 8 | */ 9 | model: string; 10 | 11 | /** 12 | * Object type 13 | */ 14 | object: 'rerank'; 15 | 16 | results: Array; 17 | 18 | /** 19 | * Request ID 20 | */ 21 | id?: string; 22 | 23 | usage?: CompletionsAPI.ChatCompletionUsage | null; 24 | } 25 | 26 | export namespace RerankResponse { 27 | export interface Result { 28 | document: Result.Document; 29 | 30 | index: number; 31 | 32 | relevance_score: number; 33 | } 34 | 35 | export namespace Result { 36 | export interface Document { 37 | text?: string | null; 38 | } 39 | } 40 | } 41 | 42 | export interface RerankParams { 43 | /** 44 | * List of documents, which can be either strings or objects. 45 | */ 46 | documents: Array> | Array; 47 | 48 | /** 49 | * The model to be used for the rerank request. 50 | * 51 | * [See all of Together AI's rerank models](https://docs.together.ai/docs/serverless-models#rerank-models) 52 | */ 53 | model: 'Salesforce/Llama-Rank-v1' | (string & {}); 54 | 55 | /** 56 | * The search query to be used for ranking. 57 | */ 58 | query: string; 59 | 60 | /** 61 | * List of keys in the JSON Object document to rank by. Defaults to use all 62 | * supplied keys for ranking. 63 | */ 64 | rank_fields?: Array; 65 | 66 | /** 67 | * Whether to return supplied documents with the response. 68 | */ 69 | return_documents?: boolean; 70 | 71 | /** 72 | * The number of top results to return. 73 | */ 74 | top_n?: number; 75 | } 76 | 77 | export declare namespace TopLevel { 78 | export { type RerankResponse as RerankResponse, type RerankParams as RerankParams }; 79 | } 80 | -------------------------------------------------------------------------------- /src/shims/node.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import * as types from '../_shims/node-types'; 3 | import { setShims } from '../_shims/registry'; 4 | import { getRuntime } from '../_shims/node-runtime'; 5 | setShims(getRuntime()); 6 | 7 | declare module '../_shims/manual-types' { 8 | export namespace manual { 9 | // @ts-ignore 10 | export type Agent = types.Agent; 11 | // @ts-ignore 12 | export import fetch = types.fetch; 13 | // @ts-ignore 14 | export type Request = types.Request; 15 | // @ts-ignore 16 | export type RequestInfo = types.RequestInfo; 17 | // @ts-ignore 18 | export type RequestInit = types.RequestInit; 19 | // @ts-ignore 20 | export type Response = types.Response; 21 | // @ts-ignore 22 | export type ResponseInit = types.ResponseInit; 23 | // @ts-ignore 24 | export type ResponseType = types.ResponseType; 25 | // @ts-ignore 26 | export type BodyInit = types.BodyInit; 27 | // @ts-ignore 28 | export type Headers = types.Headers; 29 | // @ts-ignore 30 | export type HeadersInit = types.HeadersInit; 31 | // @ts-ignore 32 | export type BlobPropertyBag = types.BlobPropertyBag; 33 | // @ts-ignore 34 | export type FilePropertyBag = types.FilePropertyBag; 35 | // @ts-ignore 36 | export type FileFromPathOptions = types.FileFromPathOptions; 37 | // @ts-ignore 38 | export import FormData = types.FormData; 39 | // @ts-ignore 40 | export import File = types.File; 41 | // @ts-ignore 42 | export import Blob = types.Blob; 43 | // @ts-ignore 44 | export type Readable = types.Readable; 45 | // @ts-ignore 46 | export type FsReadStream = types.FsReadStream; 47 | // @ts-ignore 48 | export import ReadableStream = types.ReadableStream; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/shims/web.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import * as types from '../_shims/web-types'; 3 | import { setShims } from '../_shims/registry'; 4 | import { getRuntime } from '../_shims/web-runtime'; 5 | setShims(getRuntime({ manuallyImported: true })); 6 | 7 | declare module '../_shims/manual-types' { 8 | export namespace manual { 9 | // @ts-ignore 10 | export type Agent = types.Agent; 11 | // @ts-ignore 12 | export import fetch = types.fetch; 13 | // @ts-ignore 14 | export type Request = types.Request; 15 | // @ts-ignore 16 | export type RequestInfo = types.RequestInfo; 17 | // @ts-ignore 18 | export type RequestInit = types.RequestInit; 19 | // @ts-ignore 20 | export type Response = types.Response; 21 | // @ts-ignore 22 | export type ResponseInit = types.ResponseInit; 23 | // @ts-ignore 24 | export type ResponseType = types.ResponseType; 25 | // @ts-ignore 26 | export type BodyInit = types.BodyInit; 27 | // @ts-ignore 28 | export type Headers = types.Headers; 29 | // @ts-ignore 30 | export type HeadersInit = types.HeadersInit; 31 | // @ts-ignore 32 | export type BlobPropertyBag = types.BlobPropertyBag; 33 | // @ts-ignore 34 | export type FilePropertyBag = types.FilePropertyBag; 35 | // @ts-ignore 36 | export type FileFromPathOptions = types.FileFromPathOptions; 37 | // @ts-ignore 38 | export import FormData = types.FormData; 39 | // @ts-ignore 40 | export import File = types.File; 41 | // @ts-ignore 42 | export import Blob = types.Blob; 43 | // @ts-ignore 44 | export type Readable = types.Readable; 45 | // @ts-ignore 46 | export type FsReadStream = types.FsReadStream; 47 | // @ts-ignore 48 | export import ReadableStream = types.ReadableStream; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/version.ts: -------------------------------------------------------------------------------- 1 | export const VERSION = '0.16.0'; // x-release-please-version 2 | -------------------------------------------------------------------------------- /tests/api-resources/audio.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | 5 | const client = new Together({ 6 | apiKey: 'My API Key', 7 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 8 | }); 9 | 10 | describe('resource audio', () => { 11 | test('create: required and optional params', async () => { 12 | const response = await client.audio.create({ 13 | input: 'input', 14 | model: 'cartesia/sonic', 15 | voice: 'laidback woman', 16 | language: 'en', 17 | response_encoding: 'pcm_f32le', 18 | response_format: 'mp3', 19 | sample_rate: 0, 20 | stream: true, 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /tests/api-resources/chat/completions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource completions', () => { 12 | test('create: only required params', async () => { 13 | const responsePromise = client.chat.completions.create({ 14 | messages: [{ content: 'string', role: 'system' }], 15 | model: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo', 16 | }); 17 | const rawResponse = await responsePromise.asResponse(); 18 | expect(rawResponse).toBeInstanceOf(Response); 19 | const response = await responsePromise; 20 | expect(response).not.toBeInstanceOf(Response); 21 | const dataAndResponse = await responsePromise.withResponse(); 22 | expect(dataAndResponse.data).toBe(response); 23 | expect(dataAndResponse.response).toBe(rawResponse); 24 | }); 25 | 26 | test('create: required and optional params', async () => { 27 | const response = await client.chat.completions.create({ 28 | messages: [{ content: 'string', role: 'system' }], 29 | model: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo', 30 | context_length_exceeded_behavior: 'truncate', 31 | echo: true, 32 | frequency_penalty: 0, 33 | function_call: 'none', 34 | logit_bias: { '105': 21.4, '1024': -10.5 }, 35 | logprobs: 0, 36 | max_tokens: 0, 37 | min_p: 0, 38 | n: 1, 39 | presence_penalty: 0, 40 | repetition_penalty: 0, 41 | response_format: { schema: { foo: 'bar' }, type: 'json' }, 42 | safety_model: 'safety_model_name', 43 | seed: 42, 44 | stop: ['string'], 45 | stream: false, 46 | temperature: 0, 47 | tool_choice: 'tool_name', 48 | tools: [ 49 | { 50 | function: { 51 | description: 'A description of the function.', 52 | name: 'function_name', 53 | parameters: { foo: 'bar' }, 54 | }, 55 | type: 'tool_type', 56 | }, 57 | ], 58 | top_k: 0, 59 | top_p: 0, 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /tests/api-resources/code-interpreter/code-interpreter.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource codeInterpreter', () => { 12 | // skipped: currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url 13 | test.skip('execute: only required params', async () => { 14 | const responsePromise = client.codeInterpreter.execute({ 15 | code: "print('Hello, world!')", 16 | language: 'python', 17 | }); 18 | const rawResponse = await responsePromise.asResponse(); 19 | expect(rawResponse).toBeInstanceOf(Response); 20 | const response = await responsePromise; 21 | expect(response).not.toBeInstanceOf(Response); 22 | const dataAndResponse = await responsePromise.withResponse(); 23 | expect(dataAndResponse.data).toBe(response); 24 | expect(dataAndResponse.response).toBe(rawResponse); 25 | }); 26 | 27 | // skipped: currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url 28 | test.skip('execute: required and optional params', async () => { 29 | const response = await client.codeInterpreter.execute({ 30 | code: "print('Hello, world!')", 31 | language: 'python', 32 | files: [{ content: 'content', encoding: 'string', name: 'name' }], 33 | session_id: 'ses_abcDEF123', 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/api-resources/code-interpreter/sessions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource sessions', () => { 12 | // skipped: currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url 13 | test.skip('list', async () => { 14 | const responsePromise = client.codeInterpreter.sessions.list(); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | // skipped: currently no good way to test endpoints defining callbacks, Prism mock server will fail trying to reach the provided callback url 25 | test.skip('list: request options instead of params are passed correctly', async () => { 26 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 27 | await expect(client.codeInterpreter.sessions.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 28 | Together.NotFoundError, 29 | ); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /tests/api-resources/completions.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource completions', () => { 12 | test('create: only required params', async () => { 13 | const responsePromise = client.completions.create({ 14 | model: 'mistralai/Mixtral-8x7B-Instruct-v0.1', 15 | prompt: '[INST] What is the capital of France? [/INST]', 16 | }); 17 | const rawResponse = await responsePromise.asResponse(); 18 | expect(rawResponse).toBeInstanceOf(Response); 19 | const response = await responsePromise; 20 | expect(response).not.toBeInstanceOf(Response); 21 | const dataAndResponse = await responsePromise.withResponse(); 22 | expect(dataAndResponse.data).toBe(response); 23 | expect(dataAndResponse.response).toBe(rawResponse); 24 | }); 25 | 26 | test('create: required and optional params', async () => { 27 | const response = await client.completions.create({ 28 | model: 'mistralai/Mixtral-8x7B-Instruct-v0.1', 29 | prompt: '[INST] What is the capital of France? [/INST]', 30 | echo: true, 31 | frequency_penalty: 0, 32 | logit_bias: { '105': 21.4, '1024': -10.5 }, 33 | logprobs: 0, 34 | max_tokens: 0, 35 | min_p: 0, 36 | n: 1, 37 | presence_penalty: 0, 38 | repetition_penalty: 0, 39 | safety_model: 'safety_model_name', 40 | seed: 42, 41 | stop: ['string'], 42 | stream: false, 43 | temperature: 0, 44 | top_k: 0, 45 | top_p: 0, 46 | }); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /tests/api-resources/embeddings.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource embeddings', () => { 12 | test('create: only required params', async () => { 13 | const responsePromise = client.embeddings.create({ 14 | input: 'Our solar system orbits the Milky Way galaxy at about 515,000 mph', 15 | model: 'togethercomputer/m2-bert-80M-8k-retrieval', 16 | }); 17 | const rawResponse = await responsePromise.asResponse(); 18 | expect(rawResponse).toBeInstanceOf(Response); 19 | const response = await responsePromise; 20 | expect(response).not.toBeInstanceOf(Response); 21 | const dataAndResponse = await responsePromise.withResponse(); 22 | expect(dataAndResponse.data).toBe(response); 23 | expect(dataAndResponse.response).toBe(rawResponse); 24 | }); 25 | 26 | test('create: required and optional params', async () => { 27 | const response = await client.embeddings.create({ 28 | input: 'Our solar system orbits the Milky Way galaxy at about 515,000 mph', 29 | model: 'togethercomputer/m2-bert-80M-8k-retrieval', 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /tests/api-resources/endpoints.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource endpoints', () => { 12 | test('create: only required params', async () => { 13 | const responsePromise = client.endpoints.create({ 14 | autoscaling: { max_replicas: 5, min_replicas: 2 }, 15 | hardware: '1x_nvidia_a100_80gb_sxm', 16 | model: 'meta-llama/Llama-3-8b-chat-hf', 17 | }); 18 | const rawResponse = await responsePromise.asResponse(); 19 | expect(rawResponse).toBeInstanceOf(Response); 20 | const response = await responsePromise; 21 | expect(response).not.toBeInstanceOf(Response); 22 | const dataAndResponse = await responsePromise.withResponse(); 23 | expect(dataAndResponse.data).toBe(response); 24 | expect(dataAndResponse.response).toBe(rawResponse); 25 | }); 26 | 27 | test('create: required and optional params', async () => { 28 | const response = await client.endpoints.create({ 29 | autoscaling: { max_replicas: 5, min_replicas: 2 }, 30 | hardware: '1x_nvidia_a100_80gb_sxm', 31 | model: 'meta-llama/Llama-3-8b-chat-hf', 32 | disable_prompt_cache: true, 33 | disable_speculative_decoding: true, 34 | display_name: 'My Llama3 70b endpoint', 35 | inactive_timeout: 60, 36 | state: 'STARTED', 37 | }); 38 | }); 39 | 40 | test('retrieve', async () => { 41 | const responsePromise = client.endpoints.retrieve('endpoint-d23901de-ef8f-44bf-b3e7-de9c1ca8f2d7'); 42 | const rawResponse = await responsePromise.asResponse(); 43 | expect(rawResponse).toBeInstanceOf(Response); 44 | const response = await responsePromise; 45 | expect(response).not.toBeInstanceOf(Response); 46 | const dataAndResponse = await responsePromise.withResponse(); 47 | expect(dataAndResponse.data).toBe(response); 48 | expect(dataAndResponse.response).toBe(rawResponse); 49 | }); 50 | 51 | test('retrieve: request options instead of params are passed correctly', async () => { 52 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 53 | await expect( 54 | client.endpoints.retrieve('endpoint-d23901de-ef8f-44bf-b3e7-de9c1ca8f2d7', { 55 | path: '/_stainless_unknown_path', 56 | }), 57 | ).rejects.toThrow(Together.NotFoundError); 58 | }); 59 | 60 | test('update', async () => { 61 | const responsePromise = client.endpoints.update('endpoint-d23901de-ef8f-44bf-b3e7-de9c1ca8f2d7', {}); 62 | const rawResponse = await responsePromise.asResponse(); 63 | expect(rawResponse).toBeInstanceOf(Response); 64 | const response = await responsePromise; 65 | expect(response).not.toBeInstanceOf(Response); 66 | const dataAndResponse = await responsePromise.withResponse(); 67 | expect(dataAndResponse.data).toBe(response); 68 | expect(dataAndResponse.response).toBe(rawResponse); 69 | }); 70 | 71 | test('list', async () => { 72 | const responsePromise = client.endpoints.list(); 73 | const rawResponse = await responsePromise.asResponse(); 74 | expect(rawResponse).toBeInstanceOf(Response); 75 | const response = await responsePromise; 76 | expect(response).not.toBeInstanceOf(Response); 77 | const dataAndResponse = await responsePromise.withResponse(); 78 | expect(dataAndResponse.data).toBe(response); 79 | expect(dataAndResponse.response).toBe(rawResponse); 80 | }); 81 | 82 | test('list: request options instead of params are passed correctly', async () => { 83 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 84 | await expect(client.endpoints.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 85 | Together.NotFoundError, 86 | ); 87 | }); 88 | 89 | test('list: request options and params are passed correctly', async () => { 90 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 91 | await expect( 92 | client.endpoints.list({ type: 'dedicated' }, { path: '/_stainless_unknown_path' }), 93 | ).rejects.toThrow(Together.NotFoundError); 94 | }); 95 | 96 | test('delete', async () => { 97 | const responsePromise = client.endpoints.delete('endpoint-d23901de-ef8f-44bf-b3e7-de9c1ca8f2d7'); 98 | const rawResponse = await responsePromise.asResponse(); 99 | expect(rawResponse).toBeInstanceOf(Response); 100 | const response = await responsePromise; 101 | expect(response).not.toBeInstanceOf(Response); 102 | const dataAndResponse = await responsePromise.withResponse(); 103 | expect(dataAndResponse.data).toBe(response); 104 | expect(dataAndResponse.response).toBe(rawResponse); 105 | }); 106 | 107 | test('delete: request options instead of params are passed correctly', async () => { 108 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 109 | await expect( 110 | client.endpoints.delete('endpoint-d23901de-ef8f-44bf-b3e7-de9c1ca8f2d7', { 111 | path: '/_stainless_unknown_path', 112 | }), 113 | ).rejects.toThrow(Together.NotFoundError); 114 | }); 115 | }); 116 | -------------------------------------------------------------------------------- /tests/api-resources/files.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource files', () => { 12 | test('retrieve', async () => { 13 | const responsePromise = client.files.retrieve('id'); 14 | const rawResponse = await responsePromise.asResponse(); 15 | expect(rawResponse).toBeInstanceOf(Response); 16 | const response = await responsePromise; 17 | expect(response).not.toBeInstanceOf(Response); 18 | const dataAndResponse = await responsePromise.withResponse(); 19 | expect(dataAndResponse.data).toBe(response); 20 | expect(dataAndResponse.response).toBe(rawResponse); 21 | }); 22 | 23 | test('retrieve: request options instead of params are passed correctly', async () => { 24 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 25 | await expect(client.files.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( 26 | Together.NotFoundError, 27 | ); 28 | }); 29 | 30 | test('list', async () => { 31 | const responsePromise = client.files.list(); 32 | const rawResponse = await responsePromise.asResponse(); 33 | expect(rawResponse).toBeInstanceOf(Response); 34 | const response = await responsePromise; 35 | expect(response).not.toBeInstanceOf(Response); 36 | const dataAndResponse = await responsePromise.withResponse(); 37 | expect(dataAndResponse.data).toBe(response); 38 | expect(dataAndResponse.response).toBe(rawResponse); 39 | }); 40 | 41 | test('list: request options instead of params are passed correctly', async () => { 42 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 43 | await expect(client.files.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 44 | Together.NotFoundError, 45 | ); 46 | }); 47 | 48 | test('delete', async () => { 49 | const responsePromise = client.files.delete('id'); 50 | const rawResponse = await responsePromise.asResponse(); 51 | expect(rawResponse).toBeInstanceOf(Response); 52 | const response = await responsePromise; 53 | expect(response).not.toBeInstanceOf(Response); 54 | const dataAndResponse = await responsePromise.withResponse(); 55 | expect(dataAndResponse.data).toBe(response); 56 | expect(dataAndResponse.response).toBe(rawResponse); 57 | }); 58 | 59 | test('delete: request options instead of params are passed correctly', async () => { 60 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 61 | await expect(client.files.delete('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( 62 | Together.NotFoundError, 63 | ); 64 | }); 65 | 66 | test('content: request options instead of params are passed correctly', async () => { 67 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 68 | await expect(client.files.content('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( 69 | Together.NotFoundError, 70 | ); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /tests/api-resources/fine-tune.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource fineTune', () => { 12 | // invalid oneOf in required props 13 | test.skip('create: only required params', async () => { 14 | const responsePromise = client.fineTune.create({ model: 'model', training_file: 'training_file' }); 15 | const rawResponse = await responsePromise.asResponse(); 16 | expect(rawResponse).toBeInstanceOf(Response); 17 | const response = await responsePromise; 18 | expect(response).not.toBeInstanceOf(Response); 19 | const dataAndResponse = await responsePromise.withResponse(); 20 | expect(dataAndResponse.data).toBe(response); 21 | expect(dataAndResponse.response).toBe(rawResponse); 22 | }); 23 | 24 | // invalid oneOf in required props 25 | test.skip('create: required and optional params', async () => { 26 | const response = await client.fineTune.create({ 27 | model: 'model', 28 | training_file: 'training_file', 29 | batch_size: 0, 30 | from_checkpoint: 'from_checkpoint', 31 | learning_rate: 0, 32 | lr_scheduler: { lr_scheduler_type: 'linear', lr_scheduler_args: { min_lr_ratio: 0 } }, 33 | max_grad_norm: 0, 34 | n_checkpoints: 0, 35 | n_epochs: 0, 36 | n_evals: 0, 37 | suffix: 'suffix', 38 | train_on_inputs: true, 39 | training_method: { method: 'sft' }, 40 | training_type: { type: 'Full' }, 41 | validation_file: 'validation_file', 42 | wandb_api_key: 'wandb_api_key', 43 | wandb_base_url: 'wandb_base_url', 44 | wandb_name: 'wandb_name', 45 | wandb_project_name: 'wandb_project_name', 46 | warmup_ratio: 0, 47 | weight_decay: 0, 48 | }); 49 | }); 50 | 51 | test('retrieve', async () => { 52 | const responsePromise = client.fineTune.retrieve('id'); 53 | const rawResponse = await responsePromise.asResponse(); 54 | expect(rawResponse).toBeInstanceOf(Response); 55 | const response = await responsePromise; 56 | expect(response).not.toBeInstanceOf(Response); 57 | const dataAndResponse = await responsePromise.withResponse(); 58 | expect(dataAndResponse.data).toBe(response); 59 | expect(dataAndResponse.response).toBe(rawResponse); 60 | }); 61 | 62 | test('retrieve: request options instead of params are passed correctly', async () => { 63 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 64 | await expect(client.fineTune.retrieve('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( 65 | Together.NotFoundError, 66 | ); 67 | }); 68 | 69 | test('list', async () => { 70 | const responsePromise = client.fineTune.list(); 71 | const rawResponse = await responsePromise.asResponse(); 72 | expect(rawResponse).toBeInstanceOf(Response); 73 | const response = await responsePromise; 74 | expect(response).not.toBeInstanceOf(Response); 75 | const dataAndResponse = await responsePromise.withResponse(); 76 | expect(dataAndResponse.data).toBe(response); 77 | expect(dataAndResponse.response).toBe(rawResponse); 78 | }); 79 | 80 | test('list: request options instead of params are passed correctly', async () => { 81 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 82 | await expect(client.fineTune.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 83 | Together.NotFoundError, 84 | ); 85 | }); 86 | 87 | test('cancel', async () => { 88 | const responsePromise = client.fineTune.cancel('id'); 89 | const rawResponse = await responsePromise.asResponse(); 90 | expect(rawResponse).toBeInstanceOf(Response); 91 | const response = await responsePromise; 92 | expect(response).not.toBeInstanceOf(Response); 93 | const dataAndResponse = await responsePromise.withResponse(); 94 | expect(dataAndResponse.data).toBe(response); 95 | expect(dataAndResponse.response).toBe(rawResponse); 96 | }); 97 | 98 | test('cancel: request options instead of params are passed correctly', async () => { 99 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 100 | await expect(client.fineTune.cancel('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( 101 | Together.NotFoundError, 102 | ); 103 | }); 104 | 105 | test('download: only required params', async () => { 106 | const responsePromise = client.fineTune.download({ ft_id: 'ft_id' }); 107 | const rawResponse = await responsePromise.asResponse(); 108 | expect(rawResponse).toBeInstanceOf(Response); 109 | const response = await responsePromise; 110 | expect(response).not.toBeInstanceOf(Response); 111 | const dataAndResponse = await responsePromise.withResponse(); 112 | expect(dataAndResponse.data).toBe(response); 113 | expect(dataAndResponse.response).toBe(rawResponse); 114 | }); 115 | 116 | test('download: required and optional params', async () => { 117 | const response = await client.fineTune.download({ 118 | ft_id: 'ft_id', 119 | checkpoint: 'merged', 120 | checkpoint_step: 0, 121 | output: 'output', 122 | }); 123 | }); 124 | 125 | test('listEvents', async () => { 126 | const responsePromise = client.fineTune.listEvents('id'); 127 | const rawResponse = await responsePromise.asResponse(); 128 | expect(rawResponse).toBeInstanceOf(Response); 129 | const response = await responsePromise; 130 | expect(response).not.toBeInstanceOf(Response); 131 | const dataAndResponse = await responsePromise.withResponse(); 132 | expect(dataAndResponse.data).toBe(response); 133 | expect(dataAndResponse.response).toBe(rawResponse); 134 | }); 135 | 136 | test('listEvents: request options instead of params are passed correctly', async () => { 137 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 138 | await expect(client.fineTune.listEvents('id', { path: '/_stainless_unknown_path' })).rejects.toThrow( 139 | Together.NotFoundError, 140 | ); 141 | }); 142 | }); 143 | -------------------------------------------------------------------------------- /tests/api-resources/hardware.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource hardware', () => { 12 | test('list', async () => { 13 | const responsePromise = client.hardware.list(); 14 | const rawResponse = await responsePromise.asResponse(); 15 | expect(rawResponse).toBeInstanceOf(Response); 16 | const response = await responsePromise; 17 | expect(response).not.toBeInstanceOf(Response); 18 | const dataAndResponse = await responsePromise.withResponse(); 19 | expect(dataAndResponse.data).toBe(response); 20 | expect(dataAndResponse.response).toBe(rawResponse); 21 | }); 22 | 23 | test('list: request options instead of params are passed correctly', async () => { 24 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 25 | await expect(client.hardware.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 26 | Together.NotFoundError, 27 | ); 28 | }); 29 | 30 | test('list: request options and params are passed correctly', async () => { 31 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 32 | await expect( 33 | client.hardware.list({ model: 'model' }, { path: '/_stainless_unknown_path' }), 34 | ).rejects.toThrow(Together.NotFoundError); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/api-resources/images.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource images', () => { 12 | // invalid oneOf in required props 13 | test.skip('create: only required params', async () => { 14 | const responsePromise = client.images.create({ 15 | model: 'black-forest-labs/FLUX.1-schnell', 16 | prompt: 'cat floating in space, cinematic', 17 | }); 18 | const rawResponse = await responsePromise.asResponse(); 19 | expect(rawResponse).toBeInstanceOf(Response); 20 | const response = await responsePromise; 21 | expect(response).not.toBeInstanceOf(Response); 22 | const dataAndResponse = await responsePromise.withResponse(); 23 | expect(dataAndResponse.data).toBe(response); 24 | expect(dataAndResponse.response).toBe(rawResponse); 25 | }); 26 | 27 | // invalid oneOf in required props 28 | test.skip('create: required and optional params', async () => { 29 | const response = await client.images.create({ 30 | model: 'black-forest-labs/FLUX.1-schnell', 31 | prompt: 'cat floating in space, cinematic', 32 | guidance: 0, 33 | height: 0, 34 | image_loras: [{ path: 'path', scale: 0 }], 35 | image_url: 'image_url', 36 | n: 0, 37 | negative_prompt: 'negative_prompt', 38 | output_format: 'jpeg', 39 | response_format: 'base64', 40 | seed: 0, 41 | steps: 0, 42 | width: 0, 43 | }); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /tests/api-resources/jobs.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource jobs', () => { 12 | test('retrieve', async () => { 13 | const responsePromise = client.jobs.retrieve('job-a15dad11-8d8e-4007-97c5-a211304de284'); 14 | const rawResponse = await responsePromise.asResponse(); 15 | expect(rawResponse).toBeInstanceOf(Response); 16 | const response = await responsePromise; 17 | expect(response).not.toBeInstanceOf(Response); 18 | const dataAndResponse = await responsePromise.withResponse(); 19 | expect(dataAndResponse.data).toBe(response); 20 | expect(dataAndResponse.response).toBe(rawResponse); 21 | }); 22 | 23 | test('retrieve: request options instead of params are passed correctly', async () => { 24 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 25 | await expect( 26 | client.jobs.retrieve('job-a15dad11-8d8e-4007-97c5-a211304de284', { path: '/_stainless_unknown_path' }), 27 | ).rejects.toThrow(Together.NotFoundError); 28 | }); 29 | 30 | test('list', async () => { 31 | const responsePromise = client.jobs.list(); 32 | const rawResponse = await responsePromise.asResponse(); 33 | expect(rawResponse).toBeInstanceOf(Response); 34 | const response = await responsePromise; 35 | expect(response).not.toBeInstanceOf(Response); 36 | const dataAndResponse = await responsePromise.withResponse(); 37 | expect(dataAndResponse.data).toBe(response); 38 | expect(dataAndResponse.response).toBe(rawResponse); 39 | }); 40 | 41 | test('list: request options instead of params are passed correctly', async () => { 42 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 43 | await expect(client.jobs.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 44 | Together.NotFoundError, 45 | ); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /tests/api-resources/models.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('resource models', () => { 12 | test('list', async () => { 13 | const responsePromise = client.models.list(); 14 | const rawResponse = await responsePromise.asResponse(); 15 | expect(rawResponse).toBeInstanceOf(Response); 16 | const response = await responsePromise; 17 | expect(response).not.toBeInstanceOf(Response); 18 | const dataAndResponse = await responsePromise.withResponse(); 19 | expect(dataAndResponse.data).toBe(response); 20 | expect(dataAndResponse.response).toBe(rawResponse); 21 | }); 22 | 23 | test('list: request options instead of params are passed correctly', async () => { 24 | // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error 25 | await expect(client.models.list({ path: '/_stainless_unknown_path' })).rejects.toThrow( 26 | Together.NotFoundError, 27 | ); 28 | }); 29 | 30 | test('upload: only required params', async () => { 31 | const responsePromise = client.models.upload({ 32 | model_name: 'Qwen2.5-72B-Instruct', 33 | model_source: 'unsloth/Qwen2.5-72B-Instruct', 34 | }); 35 | const rawResponse = await responsePromise.asResponse(); 36 | expect(rawResponse).toBeInstanceOf(Response); 37 | const response = await responsePromise; 38 | expect(response).not.toBeInstanceOf(Response); 39 | const dataAndResponse = await responsePromise.withResponse(); 40 | expect(dataAndResponse.data).toBe(response); 41 | expect(dataAndResponse.response).toBe(rawResponse); 42 | }); 43 | 44 | test('upload: required and optional params', async () => { 45 | const response = await client.models.upload({ 46 | model_name: 'Qwen2.5-72B-Instruct', 47 | model_source: 'unsloth/Qwen2.5-72B-Instruct', 48 | description: 'Finetuned Qwen2.5-72B-Instruct by Unsloth', 49 | hf_token: 'hf_examplehuggingfacetoken', 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /tests/api-resources/top-level.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import Together from 'together-ai'; 4 | import { Response } from 'node-fetch'; 5 | 6 | const client = new Together({ 7 | apiKey: 'My API Key', 8 | baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', 9 | }); 10 | 11 | describe('top level methods', () => { 12 | test('rerank: only required params', async () => { 13 | const responsePromise = client.rerank({ 14 | documents: [ 15 | { title: 'bar', text: 'bar' }, 16 | { title: 'bar', text: 'bar' }, 17 | { title: 'bar', text: 'bar' }, 18 | { title: 'bar', text: 'bar' }, 19 | ], 20 | model: 'Salesforce/Llama-Rank-V1', 21 | query: 'What animals can I find near Peru?', 22 | }); 23 | const rawResponse = await responsePromise.asResponse(); 24 | expect(rawResponse).toBeInstanceOf(Response); 25 | const response = await responsePromise; 26 | expect(response).not.toBeInstanceOf(Response); 27 | const dataAndResponse = await responsePromise.withResponse(); 28 | expect(dataAndResponse.data).toBe(response); 29 | expect(dataAndResponse.response).toBe(rawResponse); 30 | }); 31 | 32 | test('rerank: required and optional params', async () => { 33 | const response = await client.rerank({ 34 | documents: [ 35 | { title: 'bar', text: 'bar' }, 36 | { title: 'bar', text: 'bar' }, 37 | { title: 'bar', text: 'bar' }, 38 | { title: 'bar', text: 'bar' }, 39 | ], 40 | model: 'Salesforce/Llama-Rank-V1', 41 | query: 'What animals can I find near Peru?', 42 | rank_fields: ['title', 'text'], 43 | return_documents: true, 44 | top_n: 2, 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /tests/form.test.ts: -------------------------------------------------------------------------------- 1 | import { multipartFormRequestOptions, createForm } from 'together-ai/core'; 2 | import { Blob } from 'together-ai/_shims/index'; 3 | import { toFile } from 'together-ai'; 4 | 5 | describe('form data validation', () => { 6 | test('valid values do not error', async () => { 7 | await multipartFormRequestOptions({ 8 | body: { 9 | foo: 'foo', 10 | string: 1, 11 | bool: true, 12 | file: await toFile(Buffer.from('some-content')), 13 | blob: new Blob(['Some content'], { type: 'text/plain' }), 14 | }, 15 | }); 16 | }); 17 | 18 | test('null', async () => { 19 | await expect(() => 20 | multipartFormRequestOptions({ 21 | body: { 22 | null: null, 23 | }, 24 | }), 25 | ).rejects.toThrow(TypeError); 26 | }); 27 | 28 | test('undefined is stripped', async () => { 29 | const form = await createForm({ 30 | foo: undefined, 31 | bar: 'baz', 32 | }); 33 | expect(form.has('foo')).toBe(false); 34 | expect(form.get('bar')).toBe('baz'); 35 | }); 36 | 37 | test('nested undefined property is stripped', async () => { 38 | const form = await createForm({ 39 | bar: { 40 | baz: undefined, 41 | }, 42 | }); 43 | expect(Array.from(form.entries())).toEqual([]); 44 | 45 | const form2 = await createForm({ 46 | bar: { 47 | foo: 'string', 48 | baz: undefined, 49 | }, 50 | }); 51 | expect(Array.from(form2.entries())).toEqual([['bar[foo]', 'string']]); 52 | }); 53 | 54 | test('nested undefined array item is stripped', async () => { 55 | const form = await createForm({ 56 | bar: [undefined, undefined], 57 | }); 58 | expect(Array.from(form.entries())).toEqual([]); 59 | 60 | const form2 = await createForm({ 61 | bar: [undefined, 'foo'], 62 | }); 63 | expect(Array.from(form2.entries())).toEqual([['bar[]', 'foo']]); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /tests/internal/decoders/line.test.ts: -------------------------------------------------------------------------------- 1 | import { findDoubleNewlineIndex, LineDecoder } from 'together-ai/internal/decoders/line'; 2 | 3 | function decodeChunks(chunks: string[], { flush }: { flush: boolean } = { flush: false }): string[] { 4 | const decoder = new LineDecoder(); 5 | const lines: string[] = []; 6 | for (const chunk of chunks) { 7 | lines.push(...decoder.decode(chunk)); 8 | } 9 | 10 | if (flush) { 11 | lines.push(...decoder.flush()); 12 | } 13 | 14 | return lines; 15 | } 16 | 17 | describe('line decoder', () => { 18 | test('basic', () => { 19 | // baz is not included because the line hasn't ended yet 20 | expect(decodeChunks(['foo', ' bar\nbaz'])).toEqual(['foo bar']); 21 | }); 22 | 23 | test('basic with \\r', () => { 24 | expect(decodeChunks(['foo', ' bar\r\nbaz'])).toEqual(['foo bar']); 25 | expect(decodeChunks(['foo', ' bar\r\nbaz'], { flush: true })).toEqual(['foo bar', 'baz']); 26 | }); 27 | 28 | test('trailing new lines', () => { 29 | expect(decodeChunks(['foo', ' bar', 'baz\n', 'thing\n'])).toEqual(['foo barbaz', 'thing']); 30 | }); 31 | 32 | test('trailing new lines with \\r', () => { 33 | expect(decodeChunks(['foo', ' bar', 'baz\r\n', 'thing\r\n'])).toEqual(['foo barbaz', 'thing']); 34 | }); 35 | 36 | test('escaped new lines', () => { 37 | expect(decodeChunks(['foo', ' bar\\nbaz\n'])).toEqual(['foo bar\\nbaz']); 38 | }); 39 | 40 | test('escaped new lines with \\r', () => { 41 | expect(decodeChunks(['foo', ' bar\\r\\nbaz\n'])).toEqual(['foo bar\\r\\nbaz']); 42 | }); 43 | 44 | test('\\r & \\n split across multiple chunks', () => { 45 | expect(decodeChunks(['foo\r', '\n', 'bar'], { flush: true })).toEqual(['foo', 'bar']); 46 | }); 47 | 48 | test('single \\r', () => { 49 | expect(decodeChunks(['foo\r', 'bar'], { flush: true })).toEqual(['foo', 'bar']); 50 | }); 51 | 52 | test('double \\r', () => { 53 | expect(decodeChunks(['foo\r', 'bar\r'], { flush: true })).toEqual(['foo', 'bar']); 54 | expect(decodeChunks(['foo\r', '\r', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']); 55 | // implementation detail that we don't yield the single \r line until a new \r or \n is encountered 56 | expect(decodeChunks(['foo\r', '\r', 'bar'], { flush: false })).toEqual(['foo']); 57 | }); 58 | 59 | test('double \\r then \\r\\n', () => { 60 | expect(decodeChunks(['foo\r', '\r', '\r', '\n', 'bar', '\n'])).toEqual(['foo', '', '', 'bar']); 61 | expect(decodeChunks(['foo\n', '\n', '\n', 'bar', '\n'])).toEqual(['foo', '', '', 'bar']); 62 | }); 63 | 64 | test('double newline', () => { 65 | expect(decodeChunks(['foo\n\nbar'], { flush: true })).toEqual(['foo', '', 'bar']); 66 | expect(decodeChunks(['foo', '\n', '\nbar'], { flush: true })).toEqual(['foo', '', 'bar']); 67 | expect(decodeChunks(['foo\n', '\n', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']); 68 | expect(decodeChunks(['foo', '\n', '\n', 'bar'], { flush: true })).toEqual(['foo', '', 'bar']); 69 | }); 70 | 71 | test('multi-byte characters across chunks', () => { 72 | const decoder = new LineDecoder(); 73 | 74 | // bytes taken from the string 'известни' and arbitrarily split 75 | // so that some multi-byte characters span multiple chunks 76 | expect(decoder.decode(new Uint8Array([0xd0]))).toHaveLength(0); 77 | expect(decoder.decode(new Uint8Array([0xb8, 0xd0, 0xb7, 0xd0]))).toHaveLength(0); 78 | expect( 79 | decoder.decode(new Uint8Array([0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb8])), 80 | ).toHaveLength(0); 81 | 82 | const decoded = decoder.decode(new Uint8Array([0xa])); 83 | expect(decoded).toEqual(['известни']); 84 | }); 85 | 86 | test('flushing trailing newlines', () => { 87 | expect(decodeChunks(['foo\n', '\nbar'], { flush: true })).toEqual(['foo', '', 'bar']); 88 | }); 89 | 90 | test('flushing empty buffer', () => { 91 | expect(decodeChunks([], { flush: true })).toEqual([]); 92 | }); 93 | }); 94 | 95 | describe('findDoubleNewlineIndex', () => { 96 | test('finds \\n\\n', () => { 97 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\n\nbar'))).toBe(5); 98 | expect(findDoubleNewlineIndex(new TextEncoder().encode('\n\nbar'))).toBe(2); 99 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\n\n'))).toBe(5); 100 | expect(findDoubleNewlineIndex(new TextEncoder().encode('\n\n'))).toBe(2); 101 | }); 102 | 103 | test('finds \\r\\r', () => { 104 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\rbar'))).toBe(5); 105 | expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\rbar'))).toBe(2); 106 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\r'))).toBe(5); 107 | expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\r'))).toBe(2); 108 | }); 109 | 110 | test('finds \\r\\n\\r\\n', () => { 111 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r\nbar'))).toBe(7); 112 | expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\n\r\nbar'))).toBe(4); 113 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r\n'))).toBe(7); 114 | expect(findDoubleNewlineIndex(new TextEncoder().encode('\r\n\r\n'))).toBe(4); 115 | }); 116 | 117 | test('returns -1 when no double newline found', () => { 118 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\nbar'))).toBe(-1); 119 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\rbar'))).toBe(-1); 120 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\nbar'))).toBe(-1); 121 | expect(findDoubleNewlineIndex(new TextEncoder().encode(''))).toBe(-1); 122 | }); 123 | 124 | test('handles incomplete patterns', () => { 125 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n\r'))).toBe(-1); 126 | expect(findDoubleNewlineIndex(new TextEncoder().encode('foo\r\n'))).toBe(-1); 127 | }); 128 | }); 129 | -------------------------------------------------------------------------------- /tests/responses.test.ts: -------------------------------------------------------------------------------- 1 | import { createResponseHeaders } from 'together-ai/core'; 2 | import { Headers } from 'together-ai/_shims/index'; 3 | 4 | describe('response parsing', () => { 5 | // TODO: test unicode characters 6 | test('headers are case agnostic', async () => { 7 | const headers = createResponseHeaders(new Headers({ 'Content-Type': 'foo', Accept: 'text/plain' })); 8 | expect(headers['content-type']).toEqual('foo'); 9 | expect(headers['Content-type']).toEqual('foo'); 10 | expect(headers['Content-Type']).toEqual('foo'); 11 | expect(headers['accept']).toEqual('text/plain'); 12 | expect(headers['Accept']).toEqual('text/plain'); 13 | expect(headers['Hello-World']).toBeUndefined(); 14 | }); 15 | 16 | test('duplicate headers are concatenated', () => { 17 | const headers = createResponseHeaders( 18 | new Headers([ 19 | ['Content-Type', 'text/xml'], 20 | ['Content-Type', 'application/json'], 21 | ]), 22 | ); 23 | expect(headers['content-type']).toBe('text/xml, application/json'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/streaming.test.ts: -------------------------------------------------------------------------------- 1 | import { Response } from 'node-fetch'; 2 | import { PassThrough } from 'stream'; 3 | import assert from 'assert'; 4 | import { _iterSSEMessages } from 'together-ai/streaming'; 5 | 6 | describe('streaming decoding', () => { 7 | test('basic', async () => { 8 | async function* body(): AsyncGenerator { 9 | yield Buffer.from('event: completion\n'); 10 | yield Buffer.from('data: {"foo":true}\n'); 11 | yield Buffer.from('\n'); 12 | } 13 | 14 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 15 | Symbol.asyncIterator 16 | ](); 17 | 18 | let event = await stream.next(); 19 | assert(event.value); 20 | expect(JSON.parse(event.value.data)).toEqual({ foo: true }); 21 | 22 | event = await stream.next(); 23 | expect(event.done).toBeTruthy(); 24 | }); 25 | 26 | test('data without event', async () => { 27 | async function* body(): AsyncGenerator { 28 | yield Buffer.from('data: {"foo":true}\n'); 29 | yield Buffer.from('\n'); 30 | } 31 | 32 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 33 | Symbol.asyncIterator 34 | ](); 35 | 36 | let event = await stream.next(); 37 | assert(event.value); 38 | expect(event.value.event).toBeNull(); 39 | expect(JSON.parse(event.value.data)).toEqual({ foo: true }); 40 | 41 | event = await stream.next(); 42 | expect(event.done).toBeTruthy(); 43 | }); 44 | 45 | test('event without data', async () => { 46 | async function* body(): AsyncGenerator { 47 | yield Buffer.from('event: foo\n'); 48 | yield Buffer.from('\n'); 49 | } 50 | 51 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 52 | Symbol.asyncIterator 53 | ](); 54 | 55 | let event = await stream.next(); 56 | assert(event.value); 57 | expect(event.value.event).toEqual('foo'); 58 | expect(event.value.data).toEqual(''); 59 | 60 | event = await stream.next(); 61 | expect(event.done).toBeTruthy(); 62 | }); 63 | 64 | test('multiple events', async () => { 65 | async function* body(): AsyncGenerator { 66 | yield Buffer.from('event: foo\n'); 67 | yield Buffer.from('\n'); 68 | yield Buffer.from('event: ping\n'); 69 | yield Buffer.from('\n'); 70 | } 71 | 72 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 73 | Symbol.asyncIterator 74 | ](); 75 | 76 | let event = await stream.next(); 77 | assert(event.value); 78 | expect(event.value.event).toEqual('foo'); 79 | expect(event.value.data).toEqual(''); 80 | 81 | event = await stream.next(); 82 | assert(event.value); 83 | expect(event.value.event).toEqual('ping'); 84 | expect(event.value.data).toEqual(''); 85 | 86 | event = await stream.next(); 87 | expect(event.done).toBeTruthy(); 88 | }); 89 | 90 | test('multiple events with data', async () => { 91 | async function* body(): AsyncGenerator { 92 | yield Buffer.from('event: foo\n'); 93 | yield Buffer.from('data: {"foo":true}\n'); 94 | yield Buffer.from('\n'); 95 | yield Buffer.from('event: ping\n'); 96 | yield Buffer.from('data: {"bar":false}\n'); 97 | yield Buffer.from('\n'); 98 | } 99 | 100 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 101 | Symbol.asyncIterator 102 | ](); 103 | 104 | let event = await stream.next(); 105 | assert(event.value); 106 | expect(event.value.event).toEqual('foo'); 107 | expect(JSON.parse(event.value.data)).toEqual({ foo: true }); 108 | 109 | event = await stream.next(); 110 | assert(event.value); 111 | expect(event.value.event).toEqual('ping'); 112 | expect(JSON.parse(event.value.data)).toEqual({ bar: false }); 113 | 114 | event = await stream.next(); 115 | expect(event.done).toBeTruthy(); 116 | }); 117 | 118 | test('multiple data lines with empty line', async () => { 119 | async function* body(): AsyncGenerator { 120 | yield Buffer.from('event: ping\n'); 121 | yield Buffer.from('data: {\n'); 122 | yield Buffer.from('data: "foo":\n'); 123 | yield Buffer.from('data: \n'); 124 | yield Buffer.from('data:\n'); 125 | yield Buffer.from('data: true}\n'); 126 | yield Buffer.from('\n\n'); 127 | } 128 | 129 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 130 | Symbol.asyncIterator 131 | ](); 132 | 133 | let event = await stream.next(); 134 | assert(event.value); 135 | expect(event.value.event).toEqual('ping'); 136 | expect(JSON.parse(event.value.data)).toEqual({ foo: true }); 137 | expect(event.value.data).toEqual('{\n"foo":\n\n\ntrue}'); 138 | 139 | event = await stream.next(); 140 | expect(event.done).toBeTruthy(); 141 | }); 142 | 143 | test('data json escaped double new line', async () => { 144 | async function* body(): AsyncGenerator { 145 | yield Buffer.from('event: ping\n'); 146 | yield Buffer.from('data: {"foo": "my long\\n\\ncontent"}'); 147 | yield Buffer.from('\n\n'); 148 | } 149 | 150 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 151 | Symbol.asyncIterator 152 | ](); 153 | 154 | let event = await stream.next(); 155 | assert(event.value); 156 | expect(event.value.event).toEqual('ping'); 157 | expect(JSON.parse(event.value.data)).toEqual({ foo: 'my long\n\ncontent' }); 158 | 159 | event = await stream.next(); 160 | expect(event.done).toBeTruthy(); 161 | }); 162 | 163 | test('special new line characters', async () => { 164 | async function* body(): AsyncGenerator { 165 | yield Buffer.from('data: {"content": "culpa "}\n'); 166 | yield Buffer.from('\n'); 167 | yield Buffer.from('data: {"content": "'); 168 | yield Buffer.from([0xe2, 0x80, 0xa8]); 169 | yield Buffer.from('"}\n'); 170 | yield Buffer.from('\n'); 171 | yield Buffer.from('data: {"content": "foo"}\n'); 172 | yield Buffer.from('\n'); 173 | } 174 | 175 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 176 | Symbol.asyncIterator 177 | ](); 178 | 179 | let event = await stream.next(); 180 | assert(event.value); 181 | expect(JSON.parse(event.value.data)).toEqual({ content: 'culpa ' }); 182 | 183 | event = await stream.next(); 184 | assert(event.value); 185 | expect(JSON.parse(event.value.data)).toEqual({ content: Buffer.from([0xe2, 0x80, 0xa8]).toString() }); 186 | 187 | event = await stream.next(); 188 | assert(event.value); 189 | expect(JSON.parse(event.value.data)).toEqual({ content: 'foo' }); 190 | 191 | event = await stream.next(); 192 | expect(event.done).toBeTruthy(); 193 | }); 194 | 195 | test('multi-byte characters across chunks', async () => { 196 | async function* body(): AsyncGenerator { 197 | yield Buffer.from('event: completion\n'); 198 | yield Buffer.from('data: {"content": "'); 199 | // bytes taken from the string 'известни' and arbitrarily split 200 | // so that some multi-byte characters span multiple chunks 201 | yield Buffer.from([0xd0]); 202 | yield Buffer.from([0xb8, 0xd0, 0xb7, 0xd0]); 203 | yield Buffer.from([0xb2, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0xd0, 0xbd, 0xd0, 0xb8]); 204 | yield Buffer.from('"}\n'); 205 | yield Buffer.from('\n'); 206 | } 207 | 208 | const stream = _iterSSEMessages(new Response(await iteratorToStream(body())), new AbortController())[ 209 | Symbol.asyncIterator 210 | ](); 211 | 212 | let event = await stream.next(); 213 | assert(event.value); 214 | expect(event.value.event).toEqual('completion'); 215 | expect(JSON.parse(event.value.data)).toEqual({ content: 'известни' }); 216 | 217 | event = await stream.next(); 218 | expect(event.done).toBeTruthy(); 219 | }); 220 | }); 221 | 222 | async function iteratorToStream(iterator: AsyncGenerator): Promise { 223 | const parts: unknown[] = []; 224 | 225 | for await (const chunk of iterator) { 226 | parts.push(chunk); 227 | } 228 | 229 | let index = 0; 230 | 231 | const stream = new PassThrough({ 232 | read() { 233 | const value = parts[index]; 234 | if (value === undefined) { 235 | stream.end(); 236 | } else { 237 | index += 1; 238 | stream.write(value); 239 | } 240 | }, 241 | }); 242 | 243 | return stream; 244 | } 245 | -------------------------------------------------------------------------------- /tests/stringifyQuery.test.ts: -------------------------------------------------------------------------------- 1 | // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. 2 | 3 | import { Together } from 'together-ai'; 4 | 5 | const { stringifyQuery } = Together.prototype as any; 6 | 7 | describe(stringifyQuery, () => { 8 | for (const [input, expected] of [ 9 | [{ a: '1', b: 2, c: true }, 'a=1&b=2&c=true'], 10 | [{ a: null, b: false, c: undefined }, 'a=&b=false'], 11 | [{ 'a/b': 1.28341 }, `${encodeURIComponent('a/b')}=1.28341`], 12 | [ 13 | { 'a/b': 'c/d', 'e=f': 'g&h' }, 14 | `${encodeURIComponent('a/b')}=${encodeURIComponent('c/d')}&${encodeURIComponent( 15 | 'e=f', 16 | )}=${encodeURIComponent('g&h')}`, 17 | ], 18 | ]) { 19 | it(`${JSON.stringify(input)} -> ${expected}`, () => { 20 | expect(stringifyQuery(input)).toEqual(expected); 21 | }); 22 | } 23 | 24 | for (const value of [[], {}, new Date()]) { 25 | it(`${JSON.stringify(value)} -> `, () => { 26 | expect(() => stringifyQuery({ value })).toThrow(`Cannot stringify type ${typeof value}`); 27 | }); 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /tests/uploads.test.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import { toFile, type ResponseLike } from 'together-ai/uploads'; 3 | import { File } from 'together-ai/_shims/index'; 4 | 5 | class MyClass { 6 | name: string = 'foo'; 7 | } 8 | 9 | function mockResponse({ url, content }: { url: string; content?: Blob }): ResponseLike { 10 | return { 11 | url, 12 | blob: async () => content as any, 13 | }; 14 | } 15 | 16 | describe('toFile', () => { 17 | it('throws a helpful error for mismatched types', async () => { 18 | await expect( 19 | // @ts-expect-error intentionally mismatched type 20 | toFile({ foo: 'string' }), 21 | ).rejects.toThrowErrorMatchingInlineSnapshot( 22 | `"Unexpected data type: object; constructor: Object; props: ["foo"]"`, 23 | ); 24 | 25 | await expect( 26 | // @ts-expect-error intentionally mismatched type 27 | toFile(new MyClass()), 28 | ).rejects.toThrowErrorMatchingInlineSnapshot( 29 | `"Unexpected data type: object; constructor: MyClass; props: ["name"]"`, 30 | ); 31 | }); 32 | 33 | it('disallows string at the type-level', async () => { 34 | // @ts-expect-error we intentionally do not type support for `string` 35 | // to help people avoid passing a file path 36 | const file = await toFile('contents'); 37 | expect(file.text()).resolves.toEqual('contents'); 38 | }); 39 | 40 | it('extracts a file name from a Response', async () => { 41 | const response = mockResponse({ url: 'https://example.com/my/audio.mp3' }); 42 | const file = await toFile(response); 43 | expect(file.name).toEqual('audio.mp3'); 44 | }); 45 | 46 | it('extracts a file name from a File', async () => { 47 | const input = new File(['foo'], 'input.jsonl'); 48 | const file = await toFile(input); 49 | expect(file.name).toEqual('input.jsonl'); 50 | }); 51 | 52 | it('extracts a file name from a ReadStream', async () => { 53 | const input = fs.createReadStream('tests/uploads.test.ts'); 54 | const file = await toFile(input); 55 | expect(file.name).toEqual('uploads.test.ts'); 56 | }); 57 | 58 | it('does not copy File objects', async () => { 59 | const input = new File(['foo'], 'input.jsonl', { type: 'jsonl' }); 60 | const file = await toFile(input); 61 | expect(file).toBe(input); 62 | expect(file.name).toEqual('input.jsonl'); 63 | expect(file.type).toBe('jsonl'); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /tsc-multi.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { "extname": ".js", "module": "commonjs" }, 4 | { "extname": ".mjs", "module": "esnext" } 5 | ], 6 | "projects": ["tsconfig.build.json"] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["dist/src"], 4 | "exclude": ["dist/src/_shims/*-deno.ts"], 5 | "compilerOptions": { 6 | "rootDir": "./dist/src", 7 | "paths": { 8 | "together-ai/*": ["dist/src/*"], 9 | "together-ai": ["dist/src/index.ts"], 10 | }, 11 | "noEmit": false, 12 | "declaration": true, 13 | "declarationMap": true, 14 | "outDir": "dist", 15 | "pretty": true, 16 | "sourceMap": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["dist-deno"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "rootDir": "./dist-deno", 7 | "lib": ["es2020", "DOM"], 8 | "noEmit": true, 9 | "declaration": true, 10 | "declarationMap": true, 11 | "outDir": "dist-deno", 12 | "pretty": true, 13 | "sourceMap": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.dist-src.json: -------------------------------------------------------------------------------- 1 | { 2 | // this config is included in the published src directory to prevent TS errors 3 | // from appearing when users go to source, and VSCode opens the source .ts file 4 | // via declaration maps 5 | "include": ["index.ts"], 6 | "compilerOptions": { 7 | "target": "es2015", 8 | "lib": ["DOM"], 9 | "moduleResolution": "node" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src", "tests", "examples"], 3 | "exclude": ["src/_shims/**/*-deno.ts"], 4 | "compilerOptions": { 5 | "target": "es2020", 6 | "lib": ["es2020"], 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "esModuleInterop": true, 10 | "baseUrl": "./", 11 | "paths": { 12 | "together-ai/_shims/auto/*": ["src/_shims/auto/*-node"], 13 | "together-ai/*": ["src/*"], 14 | "together-ai": ["src/index.ts"] 15 | }, 16 | "noEmit": true, 17 | 18 | "resolveJsonModule": true, 19 | 20 | "forceConsistentCasingInFileNames": true, 21 | 22 | "strict": true, 23 | "noImplicitAny": true, 24 | "strictNullChecks": true, 25 | "strictFunctionTypes": true, 26 | "strictBindCallApply": true, 27 | "strictPropertyInitialization": true, 28 | "noImplicitThis": true, 29 | "noImplicitReturns": true, 30 | "alwaysStrict": true, 31 | "exactOptionalPropertyTypes": true, 32 | "noUncheckedIndexedAccess": true, 33 | "noImplicitOverride": true, 34 | "noPropertyAccessFromIndexSignature": true, 35 | "isolatedModules": false, 36 | 37 | "skipLibCheck": true 38 | } 39 | } 40 | --------------------------------------------------------------------------------