Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c16f892
chore: format all `api.md` files
stainless-app[bot] Feb 12, 2026
a3842e0
codegen metadata
stainless-app[bot] Feb 12, 2026
70900c6
feat: Update descriptions for endpoints
stainless-app[bot] Feb 12, 2026
ba9c50a
chore: Better jig deployment progress (#242)
narasul Feb 12, 2026
2e1bd13
chore: Fix various docstrings
stainless-app[bot] Feb 17, 2026
3095b9a
feat: Improve file uploads and FT create flows with checksums (#253)
blainekasten Feb 17, 2026
105b2f9
jig formatted status (#249)
dulaj-me Feb 17, 2026
7b9e574
chore: Add documentation and changelog to project.urls (#264)
blainekasten Feb 18, 2026
778a7d9
chore: Remove broken field LineCount from FileResponse
stainless-app[bot] Feb 18, 2026
62c9da6
chore: Remove line_count field from files sdks/clis (#265)
blainekasten Feb 18, 2026
1c2b4d2
codegen metadata
stainless-app[bot] Feb 19, 2026
59d0c33
fix(cli): fine-tuning create regression (#270)
blainekasten Feb 19, 2026
13d3551
feat(cli): Add json mode to `fine-tuning list --json` (#269)
blainekasten Feb 19, 2026
642adbd
chore: Refactor argument options with CLI file downloads (#267)
blainekasten Feb 19, 2026
6502acc
chore(cli): Improve messaging when attempting to cancel finetune that…
blainekasten Feb 19, 2026
2a452df
chore: format files (#266)
blainekasten Feb 19, 2026
b312b50
chore: configure new SDK language
stainless-app[bot] Feb 19, 2026
7a322f7
chore: Revert adding mcp code. Code additions were unexpected.
stainless-app[bot] Feb 19, 2026
5bcfbdf
chore: update mock server docs
stainless-app[bot] Feb 19, 2026
aee8e31
release: 2.2.0
stainless-app[bot] Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ jobs:
- name: Run lints
run: ./scripts/lint

- name: Run formatting
run: uv run ruff format --check

build:
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
timeout-minutes: 10
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.1.1"
".": "2.2.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 74
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/togetherai%2Ftogetherai-af83378ff78b22014ab7358ae8aa060cc25e4b818e798f2e09d6deb1226e0ba6.yml
openapi_spec_hash: 113f84b407b43bd991ee6d1afb6efb49
config_hash: 67b76d1064bef2e591cadf50de08ad19
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/togetherai%2Ftogetherai-da5b9df3bfe0d31a76c91444c9eba060ad607d7d5a4e7483c5cc3fe2cac0f25e.yml
openapi_spec_hash: 7efd2ae2111f3a9bf190485828a13252
config_hash: b66198d27b4d5c152688ff6cccfdeab5
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## 2.2.0 (2026-02-19)

Full Changelog: [v2.1.1...v2.2.0](https://github.com/togethercomputer/together-py/compare/v2.1.1...v2.2.0)

### Features

* **cli:** Add json mode to `fine-tuning list --json` ([#269](https://github.com/togethercomputer/together-py/issues/269)) ([13d3551](https://github.com/togethercomputer/together-py/commit/13d35511bb039b3053ecf3e7a90c04e2e2d91237))
* Improve file uploads and FT create flows with checksums ([#253](https://github.com/togethercomputer/together-py/issues/253)) ([3095b9a](https://github.com/togethercomputer/together-py/commit/3095b9af2ba564cefe6b64a7ee65450aacfbfa4c))
* Update descriptions for endpoints ([70900c6](https://github.com/togethercomputer/together-py/commit/70900c6da2e8f60bfd0f70a5497cf41c18008ee5))


### Bug Fixes

* **cli:** fine-tuning create regression ([#270](https://github.com/togethercomputer/together-py/issues/270)) ([59d0c33](https://github.com/togethercomputer/together-py/commit/59d0c3399643c42e1c6ee9cf74c70aa99104218c))


### Chores

* Add documentation and changelog to project.urls ([#264](https://github.com/togethercomputer/together-py/issues/264)) ([7b9e574](https://github.com/togethercomputer/together-py/commit/7b9e5749e448042f548a0fbcd5db5ff5bfbb99d7))
* Better jig deployment progress ([#242](https://github.com/togethercomputer/together-py/issues/242)) ([ba9c50a](https://github.com/togethercomputer/together-py/commit/ba9c50a8b9855ec95e871525a33932e46f470379))
* **cli:** Improve messaging when attempting to cancel finetune that is not cancellable ([#268](https://github.com/togethercomputer/together-py/issues/268)) ([6502acc](https://github.com/togethercomputer/together-py/commit/6502acc911413abceff3870f620a2bed742e9b08))
* configure new SDK language ([b312b50](https://github.com/togethercomputer/together-py/commit/b312b502fcff52aa3b877e03928ef6f5a34ed88a))
* Fix various docstrings ([2e1bd13](https://github.com/togethercomputer/together-py/commit/2e1bd13a49a1ddeb717c072e3b4a4e4c1669f2de))
* format all `api.md` files ([c16f892](https://github.com/togethercomputer/together-py/commit/c16f89205ebc2a371dfa468bfb9b3b1081e41a4f))
* format files ([#266](https://github.com/togethercomputer/together-py/issues/266)) ([2a452df](https://github.com/togethercomputer/together-py/commit/2a452df565a93a32963c615a5be3eb23a2e6b713))
* Refactor argument options with CLI file downloads ([#267](https://github.com/togethercomputer/together-py/issues/267)) ([642adbd](https://github.com/togethercomputer/together-py/commit/642adbda9f113bf815d63b90a9829367c4fac82e))
* Remove broken field LineCount from FileResponse ([778a7d9](https://github.com/togethercomputer/together-py/commit/778a7d9e61f1f69feff51a5c908a1d2221e8133d))
* Remove line_count field from files sdks/clis ([#265](https://github.com/togethercomputer/together-py/issues/265)) ([62c9da6](https://github.com/togethercomputer/together-py/commit/62c9da6efd0c8e8c5f686b45736b8765030e5e5f))
* Revert adding mcp code. Code additions were unexpected. ([7a322f7](https://github.com/togethercomputer/together-py/commit/7a322f7f3388149418e3a576d93cb0017f5fdecd))
* update mock server docs ([5bcfbdf](https://github.com/togethercomputer/together-py/commit/5bcfbdf4cd2ff84de834c8df0ecdccb18cac1e35))

## 2.1.1 (2026-02-12)

Full Changelog: [v2.1.0...v2.1.1](https://github.com/togethercomputer/together-py/compare/v2.1.0...v2.1.1)
Expand Down
3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ $ pip install ./path-to-wheel-file.whl
Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.

```sh
# you will need npm installed
$ npx prism mock path/to/your/openapi.yml
$ ./scripts/mock
```

```sh
Expand Down
9 changes: 1 addition & 8 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,7 @@ Methods:
Types:

```python
from together.types import (
FileList,
FileObject,
FilePurpose,
FileResponse,
FileType,
FileDeleteResponse,
)
from together.types import FileList, FilePurpose, FileResponse, FileType, FileDeleteResponse
```

Methods:
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "together"
version = "2.1.1"
version = "2.2.0"
description = "The official Python library for the together API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down Expand Up @@ -49,6 +49,8 @@ classifiers = [
[project.urls]
Homepage = "https://github.com/togethercomputer/together-py"
Repository = "https://github.com/togethercomputer/together-py"
Documentation = "https://docs.together.ai/"
Changelog = "https://github.com/togethercomputer/together-py/blob/main/CHANGELOG.md"

[project.optional-dependencies]
aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"]
Expand Down
2 changes: 1 addition & 1 deletion scripts/format
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ uv run ruff check --fix .
uv run ruff format

echo "==> Formatting docs"
uv run python scripts/utils/ruffen-docs.py README.md api.md
uv run python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md)
2 changes: 1 addition & 1 deletion src/together/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "together"
__version__ = "2.1.1" # x-release-please-version
__version__ = "2.2.0" # x-release-please-version
6 changes: 5 additions & 1 deletion src/together/lib/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import together
from together._version import __version__
from together._constants import DEFAULT_TIMEOUT
from together._utils._logs import setup_logging
from together.lib.cli.api.beta import beta
from together.lib.cli.api.evals import evals
from together.lib.cli.api.files import files
Expand Down Expand Up @@ -58,7 +59,10 @@ def main(
max_retries: int | None,
) -> None:
"""This is a sample CLI tool."""
os.environ.setdefault("TOGETHER_LOG", "debug" if debug else "info")
if debug:
os.environ.setdefault("TOGETHER_LOG", "debug")
setup_logging() # Must run this again here to allow the new logging configuration to take effect

try:
ctx.obj = together.Together(
api_key=api_key,
Expand Down
5 changes: 3 additions & 2 deletions src/together/lib/cli/api/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
try:
return f(*args, **kwargs)
# User aborted the command
except click.Abort:
sys.exit(0)
# Re-raise abort and usage errore so it displays a proper click message
except (click.Abort, click.UsageError) as e:
raise e
except APIError as e:
error_msg = ""
if e.body is not None:
Expand Down
4 changes: 3 additions & 1 deletion src/together/lib/cli/api/beta/clusters/list_regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def list_regions(ctx: click.Context, json: bool) -> None:
data.append(
{
"Name": region.name,
"Availability Zones": ", ".join(region.availability_zones) if region.availability_zones else "",
"Supported GPU Types": ", ".join(region.supported_instance_types)
if region.supported_instance_types
else "",
"Driver Versions": ", ".join(region.driver_versions) if region.driver_versions else "",
}
)
Expand Down
107 changes: 107 additions & 0 deletions src/together/lib/cli/api/beta/jig/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""Utility functions for jig CLI commands."""

from __future__ import annotations

from datetime import datetime

from together.types.beta.deployment import Deployment


def _format_timestamp(timestamp_str: str | None) -> str:
"""Format ISO timestamp for display"""
if not timestamp_str:
return "-"
try:
ts = datetime.fromisoformat(timestamp_str.replace("Z", "+00:00"))
return ts.strftime("%Y-%m-%d %H:%M:%S")
except (ValueError, TypeError):
return timestamp_str or "-"


def _image_tag(image: str | None) -> str:
if image is None:
return "unknown"
tag = image.rsplit(":", 1)[-1] if ":" in image else image
if "@sha256:" in image:
tag = f"sha256:{tag[:8]}"

return tag


def format_deployment_status(d: Deployment) -> str:
"""Format d status for CLI display"""
status = (
"App:\n"
f" {'Name':<8}: {d.name} ┃ ID: {d.id}\n"
f" {'Image':<8}: {d.image}\n"
f" {'Status':<8}: {d.status}\n"
f" Created : {_format_timestamp(d.created_at)}"
f" ┃ Updated : {_format_timestamp(d.updated_at)}\n"
)

if d.autoscaling:
autoscaling_status = (
f"\n Autoscaling: {d.autoscaling.get('metric', 'N/A')} {d.autoscaling.get('target', 'N/A')}(target)\n"
)
status += autoscaling_status

replica_status = (
"\n"
f" Replicas:\n"
f" {'Min/Max':<16}: {d.min_replicas}/{d.max_replicas}\n"
f" {'Ready/Desired':<16}: {d.ready_replicas}/{d.desired_replicas}\n"
)

status += replica_status

config_status = (
f"\nConfiguration:\n"
f" Port: {d.port}\n"
f" Command: {d.command}\n"
f" Args: {d.args}\n"
f" Health Check Path: {d.health_check_path}\n"
f" Resources: {d.cpu} core CPU ┃ {d.memory}GB Memory ┃ {d.storage}GB Storage \n"
)

if d.gpu_count and d.gpu_type:
config_status += f" GPU: {d.gpu_count}x {d.gpu_type}\n"

if d.volumes:
config_status += f"\n Volumes:\n {'NAME':<28} MOUNT_PATH\n"
for vol in d.volumes:
config_status += f" {vol.name:<28} {vol.mount_path}\n"

if d.environment_variables:
secrets = [env for env in d.environment_variables if env.value_from_secret]
env_vars = [env for env in d.environment_variables if not env.value_from_secret]

if secrets:
config_status += f"\n Secrets: {[secret.name for secret in secrets]}\n"

if env_vars:
config_status += f"\n Environment Variables:\n {'NAME':<40} VALUE\n"
for env in env_vars:
config_status += f" {env.name:<40} {env.value}\n"

status += config_status

if d.replica_events:
events_status = "\nReplica Events:\n"
images = set(map(lambda x: x.image or "-", d.replica_events.values()))
for image in reversed(sorted(images)):
events = filter(lambda x: ((x[1].image or "-") == image), d.replica_events.items())
events_status += f"{_image_tag(image)}:\n"
for replica_id, event in events:
events_status += f" {replica_id}: "

if event.volume_preload_status and not event.volume_preload_completed_at:
events_status += f"Volume Preloading"
else:
events_status += f"{event.replica_status}"
if event.replica_status == "Running":
events_status += f", ready since {_format_timestamp(event.replica_ready_since)}"
events_status += "\n"

status += events_status

return status
Loading