gpu4agents 0.5.0__py3-none-any.whl

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.
Files changed (59) hide show
  1. gpu4agents/__init__.py +5 -0
  2. gpu4agents/__main__.py +4 -0
  3. gpu4agents/agent/__init__.py +1 -0
  4. gpu4agents/agent/install.py +173 -0
  5. gpu4agents/agent/jobs.py +193 -0
  6. gpu4agents/agent/mcp.py +646 -0
  7. gpu4agents/agent/skill/SKILL.md +68 -0
  8. gpu4agents/cli/__init__.py +0 -0
  9. gpu4agents/cli/_common.py +131 -0
  10. gpu4agents/cli/account.py +330 -0
  11. gpu4agents/cli/agent.py +74 -0
  12. gpu4agents/cli/inspect.py +207 -0
  13. gpu4agents/cli/lifecycle.py +127 -0
  14. gpu4agents/cli/main.py +163 -0
  15. gpu4agents/cli/providers.py +96 -0
  16. gpu4agents/cli/run.py +38 -0
  17. gpu4agents/cli/setup.py +164 -0
  18. gpu4agents/cli/status.py +224 -0
  19. gpu4agents/cli/timer.py +143 -0
  20. gpu4agents/cli/validate.py +57 -0
  21. gpu4agents/core/__init__.py +0 -0
  22. gpu4agents/core/beacon.py +133 -0
  23. gpu4agents/core/config.py +647 -0
  24. gpu4agents/core/credentials.py +95 -0
  25. gpu4agents/core/durations.py +47 -0
  26. gpu4agents/core/engine.py +1335 -0
  27. gpu4agents/core/errors.py +94 -0
  28. gpu4agents/core/events.py +117 -0
  29. gpu4agents/core/execution.py +169 -0
  30. gpu4agents/core/health.py +62 -0
  31. gpu4agents/core/hosts.py +58 -0
  32. gpu4agents/core/model_inspect.py +368 -0
  33. gpu4agents/core/models.py +313 -0
  34. gpu4agents/core/paths.py +42 -0
  35. gpu4agents/core/policy.py +264 -0
  36. gpu4agents/core/state.py +406 -0
  37. gpu4agents/core/sweep.py +478 -0
  38. gpu4agents/core/tool_parsers.py +63 -0
  39. gpu4agents/providers/__init__.py +4 -0
  40. gpu4agents/providers/base.py +137 -0
  41. gpu4agents/providers/registry.py +63 -0
  42. gpu4agents/providers/vast/__init__.py +3 -0
  43. gpu4agents/providers/vast/client.py +255 -0
  44. gpu4agents/providers/vast/config.py +56 -0
  45. gpu4agents/providers/vast/mapper.py +292 -0
  46. gpu4agents/providers/vast/provider.py +438 -0
  47. gpu4agents/runtime/__init__.py +6 -0
  48. gpu4agents/runtime/base.py +184 -0
  49. gpu4agents/runtime/vllm.py +295 -0
  50. gpu4agents/watchdog/__init__.py +3 -0
  51. gpu4agents/watchdog/agent_body.py +959 -0
  52. gpu4agents/watchdog/builder.py +248 -0
  53. gpu4agents-0.5.0.dist-info/METADATA +157 -0
  54. gpu4agents-0.5.0.dist-info/RECORD +59 -0
  55. gpu4agents-0.5.0.dist-info/WHEEL +4 -0
  56. gpu4agents-0.5.0.dist-info/entry_points.txt +2 -0
  57. gpu4agents-0.5.0.dist-info/licenses/LICENSE +21 -0
  58. jambu_gpu/__init__.py +9 -0
  59. jambu_gpu/__main__.py +4 -0
