colabctl 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- colabctl-0.1.0/.github/workflows/ci.yml +54 -0
- colabctl-0.1.0/.github/workflows/publish.yml +26 -0
- colabctl-0.1.0/.gitignore +27 -0
- colabctl-0.1.0/CHANGELOG.md +55 -0
- colabctl-0.1.0/CONTRIBUTING.md +44 -0
- colabctl-0.1.0/DECISIONS.md +510 -0
- colabctl-0.1.0/DIRECTIVES.md +31 -0
- colabctl-0.1.0/LICENSE +201 -0
- colabctl-0.1.0/PKG-INFO +200 -0
- colabctl-0.1.0/README.md +136 -0
- colabctl-0.1.0/RESEARCH.md +427 -0
- colabctl-0.1.0/ROADMAP.md +53 -0
- colabctl-0.1.0/SPEC.md +8443 -0
- colabctl-0.1.0/docs/architecture.md +37 -0
- colabctl-0.1.0/docs/index.md +68 -0
- colabctl-0.1.0/mkdocs.yml +11 -0
- colabctl-0.1.0/pyproject.toml +125 -0
- colabctl-0.1.0/spikes/PHASE0-FINDINGS.md +105 -0
- colabctl-0.1.0/spikes/PHASE0.md +110 -0
- colabctl-0.1.0/spikes/gpu_probe.py +109 -0
- colabctl-0.1.0/spikes/modal_smoke.py +50 -0
- colabctl-0.1.0/spikes/native_smoke.py +78 -0
- colabctl-0.1.0/spikes/run_phase0.sh +117 -0
- colabctl-0.1.0/src/colabctl/__init__.py +71 -0
- colabctl-0.1.0/src/colabctl/auth/__init__.py +21 -0
- colabctl-0.1.0/src/colabctl/auth/adc.py +80 -0
- colabctl-0.1.0/src/colabctl/auth/base.py +63 -0
- colabctl-0.1.0/src/colabctl/backends/__init__.py +42 -0
- colabctl-0.1.0/src/colabctl/backends/base.py +147 -0
- colabctl-0.1.0/src/colabctl/backends/colab.py +166 -0
- colabctl-0.1.0/src/colabctl/backends/factory.py +65 -0
- colabctl-0.1.0/src/colabctl/backends/hf_backend.py +197 -0
- colabctl-0.1.0/src/colabctl/backends/kaggle_backend.py +216 -0
- colabctl-0.1.0/src/colabctl/backends/modal_backend.py +201 -0
- colabctl-0.1.0/src/colabctl/backends/router.py +76 -0
- colabctl-0.1.0/src/colabctl/backends/vertex_backend.py +237 -0
- colabctl-0.1.0/src/colabctl/cli.py +327 -0
- colabctl-0.1.0/src/colabctl/drive.py +218 -0
- colabctl-0.1.0/src/colabctl/errors.py +147 -0
- colabctl-0.1.0/src/colabctl/lifecycle.py +194 -0
- colabctl-0.1.0/src/colabctl/mcp_server.py +209 -0
- colabctl-0.1.0/src/colabctl/models.py +233 -0
- colabctl-0.1.0/src/colabctl/observability.py +107 -0
- colabctl-0.1.0/src/colabctl/sdk/__init__.py +8 -0
- colabctl-0.1.0/src/colabctl/sdk/client.py +202 -0
- colabctl-0.1.0/src/colabctl/sdk/remote.py +178 -0
- colabctl-0.1.0/src/colabctl/secrets/__init__.py +37 -0
- colabctl-0.1.0/src/colabctl/secrets/base.py +56 -0
- colabctl-0.1.0/src/colabctl/secrets/encrypted_file.py +122 -0
- colabctl-0.1.0/src/colabctl/secrets/keyring_store.py +107 -0
- colabctl-0.1.0/src/colabctl/secrets/memory.py +24 -0
- colabctl-0.1.0/src/colabctl/transport/__init__.py +18 -0
- colabctl-0.1.0/src/colabctl/transport/base.py +122 -0
- colabctl-0.1.0/src/colabctl/transport/browser/__init__.py +19 -0
- colabctl-0.1.0/src/colabctl/transport/browser/bridge.py +260 -0
- colabctl-0.1.0/src/colabctl/transport/cli/__init__.py +15 -0
- colabctl-0.1.0/src/colabctl/transport/cli/adapter.py +252 -0
- colabctl-0.1.0/src/colabctl/transport/cli/parser.py +192 -0
- colabctl-0.1.0/src/colabctl/transport/native/__init__.py +49 -0
- colabctl-0.1.0/src/colabctl/transport/native/adapter.py +260 -0
- colabctl-0.1.0/src/colabctl/transport/native/client.py +371 -0
- colabctl-0.1.0/src/colabctl/transport/native/kernel.py +259 -0
- colabctl-0.1.0/tests/conftest.py +136 -0
- colabctl-0.1.0/tests/test_auth.py +32 -0
- colabctl-0.1.0/tests/test_backends_base.py +29 -0
- colabctl-0.1.0/tests/test_browser_bridge.py +140 -0
- colabctl-0.1.0/tests/test_cli_adapter.py +43 -0
- colabctl-0.1.0/tests/test_cli_job.py +55 -0
- colabctl-0.1.0/tests/test_cli_parser.py +153 -0
- colabctl-0.1.0/tests/test_colab_backend.py +62 -0
- colabctl-0.1.0/tests/test_drive.py +152 -0
- colabctl-0.1.0/tests/test_factory.py +38 -0
- colabctl-0.1.0/tests/test_hf_backend.py +98 -0
- colabctl-0.1.0/tests/test_kaggle_backend.py +88 -0
- colabctl-0.1.0/tests/test_lifecycle.py +166 -0
- colabctl-0.1.0/tests/test_mcp_jobs.py +48 -0
- colabctl-0.1.0/tests/test_mcp_tools.py +73 -0
- colabctl-0.1.0/tests/test_modal_backend.py +162 -0
- colabctl-0.1.0/tests/test_models.py +88 -0
- colabctl-0.1.0/tests/test_native_adapter.py +179 -0
- colabctl-0.1.0/tests/test_native_client.py +108 -0
- colabctl-0.1.0/tests/test_native_contract.py +80 -0
- colabctl-0.1.0/tests/test_native_http.py +68 -0
- colabctl-0.1.0/tests/test_native_kernel.py +94 -0
- colabctl-0.1.0/tests/test_native_optin.py +38 -0
- colabctl-0.1.0/tests/test_observability.py +93 -0
- colabctl-0.1.0/tests/test_remote.py +82 -0
- colabctl-0.1.0/tests/test_router.py +114 -0
- colabctl-0.1.0/tests/test_sdk_client.py +104 -0
- colabctl-0.1.0/tests/test_secrets.py +137 -0
- colabctl-0.1.0/tests/test_vertex_backend.py +117 -0
- colabctl-0.1.0/uv.lock +3410 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: lint · types · tests (py${{ matrix.python }})
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python: ["3.11", "3.12", "3.13"]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python }}
|
|
27
|
+
enable-cache: true
|
|
28
|
+
|
|
29
|
+
- name: Sync (all extras + dev)
|
|
30
|
+
run: uv sync --all-extras
|
|
31
|
+
|
|
32
|
+
- name: Ruff lint
|
|
33
|
+
run: uv run ruff check src tests
|
|
34
|
+
|
|
35
|
+
- name: Ruff format check
|
|
36
|
+
run: uv run ruff format --check src tests
|
|
37
|
+
|
|
38
|
+
- name: Mypy (strict)
|
|
39
|
+
run: uv run mypy src
|
|
40
|
+
|
|
41
|
+
- name: Pytest
|
|
42
|
+
run: uv run pytest -q
|
|
43
|
+
|
|
44
|
+
build:
|
|
45
|
+
name: build sdist + wheel
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v4
|
|
49
|
+
- uses: astral-sh/setup-uv@v5
|
|
50
|
+
- run: uv build
|
|
51
|
+
- uses: actions/upload-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: dist
|
|
54
|
+
path: dist/
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes on a version tag (e.g. `v0.1.0`). Uses PyPI Trusted Publishing
|
|
4
|
+
# (GitHub OIDC) — no API token is stored in the repo.
|
|
5
|
+
#
|
|
6
|
+
# One-time setup on PyPI (https://pypi.org/manage/account/publishing/):
|
|
7
|
+
# project: colabctl · owner: mandipadk · repo: colabctl · workflow: publish.yml
|
|
8
|
+
# environment: pypi
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags: ["v*"]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
publish:
|
|
15
|
+
name: build + publish
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
environment: pypi
|
|
18
|
+
permissions:
|
|
19
|
+
id-token: write # required for Trusted Publishing
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: astral-sh/setup-uv@v5
|
|
23
|
+
- name: Build sdist + wheel
|
|
24
|
+
run: uv build
|
|
25
|
+
- name: Publish to PyPI (trusted publishing)
|
|
26
|
+
run: uv publish --trusted-publishing always
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
|
|
7
|
+
# Builds
|
|
8
|
+
/dist/
|
|
9
|
+
/build/
|
|
10
|
+
/site/ # mkdocs output
|
|
11
|
+
|
|
12
|
+
# Tooling caches
|
|
13
|
+
.venv/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
htmlcov/
|
|
19
|
+
|
|
20
|
+
# Spike outputs / local artifacts
|
|
21
|
+
spikes/phase0-results.txt
|
|
22
|
+
spikes/phase0_*.txt
|
|
23
|
+
spikes/phase0_*.png
|
|
24
|
+
|
|
25
|
+
# Secrets / local config (never commit)
|
|
26
|
+
.env
|
|
27
|
+
*.token.json
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/), and the project aims to adhere to
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] - 2026-06-08
|
|
10
|
+
|
|
11
|
+
First public release. Programmatic Google Colab control plus a multi-backend job API.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Transports** behind a single `TransportAdapter` contract:
|
|
16
|
+
- `cli` — wraps the official `google-colab-cli` (sanctioned default), with a
|
|
17
|
+
golden-tested stdout parser pinned to v0.5.7.
|
|
18
|
+
- `native` — from-scratch `/tun/m/*` client + Jupyter-websocket kernel (co-primary,
|
|
19
|
+
opt-in). Both **live-validated** against real Colab Pro.
|
|
20
|
+
- **Auth** — ADC-led providers (the Phase 0-verified path) + scope constants.
|
|
21
|
+
- **Secrets** — one `SecretStore` contract over keyring (chunked), an encrypted file
|
|
22
|
+
(headless/CI), and an in-memory store.
|
|
23
|
+
- **SDK** — `ColabClient` / `ColabSession` (async, context-managed) and the `@remote`
|
|
24
|
+
decorator (ship a local function to a GPU via cloudpickle).
|
|
25
|
+
- **CLI** — `colabctl` (Typer): `run`, `exec`, `new`, `sessions`, `status`, `stop`,
|
|
26
|
+
`upload`, `download`, `keepalive`, and `job run` / `job backends`.
|
|
27
|
+
- **MCP server** — `colabctl-mcp` (FastMCP) exposing 9 tools (interactive + batch-job)
|
|
28
|
+
so AI agents can drive Colab, Modal, and Vertex.
|
|
29
|
+
- **Provider abstraction** — `Backend` (submit/status/logs/result/cancel) + a
|
|
30
|
+
capability-routing `BackendRouter` with infra failover, plus the **Colab**,
|
|
31
|
+
**Modal** (live-validated), **Vertex AI**, **Hugging Face Jobs**, and **Kaggle**
|
|
32
|
+
backends, wired into the CLI (`colabctl job …`) and MCP.
|
|
33
|
+
- **Browser-bridge transport** (colab-mcp model) — JSON-RPC relay over a local
|
|
34
|
+
WebSocket; human-in-the-loop, needs live validation.
|
|
35
|
+
- **Runtime-lifecycle manager** — best-effort keep-alive ticks + proactive checkpoint
|
|
36
|
+
+ automatic re-assign/restore on idle reclamation.
|
|
37
|
+
- **Drive sync** — `DriveSync` (durable My-Drive file sync via user-OAuth) + lifecycle
|
|
38
|
+
checkpoint/restore hooks.
|
|
39
|
+
- **Observability** — namespaced logging + a reusable `retry_async` (exponential
|
|
40
|
+
backoff that never retries terminal quota/entitlement errors).
|
|
41
|
+
- **Spend guard** — `cap_timeout` enforces a hard billable-time ceiling on paid
|
|
42
|
+
backends (wired into Modal).
|
|
43
|
+
|
|
44
|
+
### Known limitations
|
|
45
|
+
|
|
46
|
+
- The Colab RuntimeService keep-alive RPC is unusable under token auth (live-confirmed);
|
|
47
|
+
long jobs rely on kernel activity + checkpoint/re-assign instead.
|
|
48
|
+
- Vertex stdout is in Cloud Logging (not captured); `result` returns state + a log link.
|
|
49
|
+
- Vertex / Hugging Face / Kaggle backends and the browser-bridge are not yet
|
|
50
|
+
live-validated (no accounts in CI); their logic is unit-tested against fakes.
|
|
51
|
+
- Still planned: RunPod/vast.ai + hyperscaler backends, a papermill notebook adapter,
|
|
52
|
+
a `jupyter_http_over_ws` integration test rig, a billing watchdog, and a docs site.
|
|
53
|
+
|
|
54
|
+
[Unreleased]: https://github.com/mandipadk/colabctl/compare/v0.1.0...HEAD
|
|
55
|
+
[0.1.0]: https://github.com/mandipadk/colabctl/releases/tag/v0.1.0
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributing to colabctl
|
|
2
|
+
|
|
3
|
+
Thanks for helping build colabctl. This guide covers the dev workflow and the quality
|
|
4
|
+
bar every change must clear.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
colabctl uses [uv](https://docs.astral.sh/uv/). Install it, then:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
uv sync --all-extras # creates .venv with every optional dependency + dev tools
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## The quality gate (run before every commit)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv run ruff check src tests # lint
|
|
18
|
+
uv run ruff format src tests # format (use --check in CI)
|
|
19
|
+
uv run mypy src # strict type-check
|
|
20
|
+
uv run pytest -q # the full suite — offline, no credentials
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
CI runs exactly this on Python 3.11 / 3.12 / 3.13, plus `uv build`. All four must pass.
|
|
24
|
+
|
|
25
|
+
## Conventions
|
|
26
|
+
|
|
27
|
+
- **Strict typing.** `mypy --strict` must pass. Lazy-imported third-party SDKs are
|
|
28
|
+
listed under `[[tool.mypy.overrides]]` in `pyproject.toml`.
|
|
29
|
+
- **Tests are offline.** No test may hit the network or need credentials. Live checks
|
|
30
|
+
live in `spikes/` and are run by hand against a real account.
|
|
31
|
+
- **Transports/backends are pluggable.** New transports implement
|
|
32
|
+
`transport.base.TransportAdapter`; new backends implement `backends.base.Backend`.
|
|
33
|
+
Keep heavy/optional SDKs lazy-imported and declared as an extra.
|
|
34
|
+
- **Be honest about limitations.** If something isn't live-validated or has a known
|
|
35
|
+
gap, say so in the docstring and the relevant doc — don't paper over it. (See the
|
|
36
|
+
keep-alive saga in `spikes/PHASE0-FINDINGS.md` for why.)
|
|
37
|
+
- **Pin & verify external contracts.** When wrapping an external API/CLI, verify it
|
|
38
|
+
against current docs/source and pin the version; surface contract drift loudly.
|
|
39
|
+
|
|
40
|
+
## Layout
|
|
41
|
+
|
|
42
|
+
`SPEC.md` is the canonical architecture. `DIRECTIVES.md` records binding decisions.
|
|
43
|
+
`spikes/` holds validation runbooks + findings. `src/colabctl/` is the package; see the
|
|
44
|
+
README for the module map.
|