Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: js
working-directory: ts

steps:
- name: Check out repository
Expand All @@ -51,7 +51,7 @@ jobs:
node-version: "24"
registry-url: "https://registry.npmjs.org"
cache: "npm"
cache-dependency-path: js/package-lock.json
cache-dependency-path: ts/package-lock.json

- name: Update npm
run: npm install -g npm@^11.5.1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: JS Tests
name: TS Tests

on:
push:
Expand All @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: js
working-directory: ts

steps:
- name: Check out repository
Expand All @@ -21,7 +21,7 @@ jobs:
with:
node-version: "20"
cache: "npm"
cache-dependency-path: js/package-lock.json
cache-dependency-path: ts/package-lock.json

- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,6 @@ credentials*.json
.idea/
*.skills/

# Node / JS SDK (js/)
# Node / TypeScript SDK (ts/)
node_modules/
*.tsbuildinfo
20 changes: 10 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This document provides guidance for AI assistants working on the Celesto SDK cod
- Manage delegated access to user resources (Google Drive, etc.) via GateKeeper
- Interact with the platform through both programmatic SDK and command-line interfaces

This repository also hosts the **`@celestoai/sdk`** JavaScript/TypeScript SDK under [js/](js/). It is an independent package (Gatekeeper + Computers, Node 18+, tsup build) with its own release pipeline to npm. The Python and JS packages share this repo but are otherwise decoupled — no shared tooling, no workspace, no cross-imports.
This repository also hosts the **`@celestoai/sdk`** JavaScript/TypeScript SDK under [ts/](ts/). It is an independent package (Gatekeeper + Computers, Node 18+, tsup build) with its own release pipeline to npm. The Python and TypeScript packages share this repo but are otherwise decoupled — no shared tooling, no workspace, no cross-imports.

**Current Version:** 0.0.4 (Python) · 0.1.1 (JS, `@celestoai/sdk`)
**License:** Apache 2.0
Expand All @@ -35,7 +35,7 @@ celesto-sdk/
├── tests/ # Python test suite
│ ├── test_sdk.py # SDK unit tests
│ └── test_deployment.py # Deployment tests
├── js/ # @celestoai/sdk — JavaScript/TypeScript SDK
├── ts/ # @celestoai/sdk — JavaScript/TypeScript SDK
│ ├── src/
│ │ ├── core/ # config, errors, http (shared HTTP client)
│ │ ├── gatekeeper/ # GatekeeperClient and types
Expand All @@ -50,9 +50,9 @@ celesto-sdk/
└── LICENSE # Apache 2.0 license
```

### JS SDK notes
### TypeScript SDK notes

- Location: [js/](js/)
- Location: [ts/](ts/)
- Package name: `@celestoai/sdk` (published to npm with public access)
- Scope: **Gatekeeper** + **Computers**. `Celesto` composes both: `celesto.gatekeeper.*` and `celesto.computers.*`. Individual clients are also importable via subpath exports (`@celestoai/sdk/gatekeeper`, `@celestoai/sdk/computers`).
- Computers parity with Python: all 7 HTTP methods (`create`, `list`, `get`, `exec`, `stop`, `start`, `delete`) plus `getTerminalConnection()` which returns `{ url, headers, firstMessage }` for BYO WebSocket. Zero runtime dependencies.
Expand All @@ -63,12 +63,12 @@ celesto-sdk/
- Does **not** auto-resume stopped computers — that's application logic, not SDK default.
- Public API is camelCase; wire DTOs are snake_case (`vcpus`, `ram_mb`, `exit_code`, etc.) mapped in the client file. Same pattern as Gatekeeper.
- Error hierarchy: `CelestoError` (base) → `CelestoApiError` (HTTP errors with `.status`) and `CelestoNetworkError` (DNS, timeout, offline). Network failures from `fetch()` are always wrapped — never leak raw `TypeError`.
- Build: `cd js && npm install && npm run build` (tsup → ESM + CJS + DTS under `js/dist/`)
- Lint / typecheck: `cd js && npm run lint` (runs `tsc --noEmit`)
- Unit tests: `cd js && npm test`. Uses Node's built-in `node:test` runner via `tsx`. Tests live in `js/tests/`. HTTP tests mock `fetch` via `ClientConfig.fetch`.
- Smoke test (manual, needs live API key): `cd js && node test.mjs`
- No workspace plumbing, no `package.json` at the repo root — treat `js/` as a self-contained project.
- Publish process is manual and independent from the Python release: bump `js/package.json` version, `npm run build`, `npm publish` from inside `js/`.
- Build: `cd ts && npm install && npm run build` (tsup → ESM + CJS + DTS under `ts/dist/`)
- Lint / typecheck: `cd ts && npm run lint` (runs `tsc --noEmit`)
- Unit tests: `cd ts && npm test`. Uses Node's built-in `node:test` runner via `tsx`. Tests live in `ts/tests/`. HTTP tests mock `fetch` via `ClientConfig.fetch`.
- Smoke test (manual, needs live API key): `cd ts && node test.mjs`
- No workspace plumbing, no `package.json` at the repo root — treat `ts/` as a self-contained project.
- Publish process is manual and independent from the Python release: bump `ts/package.json` version, `npm run build`, `npm publish` from inside `ts/`.

## Architecture

Expand Down
165 changes: 76 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Use Celesto when you want to:

This README covers the Python SDK, which is a code package, and the CLI, which
is the `celesto` command. The JavaScript and TypeScript SDK is also available as
[`@celestoai/sdk`](./js/README.md).
[`@celestoai/sdk`](./ts/README.md).

## Install

Expand Down Expand Up @@ -60,7 +60,7 @@ Linux machines without a credential store, it saves the key in
`$XDG_CONFIG_HOME/celesto/credentials.json` when `XDG_CONFIG_HOME` is set, or
`~/.config/celesto/credentials.json` otherwise, with user-only file
permissions. SDK code does not read that saved CLI key; it reads
`CELESTO_API_KEY` or the `api_key` value you pass to `Celesto`.
`CELESTO_API_KEY` or the `api_key` value you pass to `Computer`.

## Create a Computer from Python

Expand All @@ -69,27 +69,29 @@ output, and deletes the computer. Celesto uses the `scratch` template by
default.

```python
from celesto import Celesto