@@ -0,0 +1,248 @@
1
+ """Assembles the remote watchdog into a single self-contained script.
2
+
3
+ The lifecycle *policy* is owned by the core and inlined verbatim from
4
+ ``core/policy.py`` so the remote guard and `gpu status` can never
5
+ disagree. The *provider actions* are injected by the adapter. Neither side
6
+ knows about the other.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import ast
12
+ import base64
13
+ import json
14
+ import zlib
15
+ import secrets
16
+ from pathlib import Path
17
+ from typing import Optional
18
+
19
+ from ..core import policy as policy_module
20
+ from ..providers.base import WatchdogSpec
21
+
22
+ AGENT_REMOTE_PATH = "/opt/jambu/watchdog.py"
23
+ CONFIG_REMOTE_PATH = "/etc/jambu/watchdog.json"
24
+ STATE_REMOTE_PATH = "/var/lib/jambu/activity.json"
25
+ EVENTS_REMOTE_PATH = "/var/log/jambu/events.jsonl"
26
+ WATCHDOG_LOG_PATH = "/var/log/jambu/watchdog.log"
27
+ ONSTART_LOG_PATH = "/var/log/jambu/onstart.log"
28
+ SUPERVISOR_PID_PATH = "/var/run/jambu/watchdog.pid"
29
+ SUPERVISOR_RESPAWN_DELAY_S = 5
30
+
31
+ _HEADER = """#!/usr/bin/env python3
32
+ # Generated by gpu4agents. Do not edit on the instance.
33
+ # Lifecycle policy is inlined from gpu4agents/core/policy.py.
34
+ from __future__ import annotations
35
+ """
36
+
37
+ _FUTURE_IMPORT = "from __future__ import annotations"
38
+
39
+ _FALLBACK_ACTIONS = '''
40
+ def provider_stop(ctx):
41
+ raise RuntimeError("this provider supplied no stop action")
42
+
43
+
44
+ def provider_destroy(ctx):
45
+ raise RuntimeError("this provider supplied no destroy action")
46
+ '''
47
+
48
+
49
+ def generate_token() -> str:
50
+ """Shared secret protecting the watchdog's public control port."""
51
+ return secrets.token_urlsafe(32)
52
+
53
+
54
+ def _strip_future(source: str) -> str:
55
+ return "\n".join(
56
+ line for line in source.splitlines() if line.strip() != _FUTURE_IMPORT
57
+ )
58
+
59
+
60
+ def _compact(source: str) -> str:
61
+ """Same code without comments or docstrings.
62
+
63
+ The boot script rides in a size-capped provider field (Vast: 16 KB), so
64
+ what travels is the parsed-and-unparsed source: identical semantics, none
65
+ of the prose.
66
+ """
67
+ tree = ast.parse(source)
68
+ for node in ast.walk(tree):
69
+ body = getattr(node, "body", None)
70
+ if not isinstance(body, list) or not body:
71
+ continue
72
+ first = body[0]
73
+ if (
74
+ isinstance(first, ast.Expr)
75
+ and isinstance(first.value, ast.Constant)
76
+ and isinstance(first.value.value, str)
77
+ ):
78
+ node.body = body[1:] or [ast.Pass()]
79
+ return ast.unparse(tree)
80
+
81
+
82
+ def build_agent_source(actions_source: Optional[str] = None) -> str:
83
+ """Return the full stdlib-only watchdog script."""
84
+ policy_source = _compact(_strip_future(Path(policy_module.__file__).read_text()))
85
+ body_source = _compact(
86
+ _strip_future((Path(__file__).parent / "agent_body.py").read_text())
87
+ )
88
+ actions = _compact(_strip_future(actions_source or _FALLBACK_ACTIONS))
89
+ return "\n\n".join(
90
+ [
91
+ _HEADER,
92
+ "# --- inlined: gpu4agents/core/policy.py ---",
93
+ policy_source,
94
+ "# --- injected: provider actions ---",
95
+ actions,
96
+ "# --- inlined: gpu4agents/watchdog/agent_body.py ---",
97
+ body_source,
98
+ ]
99
+ )
100
+
101
+
102
+ def build_agent_config(
103
+ *,
104
+ provider: str,
105
+ instance_id: str,
106
+ token: str,
107
+ port: int,
108
+ interval_s: float,
109
+ startup_grace_s: float,
110
+ policy: "policy_module.PolicyConfig",
111
+ created_at: float,
112
+ watchdog_spec: Optional[WatchdogSpec] = None,
113
+ activity_probe: Optional[dict] = None,
114
+ runtime_pid_path: Optional[str] = None,
115
+ runtime_log_path: Optional[str] = None,
116
+ ) -> dict:
117
+ """Config the remote agent reads at boot.
118
+
119
+ ``activity_probe`` lets inference traffic that bypasses `gpu run` count as
120
+ activity, e.g. ``{"kind": "prometheus", "url": ".../metrics",
121
+ "gauges": [...], "counters": [...]}``.
122
+
123
+ ``runtime_pid_path`` lets the agent tell a dead model server from a slow
124
+ one; ``logs`` names the files its ``/logs`` route may serve.
125
+ """
126
+ logs = {"onstart": ONSTART_LOG_PATH, "watchdog": WATCHDOG_LOG_PATH}
127
+ if runtime_log_path:
128
+ logs["runtime"] = runtime_log_path
129
+ config = {
130
+ "provider": provider,
131
+ "instance_id": instance_id,
132
+ "token": token,
133
+ "port": int(port),
134
+ "interval_s": float(interval_s),
135
+ "startup_grace_s": float(startup_grace_s),
136
+ "created_at": float(created_at),
137
+ "policy": policy.to_dict(),
138
+ "env": dict(watchdog_spec.env) if watchdog_spec else {},
139
+ "provider_context": dict(watchdog_spec.context) if watchdog_spec else {},
140
+ "logs": logs,
141
+ }
142
+ if runtime_pid_path:
143
+ config["runtime_pid_path"] = runtime_pid_path
144
+ if activity_probe:
145
+ config["activity_probe"] = dict(activity_probe)
146
+ return config
147
+
148
+
149
+ def _b64_gz_block(text: str, width: int = 76) -> str:
150
+ """Compressed, line-wrapped payload (``width=0``: one line).
151
+
152
+ The boot script travels inside a provider API field, so the ~29 KB agent is
153
+ deflated to ~9 KB and wrapped, instead of riding on one enormous line.
154
+ """
155
+ blob = base64.b64encode(zlib.compress(text.encode(), 9)).decode()
156
+ if not width:
157
+ return blob
158
+ return "\n".join(blob[i : i + width] for i in range(0, len(blob), width))
159
+
160
+
161
+ def build_onstart_script(
162
+ *,
163
+ agent_source: str,
164
+ agent_config: dict,
165
+ runtime_start_command: str,
166
+ runtime_env: Optional[dict] = None,
167
+ watchdog_enabled: bool = True,
168
+ ) -> str:
169
+ """Bash executed on the instance right after the container comes up.
170
+
171
+ Order matters: the watchdog starts FIRST so an instance whose model server
172
+ fails to boot is still protected by idle/max_lifetime rules.
173
+ """
174
+ lines = [
175
+ "#!/bin/bash",
176
+ "# Generated by gpu4agents",
177
+ "set -u",
178
+ # mkdir first: a failed `exec` redirect would kill a non-interactive shell.
179
+ "mkdir -p /etc/jambu /var/lib/jambu /var/log/jambu /var/run/jambu /opt/jambu",
180
+ f"exec >> {ONSTART_LOG_PATH} 2>&1",
181
+ "date -u +'[%Y-%m-%dT%H:%M:%SZ] jambu onstart begin'",
182
+ ]
183
+
184
+ for key, value in (runtime_env or {}).items():
185
+ lines.append(f"export {key}={_shell_quote(str(value))}")
186
+ lines.append(f"echo {_shell_quote(f'{key}={value}')} >> /etc/jambu/runtime.env")
187
+
188
+ if watchdog_enabled:
189
+ # Config and agent both travel deflated; the config carries the token,
190
+ # so it is written under a 077 umask.
191
+ decode = (
192
+ "import base64,os,zlib;os.umask(0o77);"
193
+ f"[open(p,'wb').write(zlib.decompress(base64.b64decode(open(p+'.b64','rb').read())))"
194
+ f" for p in ({CONFIG_REMOTE_PATH!r},{AGENT_REMOTE_PATH!r})]"
195
+ )
196
+ config_json = json.dumps(agent_config, separators=(",", ":"))
197
+ # Killing the supervisor pid must still take the watchdog down with it:
198
+ # the agent runs in the background so `wait` lets the TERM trap fire.
199
+ supervisor = (
200
+ "child=; "
201
+ "trap '[ -n \"$child\" ] && kill \"$child\" 2>/dev/null; exit 0' TERM INT; "
202
+ "while true; do "
203
+ f'"$PYBIN" -u {AGENT_REMOTE_PATH} >> {WATCHDOG_LOG_PATH} 2>&1 & '
204
+ "child=$!; "
205
+ 'wait "$child"; '
206
+ "code=$?; "
207
+ "date -u +\"[%Y-%m-%dT%H:%M:%SZ] jambu watchdog exited code=$code, respawning\" "
208
+ f">> {WATCHDOG_LOG_PATH}; "
209
+ f"sleep {SUPERVISOR_RESPAWN_DELAY_S}; "
210
+ "done"
211
+ )
212
+ lines += [
213
+ "",
214
+ "# --- lifecycle watchdog (survives local CLI death) ---",
215
+ "PYBIN=$(command -v python3 || command -v python)",
216
+ 'if [ -z "$PYBIN" ]; then',
217
+ ' echo "jambu: no python interpreter in this image; watchdog NOT installed"',
218
+ "else",
219
+ f" (umask 077; echo {_b64_gz_block(config_json, width=0)} > {CONFIG_REMOTE_PATH}.b64)",
220
+ f" cat > {AGENT_REMOTE_PATH}.b64 <<'JAMBU_AGENT_EOF'",
221
+ _b64_gz_block(agent_source),
222
+ "JAMBU_AGENT_EOF",
223
+ f' "$PYBIN" -c {_shell_quote(decode)}',
224
+ f" rm -f {CONFIG_REMOTE_PATH}.b64 {AGENT_REMOTE_PATH}.b64",
225
+ f" chmod 600 {CONFIG_REMOTE_PATH}",
226
+ f" chmod 700 {AGENT_REMOTE_PATH}",
227
+ # One id per container start: the agent tells a restart (new
228
+ # session, re-arm the guard) from a respawn (same session, keep state).
229
+ " export JAMBU_SESSION_STARTED_AT=$(date +%s)",
230
+ " export PYBIN",
231
+ # Supervisor: a crashed watchdog must not leave the GPU unguarded.
232
+ f" nohup bash -c {_shell_quote(supervisor)} > /dev/null 2>&1 &",
233
+ f" echo $! > {SUPERVISOR_PID_PATH}",
234
+ f' echo "jambu: watchdog supervisor started pid $(cat {SUPERVISOR_PID_PATH})"',
235
+ "fi",
236
+ ]
237
+
238
+ lines += [
239
+ "",
240
+ "# --- model runtime ---",
241
+ runtime_start_command,
242
+ "date -u +'[%Y-%m-%dT%H:%M:%SZ] jambu onstart done'",
243
+ ]
244
+ return "\n".join(lines) + "\n"
245
+
246
+
247
+ def _shell_quote(value: str) -> str:
248
+ return "'" + value.replace("'", "'\"'\"'") + "'"
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.5
2
+ Name: gpu4agents
3
+ Version: 0.5.0
4
+ Summary: GPU for Agents: your coding agent rents the GPU it needs, on its own. You pay only while it works.
5
+ Project-URL: Homepage, https://gpu4agents.jambu.ai
6
+ Project-URL: Documentation, https://github.com/jambuai/gpu4agents/tree/main/docs
7
+ Project-URL: Repository, https://github.com/jambuai/gpu4agents
8
+ Project-URL: Issues, https://github.com/jambuai/gpu4agents/issues
9
+ Project-URL: Changelog, https://github.com/jambuai/gpu4agents/blob/main/CHANGELOG.md
10
+ Project-URL: Author, https://www.linkedin.com/in/joaogabriellima
11
+ Author: Jambu.ai
12
+ Author-email: João Gabriel Lima <joao.gabriel@jambu.ai>
13
+ License: MIT
14
+ License-File: LICENSE
15
+ Keywords: agents,claude-code,cost,cursor,gpu,inference,llm,mcp,vast-ai,vllm
16
+ Classifier: Development Status :: 4 - Beta
17
+ Classifier: Environment :: Console
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Operating System :: MacOS
22
+ Classifier: Operating System :: POSIX :: Linux
23
+ Classifier: Programming Language :: Python :: 3
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Classifier: Programming Language :: Python :: 3.12
27
+ Classifier: Programming Language :: Python :: 3.13
28
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
29
+ Classifier: Topic :: System :: Distributed Computing
30
+ Requires-Python: >=3.10
31
+ Requires-Dist: httpx>=0.27.0
32
+ Requires-Dist: pydantic>=2.6.0
33
+ Requires-Dist: pyyaml>=6.0.1
34
+ Requires-Dist: rich>=13.7.0
35
+ Requires-Dist: typer>=0.12.0
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
38
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
39
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
40
+ Description-Content-Type: text/markdown
41
+
42
+ <p align="center">
43
+ <a href="https://gpu4agents.jambu.ai">
44
+ <img src="docs/assets/banner.png" alt="GPU for Agents: your agent rents the GPU it needs, on its own. You pay only while it works." width="100%">
45
+ </a>
46
+ </p>
47
+
48
+ <p align="center">
49
+ <a href="https://pypi.org/project/gpu4agents/"><img src="https://img.shields.io/pypi/v/gpu4agents?color=5CBF3A&label=pypi" alt="PyPI"></a>
50
+ <a href="https://pypi.org/project/gpu4agents/"><img src="https://img.shields.io/pypi/pyversions/gpu4agents?color=5CBF3A" alt="Python versions"></a>
51
+ <a href="https://github.com/jambuai/gpu4agents/actions/workflows/ci.yml"><img src="https://github.com/jambuai/gpu4agents/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
52
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-5CBF3A" alt="MIT license"></a>
53
+ </p>
54
+
55
+ <p align="center">
56
+ <a href="https://gpu4agents.jambu.ai">Website</a> ·
57
+ <a href="https://gpu4agents.jambu.ai/#video">1-minute video</a> ·
58
+ <a href="docs/AGENTS.md">Agents guide</a> ·
59
+ <a href="https://github.com/jambuai/gpu4agents/wiki">Wiki</a> ·
60
+ <a href="CHANGELOG.md">Changelog</a>
61
+ </p>
62
+
63
+ # GPU for Agents
64
+
65
+ **Your agent rents the GPU it needs, on its own.**
66
+ **You pay only while it works: we watch every machine and shut down the idle ones.**
67
+
68
+ Ask Claude Code, Cursor or any MCP client to "compare Qwen 7B and Llama 8B on these 50 prompts". The agent finds a GPU under your budget, serves the model behind an OpenAI-compatible API with vLLM, and runs the experiment. A watchdog runs on the machine itself, so when nothing uses it for `idle_timeout` (15 minutes by default) it shuts down, even if the agent forgot, the chat closed or your laptop is asleep.
69
+
70
+ - **Self-service GPUs for agents.** A skill and local MCP tools (`gpu_offers`, `gpu_setup`, `gpu_run`, `gpu_status`, `gpu_destroy`, ...) give the agent the whole lifecycle. The skill tells it to show you the price and ask before renting.
71
+ - **Billing that ends when the work does.** Idle timeout, maximum lifetime, hourly and session budgets, and a sweep that cleans up anything left behind.
72
+ - **Any app, any language.** `gpu --json setup` returns `base_url`, `api_key` and `model` for any OpenAI SDK.
73
+
74
+ Vast.ai is the first provider; another provider is a new adapter, and the lifecycle rule stays the same.
75
+
76
+ ## Quickstart: give your agent a GPU
77
+
78
+ ```bash
79
+ pipx install gpu4agents # or: uv tool install gpu4agents
80
+ cd your-project
81
+ echo "VAST_API_KEY=..." >> .env # or ~/.gpu/credentials; never in jambu.yaml
82
+ gpu agent install # Claude Code; -t cursor, -t desktop, --global
83
+ ```
84
+
85
+ Then ask the agent for an experiment. See [Letting a coding agent rent GPUs](docs/AGENTS.md).
86
+
87
+ ## Quickstart: from a shell or an app
88
+
89
+ ```bash
90
+ gpu init --model Qwen/Qwen2.5-7B-Instruct
91
+ gpu validate
92
+ gpu offers # see prices, rent nothing
93
+ gpu setup # rent, boot vLLM, wait until the model answers
94
+ gpu run python experiment.py # OPENAI_BASE_URL / OPENAI_API_KEY are set for the job
95
+ gpu destroy # or walk away: the idle timeout does it
96
+ ```
97
+
98
+ From an application in any language, `gpu --json setup` prints the endpoint as JSON. See [Integrating into an application](docs/INTEGRATION.md), with a ready TypeScript client.
99
+
100
+ ## Declare the limits
101
+
102
+ ```yaml
103
+ # jambu.yaml (only the gpu_runtime key is read, so other Jambu tools can share the file)
104
+ gpu_runtime:
105
+ provider: {name: vast}
106
+ model_profile: qwythos-9b
107
+ lifecycle:
108
+ idle_timeout: 15m # the watchdog on the machine stops it
109
+ max_lifetime: 6h # a hard ceiling, busy or not
110
+ budget:
111
+ max_hourly_cost_usd: 0.60 # offers above this are never rented
112
+ max_session_cost_usd: 5.00
113
+ health:
114
+ pull_stall_timeout: 10m # a host whose image pull stalls is replaced
115
+ ```
116
+
117
+ A full example is [`jambu.example.yaml`](jambu.example.yaml). As a last line of defense, `gpu ls` shows every machine billing in the account and `gpu sweep --install-timer` guards every project on the machine and cleans up orphans. See [Keeping the account clean](docs/USAGE.md#keeping-the-account-clean).
118
+
119
+ The API key is read from the environment, a project `.env`, or `~/.gpu/credentials`. It never goes in the manifest, and the agent never sees it.
120
+
121
+ ## Docs
122
+
123
+ - [Letting a coding agent rent GPUs (Claude Code, Cursor, Claude Desktop)](docs/AGENTS.md)
124
+ - [Integrating into an application (any language)](docs/INTEGRATION.md)
125
+ - [Commands, workloads, and agents](docs/USAGE.md)
126
+ - [Every config field](docs/CONFIG.md)
127
+ - [Choosing a model](docs/CHOOSING_A_MODEL.md)
128
+ - [How shutdown works](docs/LIFECYCLE.md)
129
+ - [Adding a provider](docs/ADDING_A_PROVIDER.md)
130
+
131
+ ## Coming from `jambu-gpu`
132
+
133
+ The package was called `jambu-gpu` until 0.4.1. Same code, same `gpu` command, same `jambu.yaml`, same machines:
134
+
135
+ ```bash
136
+ pipx uninstall jambu-gpu && pipx install gpu4agents
137
+ ```
138
+
139
+ Sweep timers installed by `jambu-gpu` keep working; `gpu sweep --install-timer` rewrites them for the new module.
140
+
141
+ ## Contributing
142
+
143
+ Issues and pull requests are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md). Report security issues privately, as described in [SECURITY.md](SECURITY.md).
144
+
145
+ ## Author
146
+
147
+ Created by [João Gabriel Lima](https://www.linkedin.com/in/joaogabriellima) at [Jambu.ai](https://jambu.ai).
148
+
149
+ ## License
150
+
151
+ [MIT](LICENSE).
152
+
153
+ <p align="center">
154
+ <a href="https://jambu.ai">
155
+ <img src="docs/assets/jambu-logo.jpg" alt="Jambu.ai — Applied Intelligence Lab" width="240">
156
+ </a>
157
+ </p>
@@ -0,0 +1,59 @@
1
+ gpu4agents/__init__.py,sha256=0IDRXmAi8yT3vmS-RiYskc0oSuxjWjm26MBcWvXsfBw,135
2
+ gpu4agents/__main__.py,sha256=dBCaXiNWd2Tv9A9tb_B9kJG2OOY-b5FpWYwRyV1yQso,66
3
+ gpu4agents/agent/__init__.py,sha256=cfB1rx-9w3XfuPig-2Kl5LA_Vpbm-y3Dz1v7EmQ-RzE,87
4
+ gpu4agents/agent/install.py,sha256=57qHdxoVC5wzVwfIStbZPfNbaY_pKhZFbBQK69Civx0,7228
5
+ gpu4agents/agent/jobs.py,sha256=WZ9TpbD_ULT_rk58FSo5jDUfdyz2QGuqrj44ZmyfCBk,7342
6
+ gpu4agents/agent/mcp.py,sha256=-cBefHoowRJC5WV9jUpH2hJM6HYZYXTrjcQj_Jax1_0,27735
7
+ gpu4agents/agent/skill/SKILL.md,sha256=7FFFWzC6KrVTuW99yclv4Bj1pUGdGv-h0vYQjX5wGtY,6050
8
+ gpu4agents/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ gpu4agents/cli/_common.py,sha256=G8lzmHOX7v3jIJe_JvSOqXgO-t9vSC3vz1ScMCcXzLQ,3807
10
+ gpu4agents/cli/account.py,sha256=SHmRPnbhGSYz92ma3BDzFS44NXYYifsJo2hsWcD4Mks,13509
11
+ gpu4agents/cli/agent.py,sha256=54VOLuKRYUDjcayD5wkC1ohEltNIjg829KnE5WkqR0A,2236
12
+ gpu4agents/cli/inspect.py,sha256=Jldc5FAZEuAdZovNvESxjqJxmNEMQ5SUkHbOXzO8EeI,8086
13
+ gpu4agents/cli/lifecycle.py,sha256=zmgkUJNK9DSdzTumxDKW-gwyiIAjTaUOM00U8kpZy_M,3862
14
+ gpu4agents/cli/main.py,sha256=P6cqa910502WErIZHCedfT4WbaFP3omM96vh6S3EQH4,5129
15
+ gpu4agents/cli/providers.py,sha256=vDR5SgxsMVLWpZsdSLKuJy8qOUxv1M7-IHIJUCnAleI,3058
16
+ gpu4agents/cli/run.py,sha256=oFj0MGAb8I44VOf6ktT5niC8s8d4Fx0LAfRueeg64Bo,1271
17
+ gpu4agents/cli/setup.py,sha256=HGtTSeiSj0gnENXl6Nx6hVuGTMympTXe0cOaX3Io0D8,5487
18
+ gpu4agents/cli/status.py,sha256=VHnad5--8Lnhlq9nUSxn5LKV_gVmK42E9oM947UJiCw,7430
19
+ gpu4agents/cli/timer.py,sha256=FQa2d3tpyvjcOFJ7gUVjJU8POawiPSlEhzZmmvSZ-SU,4846
20
+ gpu4agents/cli/validate.py,sha256=9DFh8TLIcvPIct5FQk78VPfW29PMqkOcij8N_F8yXHs,2081
21
+ gpu4agents/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ gpu4agents/core/beacon.py,sha256=a5hsHEln8Y5jKgPTNmBZOysBzV0kceHG5KWZxDDwy7w,4818
23
+ gpu4agents/core/config.py,sha256=6OTTGs3MO9ZFqagTDGjSj33m6UhxxqSey2qlsVYJLao,22624
24
+ gpu4agents/core/credentials.py,sha256=o_YCynH5B--5ZL5eUTnoQe8zs_I1uDcvaygL-U24r04,3186
25
+ gpu4agents/core/durations.py,sha256=4-Gq--HNOBGXLLWQHssC08gkQwQjT_3oBHD4ootHKxs,1645
26
+ gpu4agents/core/engine.py,sha256=8Vme7QPnfMPC-2UuaHMEP85cuCDK2yW0dxYjvo8bcXM,57317
27
+ gpu4agents/core/errors.py,sha256=MqQI4he_xyotI1wBzavVXTK5KO5L-qWDmmIR0mhsOHU,2446
28
+ gpu4agents/core/events.py,sha256=b8OSRMf01VyXTyJxoDJ-kMTL9KEsKufTLluR0akJq_E,4092
29
+ gpu4agents/core/execution.py,sha256=6cXL-QbYg7rDeIpMwgTl9uAUh9LhEwtfyST1l_QfADk,5689
30
+ gpu4agents/core/health.py,sha256=nbd4JNvNF7-Lpd58Ce_48J7A5Sob3gek6ihv9Q36nkk,1909
31
+ gpu4agents/core/hosts.py,sha256=WhdckKl_Lohckov_T-h53kTx4kN-29dRFZyT74bmviM,2107
32
+ gpu4agents/core/model_inspect.py,sha256=vb22jQ0NaSOsKrKWE4BlxXgbh26_qMhRMsAHYLVofCA,15615
33
+ gpu4agents/core/models.py,sha256=1zJoIZAX63TEhXzjIbFCe1tYcWuExmnrjbEw-AUPNfA,9181
34
+ gpu4agents/core/paths.py,sha256=xvOyVW9WVdFpT8vrSCEnPPtlMK6BnB0AXyvHA5knffE,1416
35
+ gpu4agents/core/policy.py,sha256=F3r5UwJEQD_6coUgwd2hWqO1kDXlCLbVoXQci-bxqg0,9722
36
+ gpu4agents/core/state.py,sha256=CmvkUPUwfATPB4iQWeoOp7NjCWWIkdcd5E4FPjlhFOw,15798
37
+ gpu4agents/core/sweep.py,sha256=F8i4n7Ix5JVmA3rFxAjUuhJAL_OI4SuPkwlj31tUfjE,17325
38
+ gpu4agents/core/tool_parsers.py,sha256=zqaVJ0-m0H3B9gEhhe3-gWm7nhpwp9OBMAAsBx-Odu8,2475
39
+ gpu4agents/providers/__init__.py,sha256=qM_BUMeabdamPdHTQHcSfp8okfjidkGhj2y_YUpBbMg,168
40
+ gpu4agents/providers/base.py,sha256=GVDm2JtbL0mfd223KsAHeS-4o76f9U-afP9e7VEsGx0,5203
41
+ gpu4agents/providers/registry.py,sha256=tj63zPcEPmUxVLqHFiFIesS_rWes0B45mOwLmjilanE,2032
42
+ gpu4agents/providers/vast/__init__.py,sha256=LPaQrruQaRu59u7IMrOkx2eNb_176vcN9DGvevL8E4g,63
43
+ gpu4agents/providers/vast/client.py,sha256=kHxqSsYVqceaUtvS0yYNl3gOT35EiZhn5qYJ07AFFQE,10186
44
+ gpu4agents/providers/vast/config.py,sha256=a4UYYDJFhZGpSsqPoMyoWCokqAhQ98nz5b8VsqYbrd4,1959
45
+ gpu4agents/providers/vast/mapper.py,sha256=NtFLvLxH-j1ok3rPG8ZRo4u_nrZj7bXebCjpp0EOtEk,11423
46
+ gpu4agents/providers/vast/provider.py,sha256=sqJ8kJPxqzFM_4BzomiPdvnrYMO98fTch5WQ4XIkj0c,16919
47
+ gpu4agents/runtime/__init__.py,sha256=ncpE8jTc_dX4cVlO3IBKg5vDv-n1TREKj4aksisqTDM,218
48
+ gpu4agents/runtime/base.py,sha256=SUw2VoWuFIahtFUy8RK_thIrFRdIvPDXoxmkJFEApvc,6057
49
+ gpu4agents/runtime/vllm.py,sha256=peVZya8LYtboizUN5hUKDq_cKtsMNw6tab0hIsRqLBw,11929
50
+ gpu4agents/watchdog/__init__.py,sha256=79yCptDKSE8dA-PowfQzcxrNaK6eEqhe_WDTi9BR_Fk,154
51
+ gpu4agents/watchdog/agent_body.py,sha256=B_olBJlogwIyGjroGorK93qwdu_fUj56CkigTBPiVAE,33367
52
+ gpu4agents/watchdog/builder.py,sha256=9SmkQg0wdkqj2DKnms6-CbOwdIkHIDhKn7P_sJnh5os,8997
53
+ jambu_gpu/__init__.py,sha256=lyDgFBShjnhy-o0X92miaFUD7iyZHxdhkUQGp-xHlJo,285
54
+ jambu_gpu/__main__.py,sha256=eP5QKo2yEL9eW1hnPVemmnioIASlkJ1GG6UVbIt3Dww,76
55
+ gpu4agents-0.5.0.dist-info/METADATA,sha256=26UBx7jDHvDaQ7wkvEXxVY2BAAPE_OOE-ZhuYH3iRjc,7330
56
+ gpu4agents-0.5.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
57
+ gpu4agents-0.5.0.dist-info/entry_points.txt,sha256=iBCjwTEp4MsctV-KL63DldRnKmZ-pMV-8HNxvVG52rI,49
58
+ gpu4agents-0.5.0.dist-info/licenses/LICENSE,sha256=7ofvt29ghOnzKapRr48K5JoCiQNnA5AcGFu6fSrtmSQ,1088
59
+ gpu4agents-0.5.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ gpu = gpu4agents.cli.main:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jambu.ai and João Gabriel Lima
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
jambu_gpu/__init__.py ADDED
@@ -0,0 +1,9 @@
1
+ """Compatibility alias: this package was renamed to gpu4agents in 0.5.0.
2
+
3
+ Kept so sweep timers installed by jambu-gpu (``python -m jambu_gpu sweep --apply``)
4
+ keep working after an upgrade. New code imports gpu4agents.
5
+ """
6
+
7
+ from gpu4agents import __version__
8
+
9
+ __all__ = ["__version__"]
jambu_gpu/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from gpu4agents.cli.main import main
2
+
3
+ if __name__ == "__main__":
4
+ main()