hexel 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.
hexel-0.1.0/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
hexel-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hexel Studio
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.
hexel-0.1.0/Makefile ADDED
@@ -0,0 +1,47 @@
1
+ .PHONY: generate sync-specs install dev test clean
2
+
3
+ VENV := .venv
4
+ PYTHON := $(VENV)/bin/python
5
+ COMPUTE_REPO := $(HOME)/compute
6
+ REGISTRY_REPO := $(HOME)/agent-registry
7
+
8
+ # Generate SDK from specs
9
+ generate:
10
+ $(PYTHON) generator/generate.py
11
+
12
+ # Sync specs from product repos then generate
13
+ sync-specs:
14
+ @echo "→ Syncing compute spec..."
15
+ cd $(COMPUTE_REPO)/compute-controller && make swagger
16
+ cp $(COMPUTE_REPO)/specs/json/compute-api.json specs/
17
+ @echo "→ Syncing agentd spec..."
18
+ cp $(COMPUTE_REPO)/specs/json/agentd-api.json specs/
19
+ @echo "→ Syncing registry spec..."
20
+ cp $(REGISTRY_REPO)/specs/json/agent-registry-api.json specs/
21
+ @echo "✓ Specs synced"
22
+ $(MAKE) generate
23
+
24
+ # Setup venv and install deps
25
+ install:
26
+ uv venv
27
+ $(VENV)/bin/pip install -e ".[dev]"
28
+
29
+ # Install dev deps (jinja2 for generator)
30
+ dev:
31
+ $(VENV)/bin/pip install jinja2
32
+
33
+ # Run tests
34
+ test:
35
+ $(PYTHON) -m pytest tests/ -v
36
+
37
+ # Verify imports work
38
+ check:
39
+ $(PYTHON) -c "from hexel import Hexel; print('✅ hexel', __import__('hexel').__version__)"
40
+
41
+ # Clean generated files
42
+ clean:
43
+ rm -rf hexel/compute/_*.py hexel/compute/types.py hexel/compute/__init__.py
44
+ rm -f generator/ir.json
45
+
46
+ # Full rebuild: sync specs + generate + check
47
+ all: sync-specs check
hexel-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,167 @@
1
+ Metadata-Version: 2.4
2
+ Name: hexel
3
+ Version: 0.1.0
4
+ Summary: Hexel Studio SDK — deploy and run AI agents
5
+ Project-URL: Homepage, https://hexelstudio.com
6
+ Project-URL: Documentation, https://docs.hexelstudio.com
7
+ Project-URL: Repository, https://github.com/hexelstudio/python-sdk
8
+ Project-URL: Changelog, https://docs.hexelstudio.com/changelog
9
+ Author-email: Hexel Studio <support@hexelstudio.com>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: agents,ai,code-execution,compute,hexel,sandbox
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: websockets>=12.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: jinja2; extra == 'dev'
28
+ Requires-Dist: pytest; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Hexel Python SDK
32
+
33
+ The official Python SDK for [Hexel Studio](https://hexelstudio.com) — build, deploy, and run AI agents.
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install hexel
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ```python
44
+ from hexel import Hexel
45
+
46
+ client = Hexel(api_key="your_api_key")
47
+
48
+ # Create a sandbox and execute code
49
+ sandbox = client.compute.sandbox.create(tier="standard")
50
+ print(sandbox) # {"vm_id": "...", "state": "allocated", ...}
51
+
52
+ # Register an agent
53
+ agent = client.compute.agent.register(
54
+ name="my-agent",
55
+ image="ghcr.io/org/agent:v1",
56
+ capabilities=["chat", "streaming"],
57
+ )
58
+
59
+ # Deploy an agent
60
+ instance = client.compute.instance.deploy(agent["id"], env={"MODEL": "gpt-4"})
61
+ print(instance["endpoint"]) # https://zeal-isle-a620.compute.hexelstudio.com
62
+ ```
63
+
64
+ ## Authentication
65
+
66
+ Two authentication methods are supported:
67
+
68
+ ```python
69
+ # API Key (recommended for development)
70
+ client = Hexel(api_key="studio_live_xxxx")
71
+
72
+ # OAuth Client Credentials (recommended for production)
73
+ client = Hexel(client_id="your_client_id", client_secret="your_client_secret")
74
+ ```
75
+
76
+ Both methods exchange credentials for a short-lived STS token automatically. Tokens are cached and refreshed transparently.
77
+
78
+ ## Sandboxes
79
+
80
+ Sandboxes are isolated execution environments allocated instantly.
81
+
82
+ ```python
83
+ # Create
84
+ sandbox = client.compute.sandbox.create(tier="standard")
85
+
86
+ # Execute code (HTTP)
87
+ result = client.compute.sandbox.execute(sandbox["vm_id"], code="print(1+1)", language="python")
88
+
89
+ # List
90
+ sandboxes = client.compute.sandbox.list()
91
+
92
+ # Renew TTL
93
+ client.compute.sandbox.renew(sandbox["vm_id"], ttl_seconds=3600)
94
+
95
+ # Release
96
+ client.compute.sandbox.release(sandbox["vm_id"], recycle=True)
97
+
98
+ # Delete
99
+ client.compute.sandbox.delete(sandbox["vm_id"])
100
+ ```
101
+
102
+ ## Agents
103
+
104
+ Agents are Docker images registered in the Hexel registry.
105
+
106
+ ```python
107
+ # Register
108
+ agent = client.compute.agent.register(
109
+ name="fraud-detector",
110
+ image="ghcr.io/org/fraud-agent:v1",
111
+ capabilities=["fraud-detection"],
112
+ )
113
+
114
+ # List
115
+ agents = client.compute.agent.list()
116
+
117
+ # Get
118
+ agent = client.compute.agent.get("agent-id")
119
+
120
+ # Search
121
+ results = client.compute.agent.search(q="fraud")
122
+
123
+ # Delete
124
+ client.compute.agent.delete("agent-id")
125
+ ```
126
+
127
+ ## Instances
128
+
129
+ Instances are running deployments of agents with permanent endpoints.
130
+
131
+ ```python
132
+ # Deploy
133
+ instance = client.compute.instance.deploy("agent-id", env={"MODEL": "gpt-4"})
134
+
135
+ # List
136
+ instances = client.compute.instance.list()
137
+
138
+ # Get
139
+ instance = client.compute.instance.get("deployment-id")
140
+
141
+ # Stop
142
+ client.compute.instance.stop("deployment-id")
143
+
144
+ # Redeploy
145
+ client.compute.instance.redeploy("deployment-id")
146
+
147
+ # Delete
148
+ client.compute.instance.delete("deployment-id")
149
+ ```
150
+
151
+ ## Configuration
152
+
153
+ ```python
154
+ client = Hexel(
155
+ api_key="...",
156
+ )
157
+ ```
158
+
159
+ ## Requirements
160
+
161
+ - Python 3.10+
162
+ - `httpx` for HTTP
163
+ - `websockets` for WebSocket connections
164
+
165
+ ## License
166
+
167
+ MIT
hexel-0.1.0/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # Hexel Python SDK
2
+
3
+ The official Python SDK for [Hexel Studio](https://hexelstudio.com) — build, deploy, and run AI agents.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install hexel
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from hexel import Hexel
15
+
16
+ client = Hexel(api_key="your_api_key")
17
+
18
+ # Create a sandbox and execute code
19
+ sandbox = client.compute.sandbox.create(tier="standard")
20
+ print(sandbox) # {"vm_id": "...", "state": "allocated", ...}
21
+
22
+ # Register an agent
23
+ agent = client.compute.agent.register(
24
+ name="my-agent",
25
+ image="ghcr.io/org/agent:v1",
26
+ capabilities=["chat", "streaming"],
27
+ )
28
+
29
+ # Deploy an agent
30
+ instance = client.compute.instance.deploy(agent["id"], env={"MODEL": "gpt-4"})
31
+ print(instance["endpoint"]) # https://zeal-isle-a620.compute.hexelstudio.com
32
+ ```
33
+
34
+ ## Authentication
35
+
36
+ Two authentication methods are supported:
37
+
38
+ ```python
39
+ # API Key (recommended for development)
40
+ client = Hexel(api_key="studio_live_xxxx")
41
+
42
+ # OAuth Client Credentials (recommended for production)
43
+ client = Hexel(client_id="your_client_id", client_secret="your_client_secret")
44
+ ```
45
+
46
+ Both methods exchange credentials for a short-lived STS token automatically. Tokens are cached and refreshed transparently.
47
+
48
+ ## Sandboxes
49
+
50
+ Sandboxes are isolated execution environments allocated instantly.
51
+
52
+ ```python
53
+ # Create
54
+ sandbox = client.compute.sandbox.create(tier="standard")
55
+
56
+ # Execute code (HTTP)
57
+ result = client.compute.sandbox.execute(sandbox["vm_id"], code="print(1+1)", language="python")
58
+
59
+ # List
60
+ sandboxes = client.compute.sandbox.list()
61
+
62
+ # Renew TTL
63
+ client.compute.sandbox.renew(sandbox["vm_id"], ttl_seconds=3600)
64
+
65
+ # Release
66
+ client.compute.sandbox.release(sandbox["vm_id"], recycle=True)
67
+
68
+ # Delete
69
+ client.compute.sandbox.delete(sandbox["vm_id"])
70
+ ```
71
+
72
+ ## Agents
73
+
74
+ Agents are Docker images registered in the Hexel registry.
75
+
76
+ ```python
77
+ # Register
78
+ agent = client.compute.agent.register(
79
+ name="fraud-detector",
80
+ image="ghcr.io/org/fraud-agent:v1",
81
+ capabilities=["fraud-detection"],
82
+ )
83
+
84
+ # List
85
+ agents = client.compute.agent.list()
86
+
87
+ # Get
88
+ agent = client.compute.agent.get("agent-id")
89
+
90
+ # Search
91
+ results = client.compute.agent.search(q="fraud")
92
+
93
+ # Delete
94
+ client.compute.agent.delete("agent-id")
95
+ ```
96
+
97
+ ## Instances
98
+
99
+ Instances are running deployments of agents with permanent endpoints.
100
+
101
+ ```python
102
+ # Deploy
103
+ instance = client.compute.instance.deploy("agent-id", env={"MODEL": "gpt-4"})
104
+
105
+ # List
106
+ instances = client.compute.instance.list()
107
+
108
+ # Get
109
+ instance = client.compute.instance.get("deployment-id")
110
+
111
+ # Stop
112
+ client.compute.instance.stop("deployment-id")
113
+
114
+ # Redeploy
115
+ client.compute.instance.redeploy("deployment-id")
116
+
117
+ # Delete
118
+ client.compute.instance.delete("deployment-id")
119
+ ```
120
+
121
+ ## Configuration
122
+
123
+ ```python
124
+ client = Hexel(
125
+ api_key="...",
126
+ )
127
+ ```
128
+
129
+ ## Requirements
130
+
131
+ - Python 3.10+
132
+ - `httpx` for HTTP
133
+ - `websockets` for WebSocket connections
134
+
135
+ ## License
136
+
137
+ MIT
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Hexel SDK Generator
4
+
5
+ Reads OpenAPI specs + overrides → builds IR → generates Python SDK.
6
+
7
+ Usage:
8
+ python generator/generate.py
9
+ """
10
+ import json
11
+ import os
12
+ import sys
13
+ from pathlib import Path
14
+
15
+ from jinja2 import Environment, FileSystemLoader
16
+
17
+ from parser import build_from_files
18
+
19
+ SPECS_DIR = "specs"
20
+ OVERRIDES = "generator/overrides.json"
21
+ OUTPUT_DIR = "hexel/compute"
22
+ TEMPLATES_DIR = "generator/templates"
23
+
24
+ # Type mapping: OpenAPI → Python
25
+ TYPE_MAP = {
26
+ "string": "str",
27
+ "integer": "int",
28
+ "number": "float",
29
+ "boolean": "bool",
30
+ "object": "dict",
31
+ "any": "Any",
32
+ }
33
+
34
+
35
+ def python_type(t: str) -> str:
36
+ """Convert IR type to Python type annotation."""
37
+ if t.startswith("list["):
38
+ inner = t[5:-1]
39
+ return f"list[{python_type(inner)}]"
40
+ if t.startswith("dict["):
41
+ return t
42
+ return TYPE_MAP.get(t, t)
43
+
44
+
45
+ def to_class_name(service_name: str) -> str:
46
+ """sandbox → SandboxClient"""
47
+ return service_name.capitalize() + "Client"
48
+
49
+
50
+ def generate():
51
+ print("→ Parsing specs...")
52
+ ir = build_from_files(SPECS_DIR, OVERRIDES)
53
+
54
+ print(f" Services: {list(ir['services'].keys())}")
55
+ print(f" Types: {len(ir['types'])}")
56
+
57
+ # Setup Jinja
58
+ env = Environment(
59
+ loader=FileSystemLoader(TEMPLATES_DIR),
60
+ keep_trailing_newline=True,
61
+ trim_blocks=True,
62
+ lstrip_blocks=True,
63
+ )
64
+ env.filters["python_type"] = python_type
65
+
66
+ output = Path(OUTPUT_DIR)
67
+ output.mkdir(parents=True, exist_ok=True)
68
+
69
+ # Generate types.py
70
+ print("→ Generating types.py...")
71
+ types_tmpl = env.get_template("types.py.j2")
72
+ types_code = types_tmpl.render(types=ir["types"])
73
+ (output / "types.py").write_text(types_code)
74
+
75
+ # Generate service clients
76
+ service_tmpl = env.get_template("service.py.j2")
77
+ for service_name, service_def in ir["services"].items():
78
+ class_name = to_class_name(service_name)
79
+ has_ws = service_name in ir.get("websocket", {})
80
+
81
+ print(f"→ Generating _{service_name}.py ({class_name}, {len(service_def['methods'])} methods)...")
82
+ code = service_tmpl.render(
83
+ class_name=class_name,
84
+ description=service_def["description"],
85
+ methods=service_def["methods"],
86
+ has_ws=has_ws,
87
+ )
88
+ (output / f"_{service_name}.py").write_text(code)
89
+
90
+ # Generate __init__.py
91
+ print("→ Generating __init__.py...")
92
+ init_tmpl = env.get_template("compute_init.py.j2")
93
+ init_code = init_tmpl.render()
94
+ (output / "__init__.py").write_text(init_code)
95
+
96
+ # Write IR for debugging
97
+ ir_path = Path("generator/ir.json")
98
+ ir_path.write_text(json.dumps(ir, indent=2))
99
+ print(f"→ IR written to {ir_path}")
100
+
101
+ print(f"\n✅ Generated {len(ir['services'])} services + types in {OUTPUT_DIR}/")
102
+ print(" Files:")
103
+ for f in sorted(output.glob("*.py")):
104
+ lines = len(f.read_text().splitlines())
105
+ print(f" {f.name:20s} {lines:4d} lines")
106
+
107
+
108
+ if __name__ == "__main__":
109
+ os.chdir(Path(__file__).resolve().parent.parent)
110
+ generate()