client = Celesto()
computer = client.computers.create()

print(f"Computer ready: {computer['name']}")

result = client.computers.exec(computer["id"], "uname -a")
print(result["stdout"])

client.computers.delete(computer["id"])
from celesto import Computer

computer = Computer()
try:
print(f"Computer ready: {computer.name}")

result = computer.run("uname -a")
print(result["stdout"])
finally:
computer.delete()
```

To pass the key directly instead of using `CELESTO_API_KEY`:

```python
from celesto import Celesto
from celesto import Computer

with Celesto(api_key="your-api-key") as client:
result = client.computers.list()
print(result["count"])
computer = Computer(api_key="your-api-key")
try:
result = computer.run("uname -a")
print(result["stdout"])
finally:
computer.delete()
```

## Manage Computers from the CLI
Expand Down Expand Up @@ -235,22 +237,20 @@ Use `celesto computer list` to see the computers in your account.
In an ESM or TypeScript file:

```ts
import { Celesto } from "@celestoai/sdk";

const celesto = new Celesto({ token: process.env.CELESTO_API_KEY });
import { Computer } from "@celestoai/sdk";

const computer = await celesto.computers.create();
const computer = await Computer.create();
try {
console.log(`Computer ready: ${computer.name}`);

const result = await celesto.computers.exec(computer.id, "uname -a");
const result = await computer.run("uname -a");
console.log(result.stdout);
} finally {
await celesto.computers.delete(computer.id);
await computer.delete();
}
```

See the [JavaScript and TypeScript README](./js/README.md) for Node.js
See the [JavaScript and TypeScript README](./ts/README.md) for Node.js
requirements, Gatekeeper examples, and terminal connection details.

## Python Computers API
Expand All @@ -260,21 +260,17 @@ Use the Python SDK when you want Celesto inside an app, script, or agent.
### Create

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
computer = client.computers.create(
cpus=2,
memory=2048,
disk_size_mb=15360,
)
try:
print(computer["name"])
finally:
client.computers.delete(computer["id"])
computer = Computer(cpus=2, memory=2048, disk="15gb")
try:
print(computer.name, computer["name"])
finally:
computer.delete()
```

Omit CPU, memory, or disk fields to use the default size.
Omit CPU, memory, or disk fields to use the default size. `disk` accepts MB as
an integer or strings such as `"2gb"`.

### Templates

Expand All @@ -285,12 +281,11 @@ when you want a computer that already has extra tools installed. For example,
List available templates:

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
templates = client.computers.list_templates()
for template in templates:
print(template["id"], template.get("preinstalled_tools", []))
templates = Computer.list_templates()
for template in templates:
print(template["id"], template.get("preinstalled_tools", []))
```

Template responses may include metadata such as aliases, capabilities,
Expand All @@ -301,84 +296,81 @@ when your code can run against multiple API versions.
Create a computer from a template:

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
computer = client.computers.create(template_id="coding-agent")
try:
print(computer["name"])
finally:
client.computers.delete(computer["id"])
computer = Computer(template_id="coding-agent")
try:
print(computer.name)
finally:
computer.delete()
```

