kcoral 0.1.1__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.
- kcoral-0.1.1/.claude/skills/kcoral-client/SKILL.md +271 -0
- kcoral-0.1.1/.coderabbit.yaml +119 -0
- kcoral-0.1.1/.github/workflows/build_wheels.yml +98 -0
- kcoral-0.1.1/.github/workflows/docs.yml +54 -0
- kcoral-0.1.1/.github/workflows/publish_pypi.yml +37 -0
- kcoral-0.1.1/.gitignore +28 -0
- kcoral-0.1.1/.pre-commit-config.yaml +39 -0
- kcoral-0.1.1/Cargo.lock +2328 -0
- kcoral-0.1.1/Cargo.toml +3 -0
- kcoral-0.1.1/MANIFEST.in +4 -0
- kcoral-0.1.1/PKG-INFO +148 -0
- kcoral-0.1.1/README.md +127 -0
- kcoral-0.1.1/docker/Dockerfile.cu132.dev +39 -0
- kcoral-0.1.1/docker/Dockerfile.cu132.dev.dockerignore +17 -0
- kcoral-0.1.1/docker/compose.yaml +28 -0
- kcoral-0.1.1/docs/_static/brand/kcoral-icon.png +0 -0
- kcoral-0.1.1/docs/_static/brand/kcoral-logo-dark.png +0 -0
- kcoral-0.1.1/docs/_static/brand/kcoral-logo-light.png +0 -0
- kcoral-0.1.1/docs/_static/custom.css +74 -0
- kcoral-0.1.1/docs/_static/router-architecture.png +0 -0
- kcoral-0.1.1/docs/_templates/components/view-this-page.html +25 -0
- kcoral-0.1.1/docs/_templates/sidebar/version-switcher.html +14 -0
- kcoral-0.1.1/docs/client-guide/builtin-cli-tools.md +534 -0
- kcoral-0.1.1/docs/client-guide/protocol.md +683 -0
- kcoral-0.1.1/docs/client-guide/remote-functions.md +63 -0
- kcoral-0.1.1/docs/client-guide/writing-a-program.md +347 -0
- kcoral-0.1.1/docs/conf.py +78 -0
- kcoral-0.1.1/docs/getting-started/installation.md +125 -0
- kcoral-0.1.1/docs/getting-started/quickstart.md +91 -0
- kcoral-0.1.1/docs/index.md +73 -0
- kcoral-0.1.1/docs/python-api/index.rst +116 -0
- kcoral-0.1.1/docs/requirements.in +4 -0
- kcoral-0.1.1/docs/requirements.txt +81 -0
- kcoral-0.1.1/docs/server-guide/launch-the-server.md +310 -0
- kcoral-0.1.1/docs/server-guide/logging.md +110 -0
- kcoral-0.1.1/docs/server-guide/router.md +186 -0
- kcoral-0.1.1/docs/tutorials/agent-integration.md +91 -0
- kcoral-0.1.1/docs/tutorials/benchmark-kernel.md +243 -0
- kcoral-0.1.1/docs/tutorials/remote-compilation.md +223 -0
- kcoral-0.1.1/examples/basics/first_program.py +38 -0
- kcoral-0.1.1/examples/basics/remote_function.py +31 -0
- kcoral-0.1.1/examples/benchmark_kernel/benchmark_kernel.py +84 -0
- kcoral-0.1.1/examples/cpu_compile/cpu_compile_gpu_execute.py +169 -0
- kcoral-0.1.1/examples/cpu_compile/library_upload.py +135 -0
- kcoral-0.1.1/examples/multi_gpu/multiprocess.py +125 -0
- kcoral-0.1.1/examples/multi_gpu/single_process.py +95 -0
- kcoral-0.1.1/examples/thor/.gitignore +3 -0
- kcoral-0.1.1/examples/thor/PROMPT.md +241 -0
- kcoral-0.1.1/examples/thor/README.md +202 -0
- kcoral-0.1.1/examples/thor/bench.py +724 -0
- kcoral-0.1.1/examples/thor/definition.json +27 -0
- kcoral-0.1.1/examples/thor/initial_kernel.py +68 -0
- kcoral-0.1.1/examples/thor/launch_server.sh +106 -0
- kcoral-0.1.1/examples/thor/workload.jsonl +4 -0
- kcoral-0.1.1/pyproject.toml +75 -0
- kcoral-0.1.1/python/kcoral/__init__.py +50 -0
- kcoral-0.1.1/python/kcoral/__main__.py +35 -0
- kcoral-0.1.1/python/kcoral/artifacts.py +339 -0
- kcoral-0.1.1/python/kcoral/builtins.py +324 -0
- kcoral-0.1.1/python/kcoral/client/__init__.py +16 -0
- kcoral-0.1.1/python/kcoral/client/functions.py +245 -0
- kcoral-0.1.1/python/kcoral/client/http.py +278 -0
- kcoral-0.1.1/python/kcoral/client/program.py +415 -0
- kcoral-0.1.1/python/kcoral/client/result.py +402 -0
- kcoral-0.1.1/python/kcoral/config.py +58 -0
- kcoral-0.1.1/python/kcoral/errors.py +73 -0
- kcoral-0.1.1/python/kcoral/protocol.py +601 -0
- kcoral-0.1.1/python/kcoral/runtime/__init__.py +1 -0
- kcoral-0.1.1/python/kcoral/runtime/engine.py +565 -0
- kcoral-0.1.1/python/kcoral/runtime/gpu.py +463 -0
- kcoral-0.1.1/python/kcoral/runtime/lease.py +282 -0
- kcoral-0.1.1/python/kcoral/runtime/pool.py +501 -0
- kcoral-0.1.1/python/kcoral/runtime/python.py +233 -0
- kcoral-0.1.1/python/kcoral/runtime/worker.py +902 -0
- kcoral-0.1.1/python/kcoral/schemas.py +119 -0
- kcoral-0.1.1/python/kcoral/server/__init__.py +1 -0
- kcoral-0.1.1/python/kcoral/server/_generated/__init__.py +1 -0
- kcoral-0.1.1/python/kcoral/server/_generated/kcoral_gateway_pb2.py +64 -0
- kcoral-0.1.1/python/kcoral/server/_generated/kcoral_gateway_pb2_grpc.py +145 -0
- kcoral-0.1.1/python/kcoral/server/app.py +668 -0
- kcoral-0.1.1/python/kcoral/server/cache.py +282 -0
- kcoral-0.1.1/python/kcoral/server/cli.py +350 -0
- kcoral-0.1.1/python/kcoral/server/events.py +161 -0
- kcoral-0.1.1/python/kcoral/server/tunnel.py +374 -0
- kcoral-0.1.1/python/kcoral/support/__init__.py +1 -0
- kcoral-0.1.1/python/kcoral/support/cuda.py +127 -0
- kcoral-0.1.1/python/kcoral/support/platform.py +181 -0
- kcoral-0.1.1/python/kcoral/support/sandbox.py +412 -0
- kcoral-0.1.1/python/kcoral/tools/__init__.py +10 -0
- kcoral-0.1.1/python/kcoral/tools/cli.py +301 -0
- kcoral-0.1.1/python/kcoral/tools/compute_sanitizer.py +17 -0
- kcoral-0.1.1/python/kcoral/tools/ncu.py +42 -0
- kcoral-0.1.1/python/kcoral/tools/python.py +48 -0
- kcoral-0.1.1/python/kcoral/tools/run_iket.py +32 -0
- kcoral-0.1.1/python/kcoral/tools/runner.py +90 -0
- kcoral-0.1.1/python/kcoral/tools/shell.py +17 -0
- kcoral-0.1.1/python/kcoral.egg-info/PKG-INFO +148 -0
- kcoral-0.1.1/python/kcoral.egg-info/SOURCES.txt +168 -0
- kcoral-0.1.1/python/kcoral.egg-info/dependency_links.txt +1 -0
- kcoral-0.1.1/python/kcoral.egg-info/entry_points.txt +2 -0
- kcoral-0.1.1/python/kcoral.egg-info/requires.txt +15 -0
- kcoral-0.1.1/python/kcoral.egg-info/scm_file_list.json +164 -0
- kcoral-0.1.1/python/kcoral.egg-info/scm_version.json +8 -0
- kcoral-0.1.1/python/kcoral.egg-info/top_level.txt +1 -0
- kcoral-0.1.1/rust/kcoral/Cargo.toml +47 -0
- kcoral-0.1.1/rust/kcoral/README.md +126 -0
- kcoral-0.1.1/rust/kcoral/build.rs +11 -0
- kcoral-0.1.1/rust/kcoral/proto/kcoral_gateway.proto +87 -0
- kcoral-0.1.1/rust/kcoral/src/bin/node.rs +196 -0
- kcoral-0.1.1/rust/kcoral/src/bin/router.rs +71 -0
- kcoral-0.1.1/rust/kcoral/src/headers.rs +68 -0
- kcoral-0.1.1/rust/kcoral/src/lib.rs +67 -0
- kcoral-0.1.1/rust/kcoral/src/process.rs +180 -0
- kcoral-0.1.1/rust/kcoral/src/router/gateway.rs +176 -0
- kcoral-0.1.1/rust/kcoral/src/router/http.rs +482 -0
- kcoral-0.1.1/rust/kcoral/src/router/mod.rs +17 -0
- kcoral-0.1.1/rust/kcoral/src/router/pool.rs +1047 -0
- kcoral-0.1.1/rust/kcoral/src/router/slot.rs +135 -0
- kcoral-0.1.1/rust/kcoral/src/supervisor.rs +592 -0
- kcoral-0.1.1/rust/kcoral/tests/network.rs +694 -0
- kcoral-0.1.1/scripts/build_docs.py +125 -0
- kcoral-0.1.1/scripts/generate_gateway.py +54 -0
- kcoral-0.1.1/setup.cfg +4 -0
- kcoral-0.1.1/setup.py +40 -0
- kcoral-0.1.1/tests/support/README.md +14 -0
- kcoral-0.1.1/tests/support/__init__.py +1 -0
- kcoral-0.1.1/tests/support/_common.py +20 -0
- kcoral-0.1.1/tests/support/core.py +50 -0
- kcoral-0.1.1/tests/support/cuda.py +202 -0
- kcoral-0.1.1/tests/support/cutedsl.py +54 -0
- kcoral-0.1.1/tests/support/fake.py +42 -0
- kcoral-0.1.1/tests/support/programs.py +73 -0
- kcoral-0.1.1/tests/support/runtime.py +150 -0
- kcoral-0.1.1/tests/support/triton.py +55 -0
- kcoral-0.1.1/tests/test_builtins.py +15 -0
- kcoral-0.1.1/tests/test_cache.py +180 -0
- kcoral-0.1.1/tests/test_cli.py +197 -0
- kcoral-0.1.1/tests/test_client.py +914 -0
- kcoral-0.1.1/tests/test_cpu_runtime.py +56 -0
- kcoral-0.1.1/tests/test_cuda_error_api.py +25 -0
- kcoral-0.1.1/tests/test_engine.py +600 -0
- kcoral-0.1.1/tests/test_events.py +439 -0
- kcoral-0.1.1/tests/test_file_return.py +237 -0
- kcoral-0.1.1/tests/test_folder.py +132 -0
- kcoral-0.1.1/tests/test_functions.py +121 -0
- kcoral-0.1.1/tests/test_gateway.py +563 -0
- kcoral-0.1.1/tests/test_gpu_cleanup.py +88 -0
- kcoral-0.1.1/tests/test_gpu_jobs.py +634 -0
- kcoral-0.1.1/tests/test_gpu_runtime.py +1248 -0
- kcoral-0.1.1/tests/test_keys.py +21 -0
- kcoral-0.1.1/tests/test_lease.py +169 -0
- kcoral-0.1.1/tests/test_multi_gpu_jobs.py +67 -0
- kcoral-0.1.1/tests/test_multipart.py +53 -0
- kcoral-0.1.1/tests/test_node_processes.py +143 -0
- kcoral-0.1.1/tests/test_packaging.py +81 -0
- kcoral-0.1.1/tests/test_pool.py +755 -0
- kcoral-0.1.1/tests/test_process_state.py +96 -0
- kcoral-0.1.1/tests/test_sandbox.py +964 -0
- kcoral-0.1.1/tests/test_schemas.py +474 -0
- kcoral-0.1.1/tests/test_server_e2e.py +1289 -0
- kcoral-0.1.1/tests/test_service_cli.py +518 -0
- kcoral-0.1.1/tests/test_shutdown.py +229 -0
- kcoral-0.1.1/tests/test_tool_cli.py +255 -0
- kcoral-0.1.1/tests/test_tunnel.py +405 -0
- kcoral-0.1.1/uv.lock +1926 -0
- kcoral-0.1.1/website/README.md +36 -0
- kcoral-0.1.1/website/assets/site.css +261 -0
- kcoral-0.1.1/website/assets/site.js +15 -0
- kcoral-0.1.1/website/index.html +203 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kcoral-client
|
|
3
|
+
description: >-
|
|
4
|
+
Write client code for KCoral's POST /execute instruction
|
|
5
|
+
protocol. Use when writing, reviewing, or debugging programs that upload
|
|
6
|
+
kernels (TIRx, CUDA C, CuTeDSL, Triton), create tensors, compile, check
|
|
7
|
+
correctness, or benchmark on a remote GPU server, or when using the
|
|
8
|
+
kcoral Client and Program API.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# KCoral client
|
|
12
|
+
|
|
13
|
+
Facts needed to write a protocol-conformant client. `docs/client-guide/protocol.md` is the
|
|
14
|
+
authoritative field-level specification; where this page and that file
|
|
15
|
+
disagree, that file wins.
|
|
16
|
+
|
|
17
|
+
## Model
|
|
18
|
+
|
|
19
|
+
- The client endpoints are `POST /execute` and `GET /health`.
|
|
20
|
+
- A request body is a **program**: an ordered list of instructions executed
|
|
21
|
+
top to bottom on a GPU or CPU worker.
|
|
22
|
+
- There is no session state. Handles (`id`s) live for one request; a second
|
|
23
|
+
`execute` shares nothing with the first, so every program uploads everything
|
|
24
|
+
it needs.
|
|
25
|
+
- `run` computes a value but does not send it back. The response carries only
|
|
26
|
+
what `return` selects.
|
|
27
|
+
- A reference has the exact form `{"$ref": "<id>"}` and must point to an
|
|
28
|
+
earlier instruction.
|
|
29
|
+
- The `GET /health` response includes the GPU `target` (e.g. `{"arch": "sm_100a"}`),
|
|
30
|
+
installed `versions`, and `load`: `request_capacity` (occupied + free capacity),
|
|
31
|
+
`requests_in_progress` (assigned requests), and `requests_waiting`
|
|
32
|
+
(requests awaiting assignment).
|
|
33
|
+
|
|
34
|
+
## Python client
|
|
35
|
+
|
|
36
|
+
For simple tasks, use `@client.function(timeout=30)` and call `.remote()` for the
|
|
37
|
+
decoded value, or `.execute()` for the full `ProgramResult`. Define the function
|
|
38
|
+
in a file, import dependencies inside it, and pass inputs explicitly. Configure
|
|
39
|
+
the server on `Client` and keep it open for remote calls. See
|
|
40
|
+
[Remote functions](../../../docs/client-guide/remote-functions.md)
|
|
41
|
+
for supported inputs and execution boundaries.
|
|
42
|
+
|
|
43
|
+
Upload a harness, select its entry point, run it and return what you want to inspect:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from kcoral import Client, Program
|
|
47
|
+
|
|
48
|
+
program = Program()
|
|
49
|
+
module = program.upload(kind="module", source="""
|
|
50
|
+
import torch
|
|
51
|
+
|
|
52
|
+
def main(n):
|
|
53
|
+
x = torch.arange(n, dtype=torch.float32, device="cuda")
|
|
54
|
+
y = x + 1
|
|
55
|
+
torch.testing.assert_close(y, x + 1)
|
|
56
|
+
return {"ok": True, "output": y}
|
|
57
|
+
""")
|
|
58
|
+
main = program.get_function(module=module, name="main")
|
|
59
|
+
report = program.run(fn=main, args=[256])
|
|
60
|
+
program.return_(key="report", value=report)
|
|
61
|
+
with Client("http://127.0.0.1:8000") as client:
|
|
62
|
+
result = client.execute(program, timeout_seconds=120)
|
|
63
|
+
print(result.results)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Uploaded Python can perform tasks such as compilation, tensor allocation,
|
|
67
|
+
validation, measurement, or invoking scripts and CLI tools. `run.fn` references
|
|
68
|
+
an earlier callable; a callable returned by a `run` can be used by a later call.
|
|
69
|
+
|
|
70
|
+
API surface:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
Program.upload(kind="module", source=...) -> Register
|
|
74
|
+
Program.upload(kind="tensor", value=..., dtype=None, shape=None) -> Register
|
|
75
|
+
Program.upload(kind="bytes", value=...) -> Register
|
|
76
|
+
Program.upload(kind="library", value=...) -> Register
|
|
77
|
+
Program.upload_file(blob=..., path=...) -> Register
|
|
78
|
+
Program.upload_folder(folder, *, path=...) -> None
|
|
79
|
+
Program.get_function(module=..., name=..., cpu_only=False) -> Register
|
|
80
|
+
Program.run(fn=..., args=[]) -> Register
|
|
81
|
+
Program.return_(key=..., value=...) -> None
|
|
82
|
+
Program.return_file(key=..., path=...) -> None # str or Register resolving to str
|
|
83
|
+
Program.return_folder(key=..., path=...) -> None # str or Register resolving to str
|
|
84
|
+
|
|
85
|
+
Client(base_url, *, headers=None, connect_timeout_seconds=10)
|
|
86
|
+
Client.execute(program, *, timeout_seconds=None, output_limit_bytes=None, gpu_count=None) -> ProgramResult
|
|
87
|
+
Client.health() -> dict
|
|
88
|
+
Client.target() -> dict # e.g. {"arch": "sm_100a"}
|
|
89
|
+
Client.close() -> None
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`Program` automatically generates an ID for each value-producing instruction.
|
|
93
|
+
Use the optional `id` field to customize it.
|
|
94
|
+
|
|
95
|
+
The client derives `blob`, `dtype`, and `shape` from a tensor `value`. It sends
|
|
96
|
+
no blob parts at first, retries a `CACHE_MISS` with the missing parts, and falls
|
|
97
|
+
back to resending every local blob if the cache changes between the two
|
|
98
|
+
requests. Returned tensors decode to CPU `numpy.ndarray` (`bfloat16` and
|
|
99
|
+
`float8_*` via `ml_dtypes`).
|
|
100
|
+
|
|
101
|
+
`upload_folder` snapshots a local directory into ordinary file upload
|
|
102
|
+
instructions; retries send the same instructions with different blob parts.
|
|
103
|
+
It includes hidden files, rejects links, special files and repeated directories,
|
|
104
|
+
and omits empty directories and original permissions/timestamps. A failed call
|
|
105
|
+
leaves the program unchanged. Caching is automatic and best-effort.
|
|
106
|
+
|
|
107
|
+
`return_file` and `return_folder` capture workspace-relative paths at that
|
|
108
|
+
instruction; `path` may be an earlier register containing a path string.
|
|
109
|
+
Use `result[key].save(destination)` to save locally. File results also provide
|
|
110
|
+
`read_bytes()`; folder results provide `files` and `directories`. Folders include
|
|
111
|
+
hidden files and empty directories. Missing paths, symlinks, and special files
|
|
112
|
+
fail collection. Earlier returns survive later ordinary instruction failures.
|
|
113
|
+
Saves require an existing parent; file replacement needs `overwrite=True`, and
|
|
114
|
+
folder destinations must be new. Transfers are buffered and subject to server
|
|
115
|
+
limits. See [client usage](../../../docs/client-guide/writing-a-program.md#return-files-and-folders).
|
|
116
|
+
|
|
117
|
+
## Instructions
|
|
118
|
+
|
|
119
|
+
### `upload`
|
|
120
|
+
|
|
121
|
+
Each field is required for the listed kinds:
|
|
122
|
+
|
|
123
|
+
| Field | Kinds | Notes |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `id` | all | Unique handle name |
|
|
126
|
+
| `kind` | all | `"module"`, `"tensor"`, `"bytes"`, `"file"`, or `"library"` |
|
|
127
|
+
| `source` | module | Python source executed to define a module |
|
|
128
|
+
| `blob` | tensor, bytes, file, library | SHA-256 of the raw bytes |
|
|
129
|
+
| `path` | file | Relative path in the request working directory |
|
|
130
|
+
| `dtype` | tensor | Tensor data type |
|
|
131
|
+
| `shape` | tensor | Tensor shape |
|
|
132
|
+
|
|
133
|
+
A module upload binds its full source namespace. Use `get_function` to select a
|
|
134
|
+
named Python object. Uploaded Python is ordinary code
|
|
135
|
+
executed on the worker (torch included), so a plain function works as a
|
|
136
|
+
reference baseline.
|
|
137
|
+
|
|
138
|
+
A `bytes` upload binds the blob's bytes unchanged. They stay in CPU memory and
|
|
139
|
+
can be passed to uploaded Python code, which suits files and other binary
|
|
140
|
+
formats the server should parse.
|
|
141
|
+
|
|
142
|
+
A `library` upload is a prebuilt TVM FFI shared library loaded with
|
|
143
|
+
`tvm_ffi.load_module`; use `get_function` to bind one of its exported functions.
|
|
144
|
+
|
|
145
|
+
A `file` upload binds its normalized relative path as a string. Use
|
|
146
|
+
`upload_file(blob=..., path=...)` in the Python client, where `blob` is bytes-like;
|
|
147
|
+
the wire field holds its SHA-256. The server copies it into the request's private
|
|
148
|
+
working directory with mode `0600` and removes that directory after execution.
|
|
149
|
+
Its content can remain in the disk cache across requests and server restarts.
|
|
150
|
+
|
|
151
|
+
### `get_function`
|
|
152
|
+
|
|
153
|
+
Select an object from an uploaded module with `get_function(module=..., name=...)`.
|
|
154
|
+
The returned `Register` stores its instruction ID and can be passed as `fn` to `run`.
|
|
155
|
+
|
|
156
|
+
`get_function(..., cpu_only=True)` declares that later calls to this function
|
|
157
|
+
use no GPU. Before its `run`, a GPU worker synchronizes and releases the lease.
|
|
158
|
+
A detected CUDA call fails with `gpu_access`. This is a best-effort check.
|
|
159
|
+
The flag applies to the selected function's calls; the Python module upload
|
|
160
|
+
executes top-level code under the GPU lease.
|
|
161
|
+
|
|
162
|
+
### `run`
|
|
163
|
+
|
|
164
|
+
`{"op": "run", "id": ..., "fn": {"$ref": "function_id"}, "args": [...]}`
|
|
165
|
+
calls an earlier callable. In Python, pass the `Register` returned by
|
|
166
|
+
`get_function` (or a `run` that returned a callable); the client encodes its ID
|
|
167
|
+
as `{"$ref": "function_id"}`. Top-level argument references resolve to values;
|
|
168
|
+
other JSON values pass as literals.
|
|
169
|
+
|
|
170
|
+
### `return`
|
|
171
|
+
|
|
172
|
+
`{"op": "return", "key": ..., "value": {"$ref": id}}` — selects a handle for
|
|
173
|
+
the response `results` object. A `return` that already ran keeps its entry
|
|
174
|
+
even if a later instruction fails, so returning early checkpoints partial
|
|
175
|
+
work.
|
|
176
|
+
|
|
177
|
+
## Multi-GPU programs
|
|
178
|
+
|
|
179
|
+
Use `Client.execute(program, gpu_count=N)` for 1–8 GPUs on one direct server.
|
|
180
|
+
Upload definitions and files, select an entry point with `get_function`, then
|
|
181
|
+
execute with `run`. Single- and multi-GPU workers share instruction-level leasing:
|
|
182
|
+
`cpu_only` synchronizes and releases the entire set, and later GPU instructions
|
|
183
|
+
reacquire the same devices. The script owns communication and must join GPU
|
|
184
|
+
subprocesses before returning. Spawn workers need an importable `.py` file.
|
|
185
|
+
Do not mark a GPU launcher CPU-only. See the [two single-file examples](../../../docs/client-guide/writing-a-program.md#run-a-multi-gpu-program)
|
|
186
|
+
and [execution protocol](../../../docs/client-guide/protocol.md#multi-gpu-execution).
|
|
187
|
+
|
|
188
|
+
## Compilation and measurement helpers
|
|
189
|
+
|
|
190
|
+
For convenience, uploaded Python can import `compile_tirx` and `benchmark` from
|
|
191
|
+
`kcoral.builtins`. You can also use your own compilation and measurement harness.
|
|
192
|
+
See the [API reference](../../../docs/python-api/index.rst#gpu-utilities)
|
|
193
|
+
for signatures and options, and the
|
|
194
|
+
[compilation tutorial](../../../docs/tutorials/benchmark-kernel.md#choose-where-to-compile)
|
|
195
|
+
for GPU-server, CPU-server and local compilation examples.
|
|
196
|
+
|
|
197
|
+
## Tensors
|
|
198
|
+
|
|
199
|
+
Two ways to provide tensors are to upload Python that initializes them remotely,
|
|
200
|
+
or to upload local tensors with `kind="tensor"`.
|
|
201
|
+
|
|
202
|
+
- `kind="tensor"` accepts a NumPy array, a torch tensor, any DLPack object,
|
|
203
|
+
or raw bytes with `dtype` and `shape`.
|
|
204
|
+
- Accepted dtypes: `bool`, `uint8`, `int8`, `int16`, `int32`, `int64`,
|
|
205
|
+
`float16`, `float32`, `float64`, `bfloat16`, `float8_e4m3fn`,
|
|
206
|
+
`float8_e5m2`.
|
|
207
|
+
- To hand a returned `bfloat16` array to torch:
|
|
208
|
+
`torch.from_numpy(value.view(np.uint8)).view(torch.bfloat16)`.
|
|
209
|
+
|
|
210
|
+
## Correctness and timing
|
|
211
|
+
|
|
212
|
+
Your uploaded code can configure, for example, tolerances, assertions, profiler
|
|
213
|
+
invocation, warmup, and measurement methodology. Return reports and relevant
|
|
214
|
+
artifacts explicitly. Synchronize and wait for GPU subprocesses before
|
|
215
|
+
returning or releasing a lease.
|
|
216
|
+
|
|
217
|
+
## Request timing
|
|
218
|
+
|
|
219
|
+
The execution response contains top-level `queue_ms`, `elapsed_ms`,
|
|
220
|
+
`lease_wait_ms`, and `lease_held_ms` fields. The Python client exposes them as
|
|
221
|
+
attributes of the `ProgramResult` returned by `Client.execute`, for example
|
|
222
|
+
`result.lease_held_ms`.
|
|
223
|
+
|
|
224
|
+
`queue_ms` measures the wait for a worker. `elapsed_ms` starts once a worker is
|
|
225
|
+
assigned and includes waiting for the GPU lease (`lease_wait_ms`), holding it
|
|
226
|
+
(`lease_held_ms`), and other worker work. Holding the lease reserves the GPU;
|
|
227
|
+
it does not imply continuous GPU activity. Kernel latency is measured separately
|
|
228
|
+
by `benchmark` or your own measurement code.
|
|
229
|
+
|
|
230
|
+
## Outcomes
|
|
231
|
+
|
|
232
|
+
- `options`: `timeout_seconds` (server defaults: 300, maximum 900),
|
|
233
|
+
`output_limit_bytes` (default 1 MiB per stream). Values above a maximum are
|
|
234
|
+
clamped. `stdout`/`stderr` come back with the response.
|
|
235
|
+
- `COMPLETED` — every instruction ran; `results` holds the returned values.
|
|
236
|
+
- `FAILED` — one instruction failed and the rest were skipped; returns that
|
|
237
|
+
already ran stay in `results`. `error` carries `kind` (`parse`, `compile`,
|
|
238
|
+
`runtime`, `gpu_access`, `correctness`, `serialization`, `unavailable`,
|
|
239
|
+
`engine`), `message`, `instruction_index`, `instruction_id`, `traceback`.
|
|
240
|
+
- `CACHE_MISS` — blobs missing; the Python client retries with the missing
|
|
241
|
+
blobs, then with all local blobs if that retry misses again.
|
|
242
|
+
- Exceptions: `KCoralError` (carries `status_code` and `kind`; 503
|
|
243
|
+
means no worker free, 504 means `timeout_seconds` hit), `TransportError`
|
|
244
|
+
(no HTTP response could be obtained; execution may have occurred),
|
|
245
|
+
`ProtocolError` (malformed response or failed cache recovery).
|
|
246
|
+
|
|
247
|
+
## Non-Python clients
|
|
248
|
+
|
|
249
|
+
The wire format is `multipart/form-data` with a `program` part
|
|
250
|
+
(`application/json`) plus one `blob:<sha256>` part
|
|
251
|
+
(`application/octet-stream`) per tensor, bytes, file, or library blob, where
|
|
252
|
+
`<sha256>` is the lowercase hex SHA-256 of the part bytes. Blobs are cached by
|
|
253
|
+
hash: on `status: CACHE_MISS`, resend the program with the parts listed in
|
|
254
|
+
`missing_blobs`, and resend every blob if that retry misses again. Responses
|
|
255
|
+
containing tensors or bytes are multipart with a `result` JSON part and
|
|
256
|
+
`return:<index>` binary parts. The typed value encoding, blob-cache rules, and
|
|
257
|
+
full error table are in `docs/client-guide/protocol.md`.
|
|
258
|
+
|
|
259
|
+
## References
|
|
260
|
+
|
|
261
|
+
- `docs/client-guide/protocol.md` — field-level wire specification: request envelope,
|
|
262
|
+
value encoding, library upload build routes (TVM FFI, TIRx
|
|
263
|
+
`export_library`, CuTeDSL `--enable-tvm-ffi`) and their link flags, full
|
|
264
|
+
HTTP error table.
|
|
265
|
+
- `docs/client-guide/writing-a-program.md` — narrative guide: server-side compile vs prebuilt
|
|
266
|
+
library trade-offs, measurement guidance.
|
|
267
|
+
- `examples/basics/first_program.py` — runnable: upload a function and tensor, then
|
|
268
|
+
execute and return the result.
|
|
269
|
+
- `examples/benchmark_kernel/benchmark_kernel.py` — CPU-only TIRx compilation and GPU measurement on one server.
|
|
270
|
+
- `examples/cpu_compile/library_upload.py` — client build and library upload.
|
|
271
|
+
- `examples/cpu_compile/cpu_compile_gpu_execute.py` — CPU build and GPU execution.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# yaml-language-server: $schema=https://www.coderabbit.ai/integrations/schema.v2.json
|
|
2
|
+
language: en-US
|
|
3
|
+
early_access: false
|
|
4
|
+
inheritance: false
|
|
5
|
+
tone_instructions: >-
|
|
6
|
+
Be concise and specific. Prioritize actionable correctness, security, concurrency,
|
|
7
|
+
and performance regressions. Explain the failing scenario; avoid speculative
|
|
8
|
+
findings, style-only feedback, and duplicating Ruff or formatting checks.
|
|
9
|
+
|
|
10
|
+
reviews:
|
|
11
|
+
profile: chill
|
|
12
|
+
request_changes_workflow: false
|
|
13
|
+
allow_author_approval: false
|
|
14
|
+
high_level_summary: false
|
|
15
|
+
review_status: true
|
|
16
|
+
collapse_walkthrough: true
|
|
17
|
+
sequence_diagrams: false
|
|
18
|
+
poem: false
|
|
19
|
+
in_progress_fortune: false
|
|
20
|
+
suggested_labels: false
|
|
21
|
+
auto_apply_labels: false
|
|
22
|
+
suggested_reviewers: false
|
|
23
|
+
auto_assign_reviewers: false
|
|
24
|
+
fail_commit_status: false
|
|
25
|
+
auto_review:
|
|
26
|
+
enabled: true
|
|
27
|
+
auto_incremental_review: true
|
|
28
|
+
# Bound review noise and usage on frequently updated PRs. Resume on demand.
|
|
29
|
+
auto_pause_after_reviewed_commits: 5
|
|
30
|
+
drafts: false
|
|
31
|
+
# The default branch (main) is always included; no additional target branches.
|
|
32
|
+
base_branches: []
|
|
33
|
+
ignore_title_keywords:
|
|
34
|
+
- "[skip ai review]"
|
|
35
|
+
path_filters:
|
|
36
|
+
- "!Cargo.lock"
|
|
37
|
+
- "!uv.lock"
|
|
38
|
+
- "!python/kcoral/server/_generated/**"
|
|
39
|
+
- "!docs/_static/brand/**"
|
|
40
|
+
path_instructions:
|
|
41
|
+
- path: "**/*"
|
|
42
|
+
instructions: >-
|
|
43
|
+
KCoral executes client-supplied programs on trusted, isolated networks.
|
|
44
|
+
Intentional remote execution is part of the API, not by itself a new
|
|
45
|
+
vulnerability. Review changes for regressions against the documented
|
|
46
|
+
trust model, isolation, resource bounds, cleanup, and protocol contracts.
|
|
47
|
+
Report concrete failures introduced by the diff and cite affected code.
|
|
48
|
+
- path: "python/kcoral/runtime/**"
|
|
49
|
+
instructions: >-
|
|
50
|
+
Check GPU lease ownership, single- and multi-GPU scheduling, CPU-only
|
|
51
|
+
transitions, cancellation, timeouts, worker death, and descendant cleanup.
|
|
52
|
+
Check that failure paths release capacity and cannot leave a GPU leased
|
|
53
|
+
forever. Compilation may initialize CUDA; do not assume it is CPU-only.
|
|
54
|
+
- path: "python/kcoral/server/**"
|
|
55
|
+
instructions: >-
|
|
56
|
+
Check bounded request and response handling, multipart validation,
|
|
57
|
+
content hashes, cache pinning and eviction, filesystem races, backpressure,
|
|
58
|
+
cancellation, and tunnel reconnection. Keep blocking work off the event
|
|
59
|
+
loop and preserve the protocol in docs/client-guide/protocol.md.
|
|
60
|
+
- path: "python/kcoral/support/**"
|
|
61
|
+
instructions: >-
|
|
62
|
+
Check sandbox mounts, path and symlink handling, spawn failures, temporary
|
|
63
|
+
directory cleanup, and process lifetime. Preserve documented behavior when
|
|
64
|
+
bubblewrap is unavailable and avoid broadening access to host resources.
|
|
65
|
+
- path: "python/kcoral/client/**"
|
|
66
|
+
instructions: >-
|
|
67
|
+
Check HTTP protocol compatibility, cache-miss retry semantics, response
|
|
68
|
+
validation, and resource closure. Never replay a possibly executed program
|
|
69
|
+
automatically after an ambiguous transport failure.
|
|
70
|
+
- path: "rust/kcoral/**"
|
|
71
|
+
instructions: >-
|
|
72
|
+
Check node and slot identity, admission and capacity accounting, bounded
|
|
73
|
+
streaming, cancellation safety, shutdown, supervisor child cleanup, and
|
|
74
|
+
the unknown-outcome boundary after request bytes reach an execution slot.
|
|
75
|
+
Keep the protobuf contract compatible with the Python tunnel and review
|
|
76
|
+
changes to the source .proto instead of generated bindings.
|
|
77
|
+
- path: "tests/**"
|
|
78
|
+
instructions: >-
|
|
79
|
+
Prefer deterministic tests for observable failures, especially resource
|
|
80
|
+
release and protocol compatibility. Distinguish CPU process/protocol
|
|
81
|
+
coverage from real GPU lease and CUDA behavior; simulated workers do not
|
|
82
|
+
prove GPU correctness. Avoid timing-based assertions when synchronization
|
|
83
|
+
can express the requirement.
|
|
84
|
+
- path: ".github/workflows/**"
|
|
85
|
+
instructions: >-
|
|
86
|
+
Check token permissions, fork PR trust boundaries, secret exposure, and
|
|
87
|
+
release/deployment conditions. Do not run untrusted PR code with privileged
|
|
88
|
+
credentials. Preserve existing build, docs, and publishing behavior.
|
|
89
|
+
finishing_touches:
|
|
90
|
+
docstrings:
|
|
91
|
+
enabled: false
|
|
92
|
+
unit_tests:
|
|
93
|
+
enabled: false
|
|
94
|
+
simplify:
|
|
95
|
+
enabled: false
|
|
96
|
+
autofix:
|
|
97
|
+
enabled: false
|
|
98
|
+
fix_ci:
|
|
99
|
+
enabled: false
|
|
100
|
+
resolve_merge_conflict:
|
|
101
|
+
enabled: false
|
|
102
|
+
|
|
103
|
+
chat:
|
|
104
|
+
auto_reply: false
|
|
105
|
+
# External contributors still receive automatic reviews.
|
|
106
|
+
allow_non_org_members: false
|
|
107
|
+
|
|
108
|
+
knowledge_base:
|
|
109
|
+
opt_out: true
|
|
110
|
+
web_search:
|
|
111
|
+
enabled: false
|
|
112
|
+
automatic_linking_mode: disabled
|
|
113
|
+
linked_repositories: []
|
|
114
|
+
|
|
115
|
+
issue_enrichment:
|
|
116
|
+
auto_enrich:
|
|
117
|
+
enabled: false
|
|
118
|
+
planning:
|
|
119
|
+
enabled: false
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: Build wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
tags: ['v[0-9]*']
|
|
8
|
+
workflow_call:
|
|
9
|
+
inputs:
|
|
10
|
+
ref:
|
|
11
|
+
description: 'Optional tag, branch, or SHA; defaults to the caller ref'
|
|
12
|
+
type: string
|
|
13
|
+
required: false
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
inputs:
|
|
16
|
+
ref:
|
|
17
|
+
description: 'Optional tag, branch, or SHA; defaults to the selected workflow ref'
|
|
18
|
+
type: string
|
|
19
|
+
required: false
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build-linux:
|
|
26
|
+
name: Linux ${{ matrix.arch }}
|
|
27
|
+
runs-on: ${{ matrix.os }}
|
|
28
|
+
timeout-minutes: 40
|
|
29
|
+
strategy:
|
|
30
|
+
fail-fast: false
|
|
31
|
+
matrix:
|
|
32
|
+
include:
|
|
33
|
+
- {os: ubuntu-24.04, arch: x86_64}
|
|
34
|
+
- {os: ubuntu-24.04-arm, arch: aarch64}
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
37
|
+
with:
|
|
38
|
+
ref: ${{ inputs.ref || github.ref }}
|
|
39
|
+
fetch-depth: 0
|
|
40
|
+
persist-credentials: false
|
|
41
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
42
|
+
with:
|
|
43
|
+
python-version: '3.12'
|
|
44
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
45
|
+
- name: Build and smoke-test manylinux wheels
|
|
46
|
+
uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55 # v4.1.0
|
|
47
|
+
env:
|
|
48
|
+
# The wheel has no Python ABI dependency; build once per architecture.
|
|
49
|
+
CIBW_BUILD: cp310-manylinux_${{ matrix.arch }}
|
|
50
|
+
CIBW_ARCHS_LINUX: ${{ matrix.arch }}
|
|
51
|
+
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
|
|
52
|
+
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
|
|
53
|
+
CIBW_BEFORE_ALL_LINUX: >-
|
|
54
|
+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh &&
|
|
55
|
+
sh /tmp/rustup-init.sh -y --profile minimal --default-toolchain 1.87.0
|
|
56
|
+
CIBW_ENVIRONMENT_LINUX: 'PATH="$HOME/.cargo/bin:$PATH" KCORAL_BUILD_RUST=1'
|
|
57
|
+
CIBW_TEST_COMMAND: kcoral router --help && kcoral-node --help
|
|
58
|
+
with:
|
|
59
|
+
output-dir: wheelhouse
|
|
60
|
+
- name: Check wheel metadata
|
|
61
|
+
run: uv tool run twine check --strict wheelhouse/*.whl
|
|
62
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
63
|
+
with:
|
|
64
|
+
name: kcoral-dist-linux-${{ matrix.arch }}
|
|
65
|
+
path: wheelhouse/*.whl
|
|
66
|
+
if-no-files-found: error
|
|
67
|
+
|
|
68
|
+
build-pure:
|
|
69
|
+
name: Pure wheel and sdist
|
|
70
|
+
runs-on: ubuntu-24.04
|
|
71
|
+
timeout-minutes: 15
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
74
|
+
with:
|
|
75
|
+
ref: ${{ inputs.ref || github.ref }}
|
|
76
|
+
fetch-depth: 0
|
|
77
|
+
persist-credentials: false
|
|
78
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
79
|
+
with:
|
|
80
|
+
python-version: '3.12'
|
|
81
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
82
|
+
- name: Build the sdist and a wheel without the Rust programs
|
|
83
|
+
env:
|
|
84
|
+
KCORAL_BUILD_RUST: '0'
|
|
85
|
+
run: uv build --out-dir dist
|
|
86
|
+
- name: Check the wheel is pure
|
|
87
|
+
run: |
|
|
88
|
+
wheel=$(ls dist/*-py3-none-any.whl)
|
|
89
|
+
if unzip -l "$wheel" | grep -E 'kcoral-(router|node)$'; then exit 1; fi
|
|
90
|
+
- name: Check metadata
|
|
91
|
+
run: uv tool run twine check --strict dist/*.whl dist/*.tar.gz
|
|
92
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
93
|
+
with:
|
|
94
|
+
name: kcoral-dist-pure
|
|
95
|
+
path: |
|
|
96
|
+
dist/*.whl
|
|
97
|
+
dist/*.tar.gz
|
|
98
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
tags: ['v[0-9]*']
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: write
|
|
12
|
+
pages: write
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: documentation-${{ github.event_name == 'pull_request' && github.ref || 'publish' }}
|
|
16
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
PUBLISH: ${{ github.repository == 'mlc-ai/kcoral' && github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) }}
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
build:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
# A new release rebuilds latest from main as well as every release tag.
|
|
28
|
+
ref: ${{ startsWith(github.ref, 'refs/tags/') && 'main' || github.ref }}
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: '3.12'
|
|
33
|
+
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
cache-dependency-glob: |
|
|
37
|
+
docs/requirements.txt
|
|
38
|
+
pyproject.toml
|
|
39
|
+
- name: Build the documentation website
|
|
40
|
+
run: python scripts/build_docs.py ${{ github.event_name == 'pull_request' && '--latest-only' || '' }}
|
|
41
|
+
- name: Publish to gh-pages
|
|
42
|
+
if: env.PUBLISH == 'true'
|
|
43
|
+
uses: peaceiris/actions-gh-pages@329bcc8f12caed2cefe5a5b80781499a6f3b361b # v4
|
|
44
|
+
with:
|
|
45
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
46
|
+
publish_dir: _site
|
|
47
|
+
publish_branch: gh-pages
|
|
48
|
+
cname: kcoral.mlc.ai
|
|
49
|
+
- name: Request GitHub Pages build
|
|
50
|
+
if: env.PUBLISH == 'true'
|
|
51
|
+
env:
|
|
52
|
+
GH_TOKEN: ${{ github.token }}
|
|
53
|
+
# GITHUB_TOKEN pushes do not automatically trigger a Pages build.
|
|
54
|
+
run: gh api --method POST "repos/$GITHUB_REPOSITORY/pages/builds"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: pypi-${{ github.event.release.tag_name }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
uses: ./.github/workflows/build_wheels.yml
|
|
17
|
+
with:
|
|
18
|
+
ref: refs/tags/${{ github.event.release.tag_name }}
|
|
19
|
+
|
|
20
|
+
publish:
|
|
21
|
+
needs: build
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
environment:
|
|
24
|
+
name: pypi
|
|
25
|
+
url: https://pypi.org/p/kcoral
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
28
|
+
with:
|
|
29
|
+
pattern: kcoral-dist-*
|
|
30
|
+
merge-multiple: true
|
|
31
|
+
path: dist
|
|
32
|
+
- name: Publish to PyPI
|
|
33
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
34
|
+
with:
|
|
35
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
36
|
+
attestations: false
|
|
37
|
+
verbose: false
|
kcoral-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# OS
|
|
2
|
+
.DS_Store
|
|
3
|
+
Thumbs.db
|
|
4
|
+
|
|
5
|
+
# Editors
|
|
6
|
+
.idea/
|
|
7
|
+
.vscode/
|
|
8
|
+
*.swp
|
|
9
|
+
*.swo
|
|
10
|
+
|
|
11
|
+
# Python
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.py[cod]
|
|
14
|
+
*.egg-info/
|
|
15
|
+
venv/
|
|
16
|
+
|
|
17
|
+
# Build artifacts
|
|
18
|
+
build/
|
|
19
|
+
dist/
|
|
20
|
+
docs/_build/
|
|
21
|
+
_site/
|
|
22
|
+
.docs-venv/
|
|
23
|
+
target/
|
|
24
|
+
|
|
25
|
+
# Misc
|
|
26
|
+
*.log
|
|
27
|
+
tmp/
|
|
28
|
+
**/logs
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Formatting and hygiene checks.
|
|
2
|
+
#
|
|
3
|
+
# Run on the whole repo:
|
|
4
|
+
#
|
|
5
|
+
# uvx pre-commit run --all-files
|
|
6
|
+
#
|
|
7
|
+
# Or install as a git hook so it runs on every commit:
|
|
8
|
+
#
|
|
9
|
+
# uvx pre-commit install
|
|
10
|
+
#
|
|
11
|
+
# Update pinned hook versions with:
|
|
12
|
+
#
|
|
13
|
+
# uvx pre-commit autoupdate
|
|
14
|
+
|
|
15
|
+
repos:
|
|
16
|
+
# Standard hygiene hooks
|
|
17
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
18
|
+
rev: v6.0.0
|
|
19
|
+
hooks:
|
|
20
|
+
- id: check-added-large-files
|
|
21
|
+
# Preserve the original high-resolution icon.
|
|
22
|
+
exclude: ^docs/_static/brand/kcoral-icon\.png$
|
|
23
|
+
- id: check-case-conflict
|
|
24
|
+
- id: check-merge-conflict
|
|
25
|
+
- id: check-symlinks
|
|
26
|
+
- id: check-yaml
|
|
27
|
+
- id: check-toml
|
|
28
|
+
- id: end-of-file-fixer
|
|
29
|
+
- id: mixed-line-ending
|
|
30
|
+
- id: trailing-whitespace
|
|
31
|
+
|
|
32
|
+
# Python lint + format; configured in pyproject.toml [tool.ruff].
|
|
33
|
+
# ruff-check with the "I" rules also handles import sorting (isort).
|
|
34
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
35
|
+
rev: v0.15.22
|
|
36
|
+
hooks:
|
|
37
|
+
- id: ruff-check
|
|
38
|
+
args: [--fix]
|
|
39
|
+
- id: ruff-format
|