{"id":50683009,"url":"https://github.com/julian-corbet/sporewright","last_synced_at":"2026-06-08T20:30:31.540Z","repository":{"id":363380186,"uuid":"1255449943","full_name":"julian-corbet/sporewright","owner":"julian-corbet","description":"A self-learning, multi-objective router for LLM and work routing — Rust + TypeScript (byte-equivalent), with failover, online learning, and a device↔orchestrator protocol","archived":false,"fork":false,"pushed_at":"2026-06-08T16:17:12.000Z","size":234,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T18:16:08.221Z","etag":null,"topics":["ai-agents","failover","llm","llm-router","load-balancing","orchestration","resilience","router","rust","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/julian-corbet.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-31T20:57:47.000Z","updated_at":"2026-06-08T16:17:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/julian-corbet/sporewright","commit_stats":null,"previous_names":["julian-corbet/sporewright"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/julian-corbet/sporewright","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julian-corbet%2Fsporewright","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julian-corbet%2Fsporewright/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julian-corbet%2Fsporewright/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julian-corbet%2Fsporewright/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/julian-corbet","download_url":"https://codeload.github.com/julian-corbet/sporewright/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/julian-corbet%2Fsporewright/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34080025,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","failover","llm","llm-router","load-balancing","orchestration","resilience","router","rust","typescript"],"created_at":"2026-06-08T20:30:28.383Z","updated_at":"2026-06-08T20:30:31.532Z","avatar_url":"https://github.com/julian-corbet.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/logo.svg\" alt=\"sporewright\" width=\"380\"\u003e\n\u003c/p\u003e\n\n# sporewright\n\n[![CI](https://github.com/julian-corbet/sporewright/actions/workflows/ci.yml/badge.svg)](https://github.com/julian-corbet/sporewright/actions/workflows/ci.yml)\n[![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)\n[![Docs](https://img.shields.io/badge/docs-the%20model-brightgreen.svg)](docs/MODEL.md)\n[![Cores](https://img.shields.io/badge/cores-Rust%20%2B%20TypeScript-orange.svg)](#the-object)\n\nA **self-learning, multi-objective router** — one object, a sparse tensor, and the\noperations on it. It answers one question for any kind of work (LLM calls, scraping,\nrendering, embedding…) across any set of providers or devices (browser tabs, shells,\ncontainers, servers, reachable peers):\n\n\u003e Given everything that *could* do this, in what order should *this* device try the\n\u003e options, what happens when one fails, and how does the order improve as we learn?\n\nThe engine has **no opinions about your domain**, and the same core ships in **Rust\nand TypeScript, decision-equivalent**, so a browser tab and a server agree.\n\n## The object\n\nEverything is a read or write on one sparse tensor:\n\n```\nT[ level ][ instance ][ option ][ dimension ]  →  value\n```\n\n- **level** — a fixed, ordered hierarchy, coarse→fine (`global ≺ workspace ≺ … ≺ device`).\n- **instance** — the horizontal axis a level spawns: `global` is one (`\"\"`); `workspace`/`device` branch one-per-id.\n- **option** — the candidates; the resolved **queue is a vector along this axis**.\n- **dimension** — the per-option decision parameters (`latency`, `financial`, `reliability`, a gate…). A dimension's **weight** lives one axis coarser.\n\nYou read with a **cursor** (one instance per axis — `{workspace: acme, device: A}`).\nThree operators:\n\n- **fold** — collapse the level axis; the deepest set cell wins (most-specific inheritance, the CSS cascade).\n- **resolve** — collapse the dimension axis; `Σ w·v`, a `+∞` gate drops the option, order ascending → the queue.\n- **reduce** — the one path *up*: the median over a level's instances, the orchestrator's trusted aggregation.\n\nWrites obey **write-down** (a device sets its own slice, never the shared levels), and\nrobustness is the orchestrator reading where evidence is thin — not metadata in the\ncells. The full model, maths, and design choices are in **[docs/MODEL.md](docs/MODEL.md)**;\nfor *why* one `resolve` becomes a self-learning, multi-objective, resource-aware router\n— the three-role dimension vector, the Lagrangian-dual maths, and eight worked stories —\nread **[docs/ROUTING-MODEL.md](docs/ROUTING-MODEL.md)**.\n\n## Quickstart\n\n**Rust** (`crates/sporewright`)\n\n```rust\nuse sporewright::tensor::{Tensor, Cursor};\n\nlet mut t = Tensor::new([\"global\", \"workspace\", \"device\"]);\nlet mut w = t.writer(\"global\").unwrap();\nw.set_value(\"global\", \"\", \"groq\", \"latency\", 0.4).unwrap();\nw.set_value(\"global\", \"\", \"cerebras\", \"latency\", 0.3).unwrap();\nw.set_weight(\"global\", \"\", \"latency\", 1.0).unwrap();\n\n// a premium workspace loosens a weight on its own slice; a device records its own value\nw.set_value(\"device\", \"A\", \"groq\", \"latency\", 0.05).unwrap();\n\nlet mut cursor = Cursor::new();\ncursor.insert(\"device\".into(), \"A\".into());\nassert_eq!(t.resolve(\u0026cursor), vec![\"groq\".to_string(), \"cerebras\".to_string()]);\n```\n\n**TypeScript** (`packages/sporewright`) — same model, decision-equivalent.\n\n```ts\nimport { Tensor } from \"sporewright\";\n\nconst t = new Tensor([\"global\", \"workspace\", \"device\"]);\nconst w = t.writer(\"global\")!;\nw.setValue(\"global\", \"\", \"groq\", \"latency\", 0.4);\nw.setValue(\"global\", \"\", \"cerebras\", \"latency\", 0.3);\nw.setWeight(\"global\", \"\", \"latency\", 1.0);\nw.setValue(\"device\", \"A\", \"groq\", \"latency\", 0.05);\n\nt.resolve({ device: \"A\" }); // -\u003e [\"groq\", \"cerebras\"]\n```\n\n## Build\n\n```\ncargo test -p sporewright          # the Rust core\ncd packages/sporewright \u0026\u0026 bun test # the TypeScript core\n```\n\nThe two cores are kept decision-equivalent (the wire round-trips); see\n[CONTRIBUTING.md](CONTRIBUTING.md) and [SCOPE.md](SCOPE.md) (what lives in the\nengine vs the product).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjulian-corbet%2Fsporewright","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjulian-corbet%2Fsporewright","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjulian-corbet%2Fsporewright/lists"}