### Run a Command

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
computer = client.computers.create()
try:
result = client.computers.exec(computer["id"], "ls -la", timeout=60)
print(result["exit_code"])
print(result["stdout"])
print(result["stderr"])
finally:
client.computers.delete(computer["id"])
computer = Computer()
try:
result = computer.run("ls -la", timeout=60)
print(result["exit_code"])
print(result["stdout"])
print(result["stderr"])
finally:
computer.delete()
```

The `timeout` value is the remote command timeout in seconds. The SDK gives the
HTTP request a little more time than the command itself so slow command output
can still return cleanly.

Current caveat: `exec()` runs as the computer image's default exec user. The SDK
does not yet expose a user selector.
Current caveat: `run()` and `exec()` run as the computer image's default exec
user. The SDK does not yet expose a user selector.

### List, Stop, Start, and Delete

`computer_id` can be the ID returned by `client.computers.create()`, such as
`computer["id"]`, or a computer name shown by `celesto computer list`.
`computer_id` can be `computer.id` from `Computer()` or a computer name shown by
`celesto computer list`.

Filter a list when you only want matching computers:

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
result = client.computers.list(status="running", template_id="browser-agent")
for computer in result["computers"]:
print(computer["name"])
computers = Computer.list(status="running", template_id="browser-agent")
for computer in computers:
print(computer["name"])
```

| Method | What it does |
| --- | --- |
| `client.computers.list()` | List computers in your account |
| `client.computers.list(status="running", template_id="browser-agent", project_id="proj_123", limit=10)` | List matching computers |
| `client.computers.get(computer_id)` | Get one computer by name or ID |
| `client.computers.stop(computer_id)` | Stop a running computer |
| `client.computers.start(computer_id)` | Start a stopped computer |
| `client.computers.delete(computer_id)` | Delete a computer |
| `Computer.list()` | List computers in your account |
| `Computer.list(status="running", template_id="browser-agent", project_id="proj_123", limit=10)` | List matching computers |
| `Computer.get(computer_id)` | Get one computer by name or ID |
| `computer.stop()` | Stop a running computer |
| `computer.start()` | Start a stopped computer |
| `computer.delete()` | Delete a computer |

### Publish Ports

Publish a port when a service inside the computer needs a public URL:

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
published = client.computers.publish_port("curie", port=8000)
print(published["url"])
computer = Computer.get("curie")
url = computer.publish_port(8000)
print(url)
```

List and remove published ports:

```python
from celesto import Celesto
from celesto import Computer

with Celesto() as client:
print(client.computers.list_published_ports("curie"))
client.computers.unpublish_port("curie", port=8000)
computer = Computer.get("curie")
print(computer.list_published_ports())
computer.unpublish_port(8000)
```

## CLI Commands
Expand Down Expand Up @@ -416,14 +408,9 @@ celesto computer create --disk-size-mb 15360 --json

## Other Python SDK APIs

The Python SDK also includes:

- `client.deployment` for deploying agents to Celesto.
- `client.gatekeeper` for connecting user-approved external resources, such as
Google Drive.

See the [full documentation](https://docs.celesto.ai/celesto-sdk) for these
advanced APIs.
The high-level SDK now exposes computers directly through `Computer`. Deployment
and Gatekeeper helpers are still available from the CLI while their direct SDK
resource APIs are being updated to match this style.

## OpenAI Agents SDK Sandboxes

Expand Down
4 changes: 2 additions & 2 deletions src/celesto/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Celesto SDK package."""

from .main import app
from .sdk import Celesto
from .sdk import Computer

__version__ = "0.0.9"

__all__ = ["app", "Celesto", "__version__"]
__all__ = ["app", "Computer", "__version__"]
Comment on lines +4 to +8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Sort __all__, or the lint gate stops the whole operation.

Ruff's RUF022 flags Line 8 — __all__ isn't in isort order (CamelCase before the rest, natural sort within groups). A small thing, but a man who don't tidy his own house gets no respect on the street.

As per coding guidelines, "Use Ruff for linting and formatting Python code."

🧹 Proposed fix
-__all__ = ["app", "Computer", "__version__"]
+__all__ = ["Computer", "__version__", "app"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from .sdk import Computer
__version__ = "0.0.9"
__all__ = ["app", "Celesto", "__version__"]
__all__ = ["app", "Computer", "__version__"]
from .sdk import Computer
__version__ = "0.0.9"
__all__ = ["Computer", "__version__", "app"]
🧰 Tools
🪛 Ruff (0.15.20)

[warning] 8-8: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/celesto/__init__.py` around lines 4 - 8, `__all__` in the module-level
`__init__` is out of Ruff/isort order and triggers RUF022. Update the `__all__`
declaration in `src/celesto/__init__.py` so the exported names are sorted in the
expected order, keeping `Computer` grouped before the lowercase entry and
preserving `__version__` as needed. Use the existing `__all__` symbol in
`__init__.py` as the single place to fix the ordering.

Sources: Coding guidelines, Linters/SAST tools

Loading
Loading