superii-sdk 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.
@@ -0,0 +1,44 @@
1
+ # build output
2
+ dist/
3
+ # generated types
4
+ .astro/
5
+
6
+ # dependencies
7
+ node_modules/
8
+
9
+ # local Cloudflare deployment state
10
+ .wrangler/
11
+
12
+ # logs
13
+ npm-debug.log*
14
+ yarn-debug.log*
15
+ yarn-error.log*
16
+ pnpm-debug.log*
17
+
18
+ # Python bytecode
19
+ __pycache__/
20
+ *.py[cod]
21
+ .pytest_cache/
22
+ .ruff_cache/
23
+ .venv/
24
+
25
+ # Super ii Runtime local state (uploads and generated artifacts never enter Git)
26
+ runtime/data/
27
+ runtime/workspaces/
28
+ rust/target/
29
+
30
+
31
+ # environment variables
32
+ .env
33
+ .env.*
34
+ .dev.vars
35
+ !.env.example
36
+
37
+ # local visual QA captures (the written QA record remains tracked)
38
+ qa/evidence/
39
+
40
+ # macOS-specific files
41
+ .DS_Store
42
+
43
+ # jetbrains setting folder
44
+ .idea/
@@ -0,0 +1,13 @@
1
+ Modified MIT License
2
+
3
+ Copyright (c) 2026 Super ii
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
10
+
11
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
+
13
+ Our only modification part is that, if the Software (or any derivative works thereof) is used for any of your commercial products or services that have more than 1000 monthly active users, or more than 10000 US dollars (or equivalent in other currencies) in monthly revenue, you shall at all times prominently display "www.superii.site" on the user interface of such product or service.
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.5
2
+ Name: superii-sdk
3
+ Version: 0.1.0
4
+ Summary: Verified Super ii model acquisition, hardware planning and local inference
5
+ Project-URL: Homepage, https://superii.site
6
+ Project-URL: Source, https://github.com/smavgs/super-ii/tree/main/sdk/python
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Python: >=3.11
10
+ Requires-Dist: cryptography<51,>=46
11
+ Requires-Dist: filelock<4,>=3.19
12
+ Requires-Dist: httpx<0.29,>=0.28
13
+ Requires-Dist: psutil<8,>=7
14
+ Provides-Extra: mlx
15
+ Requires-Dist: mlx-lm<1,>=0.30; (sys_platform == 'darwin') and extra == 'mlx'
16
+ Provides-Extra: serve
17
+ Requires-Dist: fastapi<1,>=0.115; extra == 'serve'
18
+ Requires-Dist: mcp<2,>=1.20; extra == 'serve'
19
+ Requires-Dist: uvicorn<1,>=0.35; extra == 'serve'
20
+ Provides-Extra: test
21
+ Requires-Dist: fastapi<1,>=0.115; extra == 'test'
22
+ Requires-Dist: mcp<2,>=1.20; extra == 'test'
23
+ Requires-Dist: pytest<10,>=9; extra == 'test'
24
+ Requires-Dist: ruff<1,>=0.16; extra == 'test'
25
+ Provides-Extra: transformers
26
+ Requires-Dist: accelerate<2,>=1.10; extra == 'transformers'
27
+ Requires-Dist: safetensors<1,>=0.6; extra == 'transformers'
28
+ Requires-Dist: torch<3,>=2.8; extra == 'transformers'
29
+ Requires-Dist: transformers<6,>=5; extra == 'transformers'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Super ii Python SDK
33
+
34
+ Install the package (Python 3.11 or newer):
35
+
36
+ ```sh
37
+ python -m pip install superii-sdk
38
+ ```
39
+
40
+ The distribution is named `superii-sdk`; the import and CLI are named `superii`.
41
+ For a source checkout, use `python -m pip install ./sdk/python` instead.
42
+
43
+ ```python
44
+ import superii
45
+
46
+ print(superii.hardware()) # stays on this machine
47
+ print(superii.inspect("owner/model")) # metadata, immutable files and evidence
48
+ print(superii.plan("owner/model")) # estimates and explains before loading
49
+ with superii.load("owner/model") as model:
50
+ print(model.generate("Hello", max_tokens=128))
51
+ ```
52
+
53
+ The catalogue remains intentionally empty before creator submissions. The
54
+ example repository is a placeholder, not a seeded or downloadable model.
55
+
56
+ `load` resolves one published commit, plans against available memory, downloads
57
+ only its selected files, verifies every SHA-256, checks memory again and invokes
58
+ an installed runtime. Pass `revision="<full 64-character commit>"` for reproducible
59
+ notebooks, applications, training inputs and CI. `pull` returns a `Snapshot` with
60
+ its path and manifest; `verify(snapshot)` rechecks bytes. `await superii.apull(...)`
61
+ and `Client.prefetch(...)` support asynchronous/background acquisition.
62
+
63
+ Install llama.cpp's `llama-server` from its official distribution for GGUF.
64
+ Optional extras `superii-sdk[mlx]`, `superii-sdk[transformers]` and
65
+ `superii-sdk[serve]` add those integrations;
66
+ install vLLM using its hardware-specific official instructions. Nothing installs
67
+ or recompiles a backend behind the user's back. The initial planner supports
68
+ single-file GGUF and known text architectures with safetensors. Unsupported
69
+ architectures, custom Python, split GGUF and ambiguous conversions fail with a
70
+ reason. The vLLM and Transformers offline adapters currently return a complete
71
+ response rather than token streaming.
72
+
73
+ Memory estimates include OS headroom and context overhead, but are not a zero-OOM
74
+ guarantee. Existing smaller or quantized artifacts are preferred to inventing a
75
+ conversion. GPU support must be present in the installed runtime; compatibility
76
+ metadata is not a benchmark. `lazy_weights=True` enables the installed MLX
77
+ loader's lazy evaluation of already-verified local weights; it does not execute
78
+ partially downloaded weights.
79
+
80
+ Downloads use strict ranges, resume partial chunks, verify the final file and
81
+ deduplicate content within each authenticated cache. Redirects cannot forward
82
+ credentials; private content uses a separate credential-scoped cache. Set
83
+ `SUPERII_TOKEN` to an existing scoped token with `repository:read` to access an
84
+ authorized private published release. Every new pull rechecks canonical access,
85
+ even when bytes are cached. Files already intentionally downloaded by their
86
+ authorized owner remain local; revocation cannot erase an owner's copies.
87
+
88
+ ```python
89
+ with superii.load("owner/model") as model:
90
+ model.serve(port=8765, token=your_random_local_token) # loopback OpenAI text API
91
+ # Or model.serve_mcp() for a stdio MCP inference tool.
92
+ ```
93
+
94
+ The OpenAI endpoint requires a token and rejects browser origins. It implements
95
+ non-streaming text completions and chat completions; it does not claim full
96
+ OpenAI API parity. MCP exposes one inference tool and does not itself configure
97
+ an agent's model provider. Repository content and model output remain untrusted.
98
+
99
+ An optional explicit `Client(peers=(Peer("https://cache.example", peer_token),))`
100
+ can use a peer cache. No discovery or LAN broadcasts occur. Private artifacts
101
+ always bypass peers. `superii.serving.create_cache_app` serves already-cached
102
+ public hashes only, after fresh canonical visibility checks. Deploy that optional
103
+ service with TLS and a separate strong peer credential; otherwise leave peers
104
+ unset. Outages, missing data and corrupted peer bytes fall back to the origin.
105
+
106
+ Canonical manifests are hashes, not publisher identity proofs. New automatic
107
+ publication also returns an Ed25519 policy attestation; verification and key
108
+ pinning are documented with the publication service. Historical releases retain
109
+ their historical evidence and are not silently relabeled.
110
+
111
+ ## Measurements and acquisition research
112
+
113
+ `superii benchmark owner/model "Hello" --max-tokens 128` records first output,
114
+ generation time, approximate tokens per second, sampled process-tree peak RSS
115
+ and bytes acquired before inference. Batch adapters label first-output time
116
+ separately from token-streaming TTFT. RSS does not measure all GPU allocations.
117
+ Run cold and warm cache trials separately; the tool does not clear the OS cache.
118
+
119
+ `superii.experiments.tensor_ranges(snapshot)` indexes verified safetensors, and
120
+ `iter_tensor_bytes(snapshot, prefix="model.layers.0.")` performs bounded mmap
121
+ reads for layer or expert experiments. These are tested access primitives;
122
+ arbitrary models do not yet execute with partial weights. All files must pass
123
+ full verification first. Quantization/conversion, layer scheduling and MoE
124
+ expert selection require an architecture-specific implementation and benchmark.
125
+
126
+ Optional remote warm-start is explicit at each remote request:
127
+
128
+ ```python
129
+ from superii.remote import RemoteModel
130
+
131
+ # This call sends the prompt to your chosen provider. Use its separate token.
132
+ # Local pull/load may run concurrently in your application's executor.
133
+ with RemoteModel("https://your-provider.example", "model-id", token=provider_token) as remote:
134
+ answer = remote.generate("Hello")
135
+ # Switch to your completed local Model for later requests when you choose.
136
+ ```
137
+
138
+ This adapter implements the provider's non-streaming `/v1/completions` contract.
139
+ It never reuses Super ii credentials, follows redirects, silently falls back to
140
+ remote execution, or asserts that remote and local model outputs are identical.
141
+
142
+ Sources: [llama.cpp server](https://github.com/ggml-org/llama.cpp/tree/master/tools/server),
143
+ [MLX LM](https://github.com/ml-explore/mlx-lm),
144
+ [vLLM](https://docs.vllm.ai/en/latest/),
145
+ [safetensors](https://huggingface.co/docs/safetensors/),
146
+ [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).
@@ -0,0 +1,115 @@
1
+ # Super ii Python SDK
2
+
3
+ Install the package (Python 3.11 or newer):
4
+
5
+ ```sh
6
+ python -m pip install superii-sdk
7
+ ```
8
+
9
+ The distribution is named `superii-sdk`; the import and CLI are named `superii`.
10
+ For a source checkout, use `python -m pip install ./sdk/python` instead.
11
+
12
+ ```python
13
+ import superii
14
+
15
+ print(superii.hardware()) # stays on this machine
16
+ print(superii.inspect("owner/model")) # metadata, immutable files and evidence
17
+ print(superii.plan("owner/model")) # estimates and explains before loading
18
+ with superii.load("owner/model") as model:
19
+ print(model.generate("Hello", max_tokens=128))
20
+ ```
21
+
22
+ The catalogue remains intentionally empty before creator submissions. The
23
+ example repository is a placeholder, not a seeded or downloadable model.
24
+
25
+ `load` resolves one published commit, plans against available memory, downloads
26
+ only its selected files, verifies every SHA-256, checks memory again and invokes
27
+ an installed runtime. Pass `revision="<full 64-character commit>"` for reproducible
28
+ notebooks, applications, training inputs and CI. `pull` returns a `Snapshot` with
29
+ its path and manifest; `verify(snapshot)` rechecks bytes. `await superii.apull(...)`
30
+ and `Client.prefetch(...)` support asynchronous/background acquisition.
31
+
32
+ Install llama.cpp's `llama-server` from its official distribution for GGUF.
33
+ Optional extras `superii-sdk[mlx]`, `superii-sdk[transformers]` and
34
+ `superii-sdk[serve]` add those integrations;
35
+ install vLLM using its hardware-specific official instructions. Nothing installs
36
+ or recompiles a backend behind the user's back. The initial planner supports
37
+ single-file GGUF and known text architectures with safetensors. Unsupported
38
+ architectures, custom Python, split GGUF and ambiguous conversions fail with a
39
+ reason. The vLLM and Transformers offline adapters currently return a complete
40
+ response rather than token streaming.
41
+
42
+ Memory estimates include OS headroom and context overhead, but are not a zero-OOM
43
+ guarantee. Existing smaller or quantized artifacts are preferred to inventing a
44
+ conversion. GPU support must be present in the installed runtime; compatibility
45
+ metadata is not a benchmark. `lazy_weights=True` enables the installed MLX
46
+ loader's lazy evaluation of already-verified local weights; it does not execute
47
+ partially downloaded weights.
48
+
49
+ Downloads use strict ranges, resume partial chunks, verify the final file and
50
+ deduplicate content within each authenticated cache. Redirects cannot forward
51
+ credentials; private content uses a separate credential-scoped cache. Set
52
+ `SUPERII_TOKEN` to an existing scoped token with `repository:read` to access an
53
+ authorized private published release. Every new pull rechecks canonical access,
54
+ even when bytes are cached. Files already intentionally downloaded by their
55
+ authorized owner remain local; revocation cannot erase an owner's copies.
56
+
57
+ ```python
58
+ with superii.load("owner/model") as model:
59
+ model.serve(port=8765, token=your_random_local_token) # loopback OpenAI text API
60
+ # Or model.serve_mcp() for a stdio MCP inference tool.
61
+ ```
62
+
63
+ The OpenAI endpoint requires a token and rejects browser origins. It implements
64
+ non-streaming text completions and chat completions; it does not claim full
65
+ OpenAI API parity. MCP exposes one inference tool and does not itself configure
66
+ an agent's model provider. Repository content and model output remain untrusted.
67
+
68
+ An optional explicit `Client(peers=(Peer("https://cache.example", peer_token),))`
69
+ can use a peer cache. No discovery or LAN broadcasts occur. Private artifacts
70
+ always bypass peers. `superii.serving.create_cache_app` serves already-cached
71
+ public hashes only, after fresh canonical visibility checks. Deploy that optional
72
+ service with TLS and a separate strong peer credential; otherwise leave peers
73
+ unset. Outages, missing data and corrupted peer bytes fall back to the origin.
74
+
75
+ Canonical manifests are hashes, not publisher identity proofs. New automatic
76
+ publication also returns an Ed25519 policy attestation; verification and key
77
+ pinning are documented with the publication service. Historical releases retain
78
+ their historical evidence and are not silently relabeled.
79
+
80
+ ## Measurements and acquisition research
81
+
82
+ `superii benchmark owner/model "Hello" --max-tokens 128` records first output,
83
+ generation time, approximate tokens per second, sampled process-tree peak RSS
84
+ and bytes acquired before inference. Batch adapters label first-output time
85
+ separately from token-streaming TTFT. RSS does not measure all GPU allocations.
86
+ Run cold and warm cache trials separately; the tool does not clear the OS cache.
87
+
88
+ `superii.experiments.tensor_ranges(snapshot)` indexes verified safetensors, and
89
+ `iter_tensor_bytes(snapshot, prefix="model.layers.0.")` performs bounded mmap
90
+ reads for layer or expert experiments. These are tested access primitives;
91
+ arbitrary models do not yet execute with partial weights. All files must pass
92
+ full verification first. Quantization/conversion, layer scheduling and MoE
93
+ expert selection require an architecture-specific implementation and benchmark.
94
+
95
+ Optional remote warm-start is explicit at each remote request:
96
+
97
+ ```python
98
+ from superii.remote import RemoteModel
99
+
100
+ # This call sends the prompt to your chosen provider. Use its separate token.
101
+ # Local pull/load may run concurrently in your application's executor.
102
+ with RemoteModel("https://your-provider.example", "model-id", token=provider_token) as remote:
103
+ answer = remote.generate("Hello")
104
+ # Switch to your completed local Model for later requests when you choose.
105
+ ```
106
+
107
+ This adapter implements the provider's non-streaming `/v1/completions` contract.
108
+ It never reuses Super ii credentials, follows redirects, silently falls back to
109
+ remote execution, or asserts that remote and local model outputs are identical.
110
+
111
+ Sources: [llama.cpp server](https://github.com/ggml-org/llama.cpp/tree/master/tools/server),
112
+ [MLX LM](https://github.com/ml-explore/mlx-lm),
113
+ [vLLM](https://docs.vllm.ai/en/latest/),
114
+ [safetensors](https://huggingface.co/docs/safetensors/),
115
+ [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27,<2"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "superii-sdk"
7
+ version = "0.1.0"
8
+ description = "Verified Super ii model acquisition, hardware planning and local inference"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ dependencies = ["httpx>=0.28,<0.29", "filelock>=3.19,<4", "psutil>=7,<8", "cryptography>=46,<51"]
14
+
15
+ [project.optional-dependencies]
16
+ mlx = ["mlx-lm>=0.30,<1; sys_platform == 'darwin'"]
17
+ transformers = ["transformers>=5,<6", "torch>=2.8,<3", "safetensors>=0.6,<1", "accelerate>=1.10,<2"]
18
+ serve = ["fastapi>=0.115,<1", "uvicorn>=0.35,<1", "mcp>=1.20,<2"]
19
+ test = ["pytest>=9,<10", "ruff>=0.16,<1", "fastapi>=0.115,<1", "mcp>=1.20,<2"]
20
+
21
+ [project.scripts]
22
+ superii = "superii.cli:main"
23
+
24
+ [project.urls]
25
+ Homepage = "https://superii.site"
26
+ Source = "https://github.com/smavgs/super-ii/tree/main/sdk/python"
27
+
28
+ [tool.hatch.build.targets.wheel]
29
+ packages = ["src/superii"]
30
+
31
+ [tool.pytest.ini_options]
32
+ testpaths = ["tests"]
33
+
34
+ [tool.ruff]
35
+ line-length = 100
36
+ target-version = "py311"
37
+
38
+ [tool.ruff.lint]
39
+ select = ["E", "F", "I", "UP", "B"]
@@ -0,0 +1,84 @@
1
+ """Super ii: inspect, plan, verify and run immutable local models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .client import Client, Peer, Snapshot
6
+ from .errors import IntegrityError, PlanError, SuperiiError
7
+ from .hardware import Hardware, hardware
8
+ from .manifest import Manifest
9
+ from .model import Model
10
+ from .planner import Plan
11
+ from .planner import plan as _plan
12
+
13
+ __version__ = "0.1.0"
14
+ __all__ = [
15
+ "Client",
16
+ "Peer",
17
+ "Snapshot",
18
+ "IntegrityError",
19
+ "PlanError",
20
+ "SuperiiError",
21
+ "Hardware",
22
+ "hardware",
23
+ "Manifest",
24
+ "Model",
25
+ "Plan",
26
+ "inspect",
27
+ "plan",
28
+ "pull",
29
+ "apull",
30
+ "verify",
31
+ "load",
32
+ ]
33
+
34
+
35
+ def inspect(repository: str, *, revision: str | None = None, **client_options) -> Manifest:
36
+ with Client(**client_options) as client:
37
+ return client.inspect(repository, revision=revision)
38
+
39
+
40
+ def plan(
41
+ repository: str | Manifest,
42
+ *,
43
+ machine: Hardware | None = None,
44
+ runtime: str | None = None,
45
+ context_size: int = 4096,
46
+ revision: str | None = None,
47
+ **client_options,
48
+ ) -> Plan:
49
+ manifest = (
50
+ repository
51
+ if isinstance(repository, Manifest)
52
+ else inspect(repository, revision=revision, **client_options)
53
+ )
54
+ return _plan(manifest, machine or hardware(), runtime=runtime, context_size=context_size)
55
+
56
+
57
+ def pull(repository: str, *, revision: str | None = None, **client_options) -> Snapshot:
58
+ with Client(**client_options) as client:
59
+ return client.pull(repository, revision=revision)
60
+
61
+
62
+ async def apull(repository: str, *, revision: str | None = None, **client_options) -> Snapshot:
63
+ with Client(**client_options) as client:
64
+ return await client.apull(repository, revision=revision)
65
+
66
+
67
+ def verify(snapshot: Snapshot) -> bool:
68
+ return snapshot.verify()
69
+
70
+
71
+ def load(
72
+ repository: str,
73
+ *,
74
+ revision: str | None = None,
75
+ runtime: str | None = None,
76
+ context_size: int = 4096,
77
+ lazy_weights: bool = False,
78
+ **client_options,
79
+ ) -> Model:
80
+ with Client(**client_options) as client:
81
+ manifest = client.inspect(repository, revision=revision)
82
+ selected = _plan(manifest, hardware(), runtime=runtime, context_size=context_size)
83
+ snapshot = client.pull(repository, revision=selected.revision, files=selected.files)
84
+ return Model(snapshot, selected, lazy_weights=lazy_weights)
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import json
5
+ from collections.abc import Mapping
6
+
7
+ from cryptography.exceptions import InvalidSignature
8
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
9
+
10
+ from .errors import IntegrityError
11
+ from .manifest import Manifest
12
+
13
+
14
+ def verify_attestation(manifest: Manifest, trusted_keys: Mapping[str, str]) -> bool:
15
+ proof = manifest.publication
16
+ if not proof:
17
+ raise IntegrityError("This release has no automatic publication attestation")
18
+ try:
19
+ key = trusted_keys[proof["key_id"]]
20
+ payload = proof["payload"]
21
+ Ed25519PublicKey.from_public_bytes(base64.b64decode(key, validate=True)).verify(
22
+ base64.b64decode(proof["signature"], validate=True),
23
+ payload.encode(),
24
+ )
25
+ data = json.loads(payload)
26
+ if (
27
+ data["manifest_sha256"] != manifest.manifest_sha256
28
+ or data["repository_id"] != manifest.repository_id
29
+ or data["revision_id"] != manifest.revision_id
30
+ or data["commit_sha"] != manifest.revision
31
+ or data["outcome"] != "passed"
32
+ or data["policy_version"] != "superii-auto-publish-v1"
33
+ ):
34
+ raise IntegrityError("Publication attestation does not approve this manifest")
35
+ except (KeyError, TypeError, ValueError, InvalidSignature) as error:
36
+ raise IntegrityError(
37
+ "Publication signature is missing, invalid or signed by an untrusted key"
38
+ ) from error
39
+ return True
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ from dataclasses import asdict
6
+
7
+
8
+ def main() -> None:
9
+ from . import Client, hardware, load, plan
10
+ from .experiments import benchmark
11
+
12
+ parser = argparse.ArgumentParser(prog="superii")
13
+ parser.add_argument("--base-url", default="https://superii.site")
14
+ parser.add_argument("--cache-dir")
15
+ commands = parser.add_subparsers(dest="command", required=True)
16
+ commands.add_parser("hardware")
17
+ for name in ("inspect", "plan", "pull", "generate", "benchmark", "mcp", "serve"):
18
+ sub = commands.add_parser(name)
19
+ sub.add_argument("repository")
20
+ sub.add_argument("--revision")
21
+ if name in {"plan", "generate", "benchmark", "mcp", "serve"}:
22
+ sub.add_argument("--runtime", choices=["llama.cpp", "mlx", "transformers", "vllm"])
23
+ sub.add_argument("--context-size", type=int, default=4096)
24
+ if name in {"generate", "benchmark"}:
25
+ sub.add_argument("prompt")
26
+ sub.add_argument("--max-tokens", type=int, default=128)
27
+ if name == "serve":
28
+ sub.add_argument("--port", type=int, default=8765)
29
+ args = parser.parse_args()
30
+ if args.command == "hardware":
31
+ print(json.dumps(asdict(hardware()), indent=2))
32
+ return
33
+ options = {"base_url": args.base_url, "cache_dir": args.cache_dir}
34
+ if args.command in {"inspect", "pull"}:
35
+ with Client(**options) as client:
36
+ result = getattr(client, args.command)(args.repository, revision=args.revision)
37
+ print(json.dumps(asdict(result), indent=2, default=str))
38
+ elif args.command == "plan":
39
+ print(
40
+ json.dumps(
41
+ asdict(
42
+ plan(
43
+ args.repository,
44
+ revision=args.revision,
45
+ runtime=args.runtime,
46
+ context_size=args.context_size,
47
+ **options,
48
+ )
49
+ ),
50
+ indent=2,
51
+ )
52
+ )
53
+ else:
54
+ with load(
55
+ args.repository,
56
+ revision=args.revision,
57
+ runtime=args.runtime,
58
+ context_size=args.context_size,
59
+ **options,
60
+ ) as model:
61
+ if args.command == "mcp":
62
+ model.serve_mcp()
63
+ elif args.command == "serve":
64
+ import os
65
+
66
+ token = os.environ.get("SUPERII_SERVING_TOKEN", "")
67
+ if len(token) < 32:
68
+ parser.error(
69
+ "Set SUPERII_SERVING_TOKEN to a random local token (32+ characters)"
70
+ )
71
+ model.serve(port=args.port, token=token)
72
+ elif args.command == "benchmark":
73
+ print(
74
+ json.dumps(benchmark(model, args.prompt, max_tokens=args.max_tokens), indent=2)
75
+ )
76
+ else:
77
+ print(model.generate(args.prompt, max_tokens=args.max_tokens))