Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .dprint.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
},
"json": {
},
// Match the repo-wide 120 line-length set in .editorconfig and ruff.toml,
// otherwise dprint's bundled ruff would reformat Python files to its
// default and fight with `mise run ruff-fmt`.
"ruff": {
"lineLength": 120,
},
"malva": {
},
"markdown": {
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ jobs:
mise install
env:
GITHUB_TOKEN: ${{ github.token }}
# GitHub release downloads occasionally take longer than mise's
# default 30s HTTP timeout; bump it so transient network slowness
# doesn't fail the whole `mise install` step.
MISE_HTTP_TIMEOUT: "120"

- name: Run checkers
run: |
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
mise install
env:
GITHUB_TOKEN: ${{ github.token }}
# Match check.yml: bump mise's 30s HTTP timeout so GitHub-release
# downloads don't fail the install on transient slowness.
MISE_HTTP_TIMEOUT: "120"

- name: Fetch MNIST model
run: mise run fetch-mnist-rclone
Expand Down
21 changes: 15 additions & 6 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
[tools]
action-validator = "latest"
"cargo:ast-grep" = "latest"
cargo-binstall = "latest"
"cargo:ast-grep" = "latest"
"cargo:aube" = "latest"
"cargo:taplo-cli" = "latest"
"cargo:wasm-pack" = "latest"
"chromedriver" = "146"
claude = "latest"
cmake = "latest"
codex = "latest"
dart = { version = "latest", url = "https://storage.googleapis.com/dart-archive/channels/stable/release/{{ version }}/sdk/dartsdk-{{ os() }}-{{ arch() }}-release.zip", version_expr = 'fromJSON(body).prefixes | filter({ # matches "^channels/stable/release/(\\d+\\.\\d+\\.\\d+)/$" }) | map({split(#, "/")[3]}) | sortVersions()', version_list_url = "https://storage.googleapis.com/storage/v1/b/dart-archive/o?prefix=channels/stable/release/&delimiter=/" }
dotnet = "latest"
dotnet-core = "latest"
"dotnet:roslynator.dotnet.cli" = "latest"
dprint = "latest"
editorconfig-checker = "latest"
gemini-cli = "latest"
"github:block/goose" = "latest"
"github:grok-rs/waitup" = "latest"
"github:wasm-bindgen/wasm-bindgen" = "0.2.114"
java = "latest"
Expand All @@ -25,7 +21,6 @@ mprocs = "latest"
node = "22"
"npm:onnxruntime-web" = "latest"
"npm:pyodide" = "0.29.3"
ollama = "latest"
osv-scanner = "latest"
pipx = "latest"
"pipx:cmake" = "latest"
Expand Down Expand Up @@ -129,6 +124,20 @@ run = "typos"
depends = ["cargo-check"]
run = "osv-scanner --lockfile Cargo.lock"

[tasks.prefetch]
depends = ["download-models"]
description = "Pre-download all dependencies and models (Rust crates, Dart packages, Python envs, Java/Maven, .NET, Node, WIT)"
run = """
cargo check --workspace
dart pub get --directory services/ws-modules/dart-comm1
uv sync --directory services/ws-modules/pydata1
uv sync --directory services/ws-modules/pyface1
mvn dependency:resolve --quiet
dotnet restore
npm install --prefix services/ws-server/static
zig build --fetch --build-file services/ws-modules/zig-data1/build.zig
"""

[tasks.regenerate-verification]
alias = "regen-verification"
description = "Regenerate checked-in verification output files"
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ resolver = "2"
actix = "0.13"
actix-rt = "2"
actix-web = { version = "4", features = ["rustls-0_23"] }
anyhow = "1.0"
base64 = "0.22.1"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.4", features = ["derive"] }
Expand Down
21 changes: 21 additions & 0 deletions config/ast-grep/rules/no-anyhow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
id: no-anyhow
language: Rust
severity: error
message: |
The `anyhow` crate is forbidden.
Define an error enum with `thiserror`.
rule:
any:
- all:
- kind: use_declaration
- regex: '\banyhow\b'
- all:
- kind: scoped_identifier
- regex: "^anyhow::"
- all:
- kind: scoped_use_list
- regex: '\banyhow\b'
- kind: macro_invocation
pattern: anyhow!($$$ARGS)
ignores:
- generated/**
12 changes: 12 additions & 0 deletions config/ast-grep/rules/no-inline-mod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
id: no-inline-mod
language: Rust
severity: error
message: |
Inline `mod X { ... }` blocks are forbidden. Move the module body into a
separate file (`X.rs` or `X/mod.rs`) and declare it with `mod X;` instead.
rule:
kind: mod_item
has:
kind: declaration_list
ignores:
- generated/**
2 changes: 2 additions & 0 deletions config/ast-grep/rules/no-rust-line-continuation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ message: |
rule:
kind: string_literal
regex: '\\\n'
ignores:
- generated/**
23 changes: 23 additions & 0 deletions config/ast-grep/rules/no-shadow-result.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
id: no-shadow-result
language: Rust
severity: error
message: |
Don't shadow `std::result::Result` at file scope — every bare `Result<T>`
then becomes ambiguous to readers. Either spell the error type at each
call site (`Result<T, my::Error>`), reference the local alias by its
qualified path (`crate::Result<T>`, `et_int_gen::Result<T>`), or alias
the import (`use foo::Result as FooResult;`).
rule:
any:
- all:
- kind: type_item
- has:
kind: type_identifier
regex: "^Result$"
- all:
- kind: use_declaration
- regex: '\bResult\b'
- not:
regex: '\bResult\s+as\s'
ignores:
- generated/**
4 changes: 1 addition & 3 deletions services/ws-modules/pydata1/pydata1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
from datetime import datetime, timezone


async def run(
ws_send, wait_for_response, put_file, get_file, sleep_ms, log, set_status
) -> None:
async def run(ws_send, wait_for_response, put_file, get_file, sleep_ms, log, set_status) -> None:
"""Execute the data1 workflow: connect, store, fetch, verify."""
log("pydata1: entered run()")

Expand Down
18 changes: 4 additions & 14 deletions services/ws-modules/pyface1/pyface1/face_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,8 @@ def preprocess_geometry(source_width: float, source_height: float) -> dict[str,
)
return {
"resize_ratio": resize_ratio,
"resized_width": float(
int(clamp(round(source_width * resize_ratio), 1, FACE_INPUT_WIDTH))
),
"resized_height": float(
int(clamp(round(source_height * resize_ratio), 1, FACE_INPUT_HEIGHT))
),
"resized_width": float(int(clamp(round(source_width * resize_ratio), 1, FACE_INPUT_WIDTH))),
"resized_height": float(int(clamp(round(source_height * resize_ratio), 1, FACE_INPUT_HEIGHT))),
}


Expand Down Expand Up @@ -205,11 +201,7 @@ def decode_outputs(
landm = output_values(landm_values, "landm", 10)
prior_count = len(loc) // 4

if (
prior_count == 0
or len(conf) != prior_count * 2
or len(landm) != prior_count * 10
):
if prior_count == 0 or len(conf) != prior_count * 2 or len(landm) != prior_count * 10:
raise ValueError("RetinaFace outputs had unexpected shapes")

priors = model_priors()
Expand Down Expand Up @@ -256,9 +248,7 @@ def decode_outputs(
}


def status_text(
input_name: str, output_names: Iterable[object], summary: DetectionSummary
) -> str:
def status_text(input_name: str, output_names: Iterable[object], summary: DetectionSummary) -> str:
"""Render the browser status text used by the face detection demo."""
outputs = ", ".join(str(name) for name in output_names)
lines = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,7 @@ def _entry(binding: int, read_only: bool) -> GpuBindGroupLayoutEntry:
binding=binding,
visibility=GpuShaderStage.compute(),
buffer=GpuBufferBindingLayout(
type=GpuBufferBindingType.READ_ONLY_STORAGE
if read_only
else GpuBufferBindingType.STORAGE,
type=GpuBufferBindingType.READ_ONLY_STORAGE if read_only else GpuBufferBindingType.STORAGE,
has_dynamic_offset=False,
min_binding_size=None,
),
Expand Down Expand Up @@ -280,15 +278,11 @@ def _run_matmul() -> dict:
label="matmul-bgl",
)
)
pl = device.create_pipeline_layout(
GpuPipelineLayoutDescriptor(bind_group_layouts=[bgl], label="matmul-pl")
)
pl = device.create_pipeline_layout(GpuPipelineLayoutDescriptor(bind_group_layouts=[bgl], label="matmul-pl"))

pipeline = device.create_compute_pipeline(
GpuComputePipelineDescriptor(
compute=GpuProgrammableStage(
module=shader, entry_point="main", constants=None
),
compute=GpuProgrammableStage(module=shader, entry_point="main", constants=None),
layout=GpuLayoutMode_Specific(value=pl),
label="matmul-pipeline",
)
Expand Down Expand Up @@ -325,9 +319,7 @@ def _run_matmul() -> dict:

result_c00 = struct.unpack("<f", bytes(data[:4]))[0]
if abs(result_c00 - EXPECTED_C00) > 1e-4:
raise RuntimeError(
f"wasi-webgpu: matmul produced C[0][0]={result_c00}, expected {EXPECTED_C00}"
)
raise RuntimeError(f"wasi-webgpu: matmul produced C[0][0]={result_c00}, expected {EXPECTED_C00}")
_log(f"wasi-webgpu matmul: C[0][0]={result_c00:.4f} in {elapsed_ms:.2f}ms")

return {
Expand Down Expand Up @@ -380,9 +372,7 @@ def _mnist_inference() -> dict:

out_name, out_tensor = outputs[0]
if out_name != MNIST_OUTPUT_NAME:
_log(
f"warning: output name {out_name!r} differs from expected {MNIST_OUTPUT_NAME!r}"
)
_log(f"warning: output name {out_name!r} differs from expected {MNIST_OUTPUT_NAME!r}")

raw = out_tensor.data()
arr = array.array("f")
Expand All @@ -396,9 +386,7 @@ def _mnist_inference() -> dict:
_log(f"predicted class: {predicted}, logits: {[round(v, 3) for v in logits]}")

if predicted != EXPECTED_MNIST_CLASS:
raise RuntimeError(
f"MNIST verification FAILED: predicted {predicted}, expected {EXPECTED_MNIST_CLASS}"
)
raise RuntimeError(f"MNIST verification FAILED: predicted {predicted}, expected {EXPECTED_MNIST_CLASS}")
_log("MNIST verification: ok")

return {
Expand Down
42 changes: 42 additions & 0 deletions services/ws-wasi-runner/src/bindings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//! `wasmtime::component::bindgen!` output for the runner world.
//!
//! Lives in its own file so `no-inline-mod` can stay enforced on the
//! crate root: the macro generates a `mod`-shaped tree of types, which
//! would otherwise have to be wrapped in `pub mod bindings { ... }` at
//! the `lib.rs` top level.

wasmtime::component::bindgen!({
path: "wit",
world: "runner",
imports: { default: async },
exports: { default: async },
// Map every wasi-webgpu resource to a payload type owned by us so
// resource_table operations work on real wgpu objects rather than
// bindgen-generated marker structs. The types live in
// `host::wasi_webgpu` and are wgpu-backed for the matmul subset.
with: {
"wasi:keyvalue/store.bucket": super::host::wasi_keyvalue::Bucket,
"wasi:webgpu/webgpu.gpu": super::host::wasi_webgpu::Gpu,
"wasi:webgpu/webgpu.gpu-adapter": super::host::wasi_webgpu::GpuAdapter,
"wasi:webgpu/webgpu.gpu-adapter-info": super::host::wasi_webgpu::GpuAdapterInfo,
"wasi:webgpu/webgpu.gpu-supported-features": super::host::wasi_webgpu::GpuSupportedFeatures,
"wasi:webgpu/webgpu.gpu-supported-limits": super::host::wasi_webgpu::GpuSupportedLimits,
"wasi:webgpu/webgpu.gpu-device": super::host::wasi_webgpu::GpuDevice,
"wasi:webgpu/webgpu.gpu-queue": super::host::wasi_webgpu::GpuQueue,
"wasi:webgpu/webgpu.gpu-buffer": super::host::wasi_webgpu::GpuBuffer,
"wasi:webgpu/webgpu.gpu-buffer-usage": super::host::wasi_webgpu::GpuBufferUsage,
"wasi:webgpu/webgpu.gpu-map-mode": super::host::wasi_webgpu::GpuMapMode,
"wasi:webgpu/webgpu.gpu-shader-stage": super::host::wasi_webgpu::GpuShaderStage,
"wasi:webgpu/webgpu.gpu-bind-group-layout": super::host::wasi_webgpu::GpuBindGroupLayout,
"wasi:webgpu/webgpu.gpu-bind-group": super::host::wasi_webgpu::GpuBindGroup,
"wasi:webgpu/webgpu.gpu-pipeline-layout": super::host::wasi_webgpu::GpuPipelineLayout,
"wasi:webgpu/webgpu.gpu-shader-module": super::host::wasi_webgpu::GpuShaderModule,
"wasi:webgpu/webgpu.gpu-compute-pipeline": super::host::wasi_webgpu::GpuComputePipeline,
"wasi:webgpu/webgpu.gpu-command-encoder": super::host::wasi_webgpu::GpuCommandEncoder,
"wasi:webgpu/webgpu.gpu-compute-pass-encoder": super::host::wasi_webgpu::GpuComputePassEncoder,
"wasi:webgpu/webgpu.gpu-command-buffer": super::host::wasi_webgpu::GpuCommandBuffer,
"wasi:webgpu/webgpu.record-option-gpu-size64": super::host::wasi_webgpu::RecordOptionGpuSize64,
"wasi:webgpu/webgpu.record-gpu-pipeline-constant-value":
super::host::wasi_webgpu::RecordGpuPipelineConstantValue,
},
});
Loading
Loading