ruby_llm_mesh 0.1.0 → 2.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f335121a2c16a9ca428f4d5110b69f6caf999d4534358cd6c68d668382c9130
4
- data.tar.gz: ec867f6d775e2ba68d5922136ebc7e6a3af52dbf213fad8016c0f613e92a25ca
3
+ metadata.gz: 31ce7f20e5d73fed9453fd89263d03eda29cff41fc4d4d28da6d815f9870841e
4
+ data.tar.gz: e83f9c1bb73712fa1a89660670d6e20efad8cb9985e21c8a7bd6d4f2bb5b5e7b
5
5
  SHA512:
6
- metadata.gz: 4c094b33bdaa1f55997d3f3719d25d4591b0daeaf23930e6868dab33b65a745560fc6bc43aadd711303d3b8cbb12ce4856f149825104d8d96401b2818c340ec7
7
- data.tar.gz: 1b99d7efe252cacc5074257ac8c950d5bd6e84d68beb5a15edd3bc05c64c0499283a98befdfa74a09a2494182e6d68690a1ab69710a799a08bef9b924fd087c1
6
+ metadata.gz: 605e9074bd646d136d3f8bd68f306d052bb4b71571e6c40f72715d2ebf2b7623088a4b5838e41a04d344e3002dd1992eea7d3d053883c4ffa79c94973c7b7c7c
7
+ data.tar.gz: b69e55002426df41be4cac00907c8c4c1c93dea524614875bf731ee12acb3915c852d380aa12a123585e278d463d5380ed4b37ff3aa620b8cc817579029c03e2
data/CHANGELOG.md CHANGED
@@ -5,6 +5,59 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.2.0] - 2026-08-14
9
+
10
+ ### Added
11
+
12
+ - **Provider retries with exponential backoff** — `max_retries` now retries transient `TimeoutError`, `RateLimitError`, and 5xx/transport `ProviderError`s before falling over
13
+ - `retry_backoff` (default `0.1s`, env `RUBY_LLM_MESH_RETRY_BACKOFF`) doubles after each failed attempt
14
+ - Authentication failures are never retried; they fail over immediately when fallback is enabled
15
+
16
+ ## [2.1.0] - 2026-08-11
17
+
18
+ ### Added
19
+
20
+ - **Token/cost budget guard** — opt-in via `budget_enabled`, `budget_max_tokens`, `budget_max_usd`, and `budget_prices`
21
+ - `RubyLlmMesh::Budget` pre-checks estimated usage before provider calls and consumes actual usage from `Response#usage` after success
22
+ - `RubyLlmMesh::BudgetExceededError` when token or USD limits would be exceeded
23
+ - `RubyLlmMesh.budget_status` / `AiAgentRouter.budget_status` for runtime budget telemetry
24
+ - Full Contributor Covenant 2.1 [Code of Conduct](CODE_OF_CONDUCT.md) with enforcement guidelines
25
+ - [Privacy Policy](PRIVACY.md) for the OSS LLM routing gem (no phone-home; data stays with configured endpoints)
26
+ - README, CONTRIBUTING, and docs site links to Code of Conduct and Privacy Policy
27
+
28
+ ### Fixed
29
+
30
+ - Router now honors `fallback: false` when a provider circuit is open or the provider name is unknown (no longer silently continues the ladder)
31
+ - `PeerRegistry#healthy_urls` no longer reintroduces unhealthy peers when the healthy set is empty (LocalNode uses its primary URL as last resort)
32
+ - Circuit breaker half-open state allows a single probe (not unbounded concurrent probes)
33
+ - HTTP client wraps connection reset / SSL / EOF transport errors as `ProviderError` so failover works
34
+ - Redis semantic-cache index cleans up stale entry IDs after TTL expiry
35
+
36
+ ## [2.0.0] - 2026-08-07
37
+
38
+ ### Added
39
+
40
+ - **Sovereign Mesh Core** — optional Rust `chimera_core` cdylib under `ext/chimera_core/` with FFI exports `start_node`, `node_alive`, `execute_wasm_payload`, `stop_node`
41
+ - **`RubyLlmMesh.execute` / `AiAgentRouter.execute`** — strategy-based intent execution (`:auto`, `:p2p_mesh`, `:cloud`, `:openai`, `:anthropic`, `:local_node`, `:local_mesh`)
42
+ - Pure-Ruby **NativeCore fallback** when the shared library or `ffi` load fails (require never hard-crashes)
43
+ - Mesh config: `mesh_port` (default `4233`), `auto_boot_mesh`, `fallback_providers`
44
+ - Optional **semantic cache** (in-memory or Redis when `REDIS_URL` + `redis` gem present)
45
+ - Optional **peer health monitoring** for multi-URL local node meshes (`peer_urls`, `HealthMonitor`)
46
+ - `rake compile` to build chimera_core via cargo
47
+ - Trusted publishing workflow `.github/workflows/release.yml` (OIDC + GitHub Release)
48
+
49
+ ### Changed
50
+
51
+ - Version jump to **2.0.0** (Sovereign Mesh / FFI major)
52
+ - Gem dependency: `ffi ~> 1.17`
53
+ - Cloud failover remains real HTTP (OpenAI / Anthropic / local_node) — not stubbed
54
+
55
+ ### Breaking
56
+
57
+ - Major version bump; consumers pinning `~> 0.1` must opt into `2.0.0`
58
+ - New default mesh settings (`auto_boot_mesh: true`, `mesh_port: 4233`) affect `:auto` / `:p2p_mesh` strategies only — `complete` API behavior is unchanged when semantic cache stays off (default)
59
+ - Trusted publisher workflow filename is now **`release.yml`** (was `push_gem.yml`)
60
+
8
61
  ## [0.1.0] - 2026-08-07
9
62
 
10
63
  ### Added
@@ -16,5 +69,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
69
  - RAG helpers: text chunker, bag-of-words embeddings, tool schema adapters
17
70
  - Optional ActiveRecord `acts_as_ai_agent` for memory, semantic cache, and audit logging
18
71
  - Rails railtie that loads only when Rails is present
72
+ - Documentation site on GitHub Pages
73
+ - Trusted publishing workflow for RubyGems OIDC releases
19
74
 
75
+ [2.2.0]: https://github.com/theworker02/ruby_llm_mesh/releases/tag/v2.2.0
76
+ [2.1.0]: https://github.com/theworker02/ruby_llm_mesh/releases/tag/v2.1.0
77
+ [2.0.0]: https://github.com/theworker02/ruby_llm_mesh/releases/tag/v2.0.0
20
78
  [0.1.0]: https://github.com/theworker02/ruby_llm_mesh/releases/tag/v0.1.0
data/CODE_OF_CONDUCT.md CHANGED
@@ -43,21 +43,95 @@ acceptable behavior and will take appropriate and fair corrective action in
43
43
  response to any behavior that they deem inappropriate, threatening, offensive,
44
44
  or harmful.
45
45
 
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
46
51
  ## Scope
47
52
 
48
53
  This Code of Conduct applies within all community spaces, and also applies when
49
54
  an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
50
58
 
51
59
  ## Enforcement
52
60
 
53
61
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
54
- reported by opening a GitHub issue or contacting the maintainers via the
55
- repository. All complaints will be reviewed and investigated promptly and fairly.
62
+ reported by:
63
+
64
+ * Opening a [GitHub issue](https://github.com/theworker02/ruby_llm_mesh/issues)
65
+ on this repository (prefer a private report when the matter is sensitive), or
66
+ * Contacting the maintainer via their GitHub profile:
67
+ [theworker02](https://github.com/theworker02)
68
+
69
+ All complaints will be reviewed and investigated promptly and fairly.
70
+
71
+ All community leaders are obligated to respect the privacy and security of the
72
+ reporter of any incident.
73
+
74
+ ## Enforcement Guidelines
75
+
76
+ Community leaders will follow these Community Impact Guidelines in determining
77
+ the consequences for any action they deem in violation of this Code of Conduct:
78
+
79
+ ### 1. Correction
80
+
81
+ **Community Impact**: Use of inappropriate language or other behavior deemed
82
+ unprofessional or unwelcome in the community.
83
+
84
+ **Consequence**: A private, written warning from community leaders, providing
85
+ clarity around the nature of the violation and an explanation of why the
86
+ behavior was inappropriate. A public apology may be requested.
87
+
88
+ ### 2. Warning
89
+
90
+ **Community Impact**: A violation through a single incident or series of
91
+ actions.
92
+
93
+ **Consequence**: A warning with consequences for continued behavior. No
94
+ interaction with the people involved, including unsolicited interaction with
95
+ those enforcing the Code of Conduct, for a specified period of time. This
96
+ includes avoiding interactions in community spaces as well as external channels
97
+ like social media. Violating these terms may lead to a temporary or permanent
98
+ ban.
99
+
100
+ ### 3. Temporary Ban
101
+
102
+ **Community Impact**: A serious violation of community standards, including
103
+ sustained inappropriate behavior.
104
+
105
+ **Consequence**: A temporary ban from any sort of interaction or public
106
+ communication with the community for a specified period of time. No public or
107
+ private interaction with the people involved, including unsolicited interaction
108
+ with those enforcing the Code of Conduct, is allowed during this period.
109
+ Violating these terms may lead to a permanent ban.
110
+
111
+ ### 4. Permanent Ban
112
+
113
+ **Community Impact**: Demonstrating a pattern of violation of community
114
+ standards, including sustained inappropriate behavior, harassment of an
115
+ individual, or aggression toward or disparagement of classes of individuals.
116
+
117
+ **Consequence**: A permanent ban from any sort of public interaction within the
118
+ community.
56
119
 
57
120
  ## Attribution
58
121
 
59
122
  This Code of Conduct is adapted from the [Contributor Covenant][homepage],
60
123
  version 2.1, available at
61
- https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
124
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
125
+
126
+ Community Impact Guidelines were inspired by
127
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
128
+
129
+ For answers to common questions about this code of conduct, see the FAQ at
130
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
131
+ [https://www.contributor-covenant.org/translations][translations].
62
132
 
63
133
  [homepage]: https://www.contributor-covenant.org
134
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
135
+ [Mozilla CoC]: https://github.com/mozilla/diversity
136
+ [FAQ]: https://www.contributor-covenant.org/faq
137
+ [translations]: https://www.contributor-covenant.org/translations
data/CONTRIBUTING.md CHANGED
@@ -22,18 +22,24 @@ bundle exec rake test
22
22
  ## Testing
23
23
 
24
24
  Unit tests must not require live provider credentials. Stub HTTP with WebMock or inject stub providers.
25
+ Native FFI tests skip automatically when `chimera_core` is not compiled.
25
26
 
26
27
  ```bash
27
28
  bundle exec rake test
29
+ bundle exec rake compile # optional — requires Rust/cargo
28
30
  ```
29
31
 
30
32
  ## Releases
31
33
 
32
34
  Maintainers cut releases by tagging `vX.Y.Z` on `main`, which triggers the
33
- RubyGems Trusted Publisher workflow (`.github/workflows/push_gem.yml`).
35
+ RubyGems Trusted Publisher workflow (`.github/workflows/release.yml`).
34
36
 
35
37
  See the README for Trusted Publisher setup details.
36
38
 
37
39
  ## Code of Conduct
38
40
 
39
41
  By participating, you agree to uphold our [Code of Conduct](CODE_OF_CONDUCT.md).
42
+
43
+ ## Privacy
44
+
45
+ See [PRIVACY.md](PRIVACY.md) for how this gem handles data (no phone-home telemetry; prompts go only to endpoints you configure).
data/PRIVACY.md ADDED
@@ -0,0 +1,56 @@
1
+ # Privacy Policy
2
+
3
+ **Effective date:** 2026-08-07
4
+ **Applies to:** the open-source `ruby_llm_mesh` Ruby gem and its companion documentation at [github.com/theworker02/ruby_llm_mesh](https://github.com/theworker02/ruby_llm_mesh)
5
+
6
+ ## Summary
7
+
8
+ `ruby_llm_mesh` is a **library you run in your own Ruby/Rails process**. The maintainers of this project do **not** operate a hosted routing service, do **not** receive your prompts by default, and do **not** collect telemetry, analytics, or crash reports from gem usage.
9
+
10
+ ## What this gem does with data
11
+
12
+ When you call APIs such as `AiAgentRouter.execute` / `RubyLlmMesh.complete`, the gem may:
13
+
14
+ 1. **Send prompts and related options** to LLM HTTP endpoints **you configure** (for example OpenAI, Anthropic, or a local OpenAI-compatible node such as Ollama / LM Studio), using API keys and base URLs from your environment or configuration.
15
+ 2. **Run intents through the optional native mesh / pure-Ruby fallback** entirely **inside your process** (and any peers **you** configure).
16
+ 3. **Optionally store prompt/response material** in an in-process or Redis semantic cache **only if you enable** semantic caching and point it at infrastructure you control.
17
+ 4. **Optionally record conversational memory / audits** when you use Rails `acts_as_ai_agent` helpers — that data lives in **your** database attributes.
18
+
19
+ The gem does not phone home to the `ruby_llm_mesh` authors.
20
+
21
+ ## What we do not collect
22
+
23
+ - No usage analytics or phone-home telemetry from the gem
24
+ - No automatic upload of prompts, completions, embeddings, or API keys to project maintainers
25
+ - No account system or user database operated by this project for gem runtime traffic
26
+
27
+ ## Third-party providers
28
+
29
+ If you configure cloud providers, **those providers’ privacy policies apply** to data you send them (prompts, system messages, tools, etc.). Review and configure:
30
+
31
+ - [OpenAI Privacy](https://openai.com/policies/privacy-policy/) (or your compatible endpoint’s policy)
32
+ - [Anthropic Privacy](https://www.anthropic.com/legal/privacy) (or your configured Anthropic-compatible endpoint)
33
+
34
+ Local nodes and peer URLs you list are under **your** operational control and policies.
35
+
36
+ ## Credentials and secrets
37
+
38
+ API keys (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, Redis URLs, etc.) are read from your environment or configuration and used only to talk to endpoints you choose. Do not commit secrets to git. This repository’s tests are designed to run **without** live credentials.
39
+
40
+ ## GitHub / project website
41
+
42
+ Visiting the GitHub repository, Issues, Discussions, or GitHub Pages docs is subject to [GitHub’s Privacy Statement](https://docs.github.com/en/site-policy/privacy-policies/github-privacy-statement). Maintainers may see information you voluntarily provide in issues, PRs, or emails (for example contact details in a Code of Conduct report).
43
+
44
+ ## Children
45
+
46
+ This project is a developer library and is not directed at children.
47
+
48
+ ## Changes
49
+
50
+ Privacy practices for the gem may change as the project evolves. Material updates will be reflected in this file in the repository. Continued use of a newer gem version after an update constitutes awareness of the revised policy for that version’s documented behavior.
51
+
52
+ ## Contact
53
+
54
+ Privacy questions about **this open-source project** (not about third-party LLM vendors): open a GitHub issue in [theworker02/ruby_llm_mesh](https://github.com/theworker02/ruby_llm_mesh/issues) or contact the maintainers via the repository.
55
+
56
+ For Code of Conduct enforcement, see [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
data/README.md CHANGED
@@ -5,22 +5,32 @@
5
5
  <h1 align="center">ruby_llm_mesh</h1>
6
6
 
7
7
  <p align="center">
8
- Unified multi-provider AI routing for Ruby &amp; Rails<br/>
9
- <code>AiAgentRouter</code> · circuit breaking · fallback · RAG helpers
8
+ Sovereign multi-provider AI mesh for Ruby &amp; Rails<br/>
9
+ <code>AiAgentRouter</code> · native FFI core · circuit breaking · cloud failover
10
10
  </p>
11
11
 
12
12
  <p align="center">
13
13
  <a href="https://rubygems.org/gems/ruby_llm_mesh"><img src="https://img.shields.io/gem/v/ruby_llm_mesh?color=9B1B30" alt="Gem Version" /></a>
14
- <a href="https://github.com/theworker02/ruby_llm_mesh/actions/workflows/ci.yml"><img src="https://github.com/theworker02/ruby_llm_mesh/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
14
+ <a href="https://github.com/theworker02/ruby_llm_mesh/actions/workflows/ci.yml"><img src="https://img.shields.io/badge/CI-GitHub%20Actions-1A1A1A" alt="CI" /></a>
15
15
  <a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-E85D4C" alt="License: MIT" /></a>
16
16
  <a href="https://theworker02.github.io/ruby_llm_mesh/"><img src="https://img.shields.io/badge/docs-GitHub%20Pages-1A1A1A" alt="GitHub Pages" /></a>
17
17
  </p>
18
18
 
19
- **Official RubyGems page:** [https://rubygems.org/gems/ruby_llm_mesh](https://rubygems.org/gems/ruby_llm_mesh)
19
+ <p align="center">
20
+ <strong>Install from RubyGems:</strong>
21
+ <a href="https://rubygems.org/gems/ruby_llm_mesh">https://rubygems.org/gems/ruby_llm_mesh</a>
22
+ </p>
23
+
24
+ > **Gem name:** `ruby_llm_mesh` (underscores) — matches this GitHub repo and the official RubyGems listing. Do not confuse with hyphenated names in design sketches.
25
+
26
+ ## What it does (v2.0.0)
20
27
 
21
- ## What it does
28
+ `ruby_llm_mesh` routes intents across:
22
29
 
23
- `ruby_llm_mesh` routes prompts across OpenAI, Anthropic, and local OpenAI-compatible nodes with a single DSL. When a provider fails or its circuit is open, the router can fall through the rest of the ladder. Lightweight RAG helpers and an optional ActiveRecord mixin are included for Rails apps.
30
+ 1. A **native sovereign mesh** (`chimera_core` Rust cdylib via FFI) for local P2P-style execution
31
+ 2. **Real cloud / local LLM HTTP** — OpenAI, Anthropic, and OpenAI-compatible nodes (Ollama, LM Studio, …)
32
+
33
+ When the native library is not compiled, a pure-Ruby fallback keeps the API working. Circuit breaking, optional semantic cache, peer health for multi-node local meshes, RAG helpers, and Rails hooks remain available.
24
34
 
25
35
  ## Install
26
36
 
@@ -36,6 +46,19 @@ gem "ruby_llm_mesh"
36
46
 
37
47
  Then `bundle install`.
38
48
 
49
+ Gem page: [rubygems.org/gems/ruby_llm_mesh](https://rubygems.org/gems/ruby_llm_mesh)
50
+
51
+ ### Compile the native core (optional)
52
+
53
+ Requires [Rust](https://rustup.rs) / `cargo`:
54
+
55
+ ```bash
56
+ bundle exec rake compile
57
+ # → ext/chimera_core/target/release/libchimera_core.so (or .dylib / .dll)
58
+ ```
59
+
60
+ Without compile, `NativeCore` uses an in-process Ruby fallback. `require "ruby_llm_mesh"` never crashes on a missing `.so`.
61
+
39
62
  ## Quickstart
40
63
 
41
64
  ```ruby
@@ -44,133 +67,135 @@ require "ruby_llm_mesh"
44
67
  AiAgentRouter.configure do |c|
45
68
  c.openai_api_key = ENV["OPENAI_API_KEY"]
46
69
  c.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
47
- c.local_node_base_url = "http://127.0.0.1:11434"
48
- c.default_providers = %i[anthropic openai local_node]
49
- c.fallback = true
70
+ c.mesh_port = 4233
71
+ c.auto_boot_mesh = true
72
+ c.fallback_providers = %i[openai anthropic local_node]
50
73
  end
51
74
 
75
+ # Strategy-based execution (v2)
76
+ response = AiAgentRouter.execute(
77
+ intent: "Summarize circuit breakers in one sentence.",
78
+ strategy: :auto # :p2p_mesh | :cloud | :openai | :anthropic | :local_node
79
+ )
80
+ puts response.content
81
+ puts response.provider # => :p2p_mesh or a cloud provider
82
+
83
+ # Classic complete API (unchanged shape from 0.1.x)
52
84
  response = AiAgentRouter.complete(
53
- prompt: "Summarize circuit breakers in one sentence.",
85
+ prompt: "Hello from the mesh",
54
86
  providers: %i[anthropic openai local_node],
55
87
  fallback: true
56
88
  )
57
-
58
- puts response.content
59
- puts response.provider # => :anthropic (or next healthy provider)
60
- puts response.fallback_used # => true if a later provider was used
61
89
  ```
62
90
 
63
- `RubyLlmMesh.complete` is the same entry point; `AiAgentRouter` is the public product alias.
91
+ ## Strategies (`execute`)
92
+
93
+ | Strategy | Behavior |
94
+ |----------|----------|
95
+ | `:auto` | Boot native mesh if `auto_boot_mesh`; use P2P when alive, else real cloud ladder |
96
+ | `:p2p_mesh` | Native `chimera_core` (or Ruby fallback) only |
97
+ | `:cloud` | HTTP via `fallback_providers` / `default_providers` |
98
+ | `:openai` / `:anthropic` / `:local_node` / `:local_mesh` | Single-provider routing |
99
+
100
+ Cloud paths call the real provider HTTP clients — they are **not** stubbed simulation strings.
64
101
 
65
102
  ## Configuration
66
103
 
67
104
  | Option | Default | Description |
68
105
  |--------|---------|-------------|
69
- | `default_providers` | `%i[openai anthropic local_node]` | Provider ladder order |
106
+ | `mesh_port` | `4233` | Native mesh listen port |
107
+ | `auto_boot_mesh` | `true` | Auto-start node for `:auto` / `:p2p_mesh` |
108
+ | `fallback_providers` | `%i[openai anthropic local_node]` | Ladder for `:cloud` / `:auto` failover |
109
+ | `default_providers` | `%i[openai anthropic local_node]` | Ladder for `complete` |
70
110
  | `fallback` | `true` | Continue to next provider on failure |
71
111
  | `timeout` | `30` | HTTP open/read timeout (seconds) |
72
- | `openai_api_key` / `openai_base_url` / `openai_model` | env / `https://api.openai.com/v1` / `gpt-4o-mini` | OpenAI settings |
73
- | `anthropic_api_key` / `anthropic_base_url` / `anthropic_model` | env / `https://api.anthropic.com` / `claude-sonnet-4-5` | Anthropic settings |
74
- | `local_node_base_url` / `local_node_model` | `http://127.0.0.1:11434` / `llama3.2` | Local node settings |
75
- | `circuit_failure_threshold` | `3` | Failures before opening a circuit |
76
- | `circuit_reset_timeout` | `60` | Seconds before half-open retry |
77
- | `logger` | `nil` | Object responding to `#info` / `#warn` / `#error` or `#call` |
78
-
79
- Environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `LOCAL_NODE_BASE_URL`, etc.) are read automatically when present.
80
-
81
- ## Providers
112
+ | `max_retries` | `1` | Extra attempts on timeout, 5xx, and rate-limit errors |
113
+ | `retry_backoff` | `0.1` | Base delay (seconds) doubled after each retry |
114
+ | `openai_*` / `anthropic_*` / `local_node_*` | env-backed | Provider credentials & endpoints |
115
+ | `circuit_failure_threshold` / `circuit_reset_timeout` | `3` / `60` | Circuit breaker |
116
+ | `semantic_cache_enabled` | `false` | Opt-in vector similarity cache |
117
+ | `semantic_cache_threshold` / `semantic_cache_ttl` | `0.92` / `3600` | Cache match & TTL |
118
+ | `redis_url` | `ENV["REDIS_URL"]` | Optional Redis for distributed cache |
119
+ | `peer_discovery_enabled` / `peer_urls` | off / `[]` | Multi-peer local node health |
120
+ | `logger` | `nil` | `#info` / `#warn` / `#error` or `#call` |
82
121
 
83
- - **`:openai`** Chat Completions API
84
- - **`:anthropic`** — Messages API
85
- - **`:local_node`** — OpenAI-compatible `/v1/chat/completions`, with a fallback to Ollama’s `/api/chat` on 404
122
+ ## Native FFI surface
86
123
 
87
- Unknown providers raise `RubyLlmMesh::ProviderError` and are skipped in the ladder when fallback is enabled.
124
+ | C export | Ruby |
125
+ |----------|------|
126
+ | `start_node(port)` | `RubyLlmMesh.boot_mesh!` / `NativeCore.start_node` |
127
+ | `node_alive()` | `RubyLlmMesh.mesh_alive?` / `NativeCore.node_alive?` |
128
+ | `execute_wasm_payload(intent)` | `NativeCore.execute_wasm_payload` → Hash |
129
+ | `stop_node()` | `NativeCore.stop_node` |
88
130
 
89
- ## Circuit breaker & fallback
131
+ ## Circuit breaker & providers
90
132
 
91
- Each provider has an independent circuit. After `circuit_failure_threshold` consecutive failures (or a failure while half-open), the circuit opens for `circuit_reset_timeout` seconds. Open circuits are skipped; the router continues down the ladder when `fallback: true`.
92
-
93
- If every provider fails, `RubyLlmMesh::AllProvidersFailedError` is raised with a per-provider error map.
94
-
95
- ```ruby
96
- breaker = RubyLlmMesh::Router.circuit_breaker
97
- breaker.state_for(:openai) # => :closed | :open | :half_open
98
- RubyLlmMesh::Router.reset_circuit_breaker!
99
- ```
133
+ Same as 0.1.x: per-provider circuits, fallback ladders, `AllProvidersFailedError`. Providers: `:openai`, `:anthropic`, `:local_node` (alias `:local_mesh` for peer-aware local routing).
100
134
 
101
135
  ## RAG helpers
102
136
 
103
137
  ```ruby
104
138
  chunks = RubyLlmMesh::Rag::Chunker.new(size: 500, overlap: 50).chunk(long_text)
105
-
106
139
  embedder = RubyLlmMesh::Rag::Embeddings.new(dimensions: 256)
107
140
  hits = embedder.top_k("billing refunds", documents, k: 3)
108
-
109
- tool = RubyLlmMesh::Rag::Tools.define(
110
- name: "lookup_order",
111
- description: "Fetch an order by id",
112
- parameters: { order_id: { type: "string" } },
113
- required: [:order_id]
114
- )
115
- openai_tools = RubyLlmMesh::Rag::Tools.for_openai([tool])
116
141
  ```
117
142
 
118
- The built-in embedder is a local bag-of-words helper for prototyping. Swap in a production embedding API when you need higher quality vectors.
119
-
120
143
  ## Rails: `acts_as_ai_agent`
121
144
 
122
- The railtie loads only when Rails is present. On ActiveRecord models:
123
-
124
145
  ```ruby
125
146
  class Conversation < ApplicationRecord
126
147
  acts_as_ai_agent
127
- # expects JSON/text columns: messages, semantic_cache, ai_audits (configurable)
128
148
  end
129
-
130
- conversation = Conversation.create!
131
- response = conversation.ai_complete("What did we discuss last?", providers: %i[openai])
132
149
  ```
133
150
 
134
- Hooks provide conversational memory, a simple promptresponse cache, and an audit trail. Attribute names are configurable via `acts_as_ai_agent(memory_attribute:, cache_attribute:, audit_attribute:)`.
135
-
136
- ## Branding
137
-
138
- Primary colors from the project logo:
139
-
140
- | Token | Hex |
141
- |-------|-----|
142
- | Ruby | `#9B1B30` |
143
- | Coral | `#E85D4C` |
144
- | Charcoal | `#1A1A1A` |
151
+ ## Upgrading from 0.1.02.0.0
145
152
 
146
- Docs site: [https://theworker02.github.io/ruby_llm_mesh/](https://theworker02.github.io/ruby_llm_mesh/)
153
+ - Bump the gem to `2.0.0` (`~> 0.1` will not pick this up).
154
+ - `complete` / `AiAgentRouter.complete` remain; prefer `execute` for mesh strategies.
155
+ - Install `ffi` (declared dependency). Compile native core only if you want the Rust engine.
156
+ - If you configured RubyGems trusted publishing against `push_gem.yml`, update the workflow filename to **`release.yml`**.
147
157
 
148
158
  ## Development
149
159
 
150
160
  ```bash
151
161
  bundle install
152
- bundle exec rake test
162
+ bundle exec rake test # no Rust required
163
+ bundle exec rake compile # optional native build
164
+ bundle exec rake test:native # cargo test
153
165
  ```
154
166
 
155
- See [CONTRIBUTING.md](CONTRIBUTING.md).
156
-
157
167
  ## Trusted publishing (RubyGems)
158
168
 
159
- Releases are intended to publish via [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) using `.github/workflows/push_gem.yml` on tags matching `v*`.
160
-
161
- Configure a **pending trusted publisher** (first release) or trusted publisher at:
162
-
163
- [https://rubygems.org/profile/oidc_pending_trusted_publishers](https://rubygems.org/profile/oidc_pending_trusted_publishers)
169
+ Releases publish via [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) using `.github/workflows/release.yml` on tags matching `v*`.
164
170
 
165
171
  | Field | Value |
166
172
  |-------|-------|
167
173
  | Gem name | `ruby_llm_mesh` |
168
174
  | GitHub repository owner | `theworker02` |
169
175
  | GitHub repository name | `ruby_llm_mesh` |
170
- | Workflow filename | `push_gem.yml` |
176
+ | Workflow filename | `release.yml` |
171
177
  | Environment name | `release` |
172
178
 
173
- Also create a GitHub Environment named `release` on the repository (Settings → Environments). Pushing tag `v0.1.0` (or later) runs the workflow with `id-token: write` and publishes via `rubygems/release-gem`.
179
+ Create a GitHub Environment named `release`. Pushing tag `v2.0.0` runs OIDC publish via `rubygems/release-gem@v1`.
180
+
181
+ ## Branding
182
+
183
+ | Token | Hex |
184
+ |-------|-----|
185
+ | Ruby | `#9B1B30` |
186
+ | Coral | `#E85D4C` |
187
+ | Charcoal | `#1A1A1A` |
188
+
189
+ Docs: [https://theworker02.github.io/ruby_llm_mesh/](https://theworker02.github.io/ruby_llm_mesh/)
190
+
191
+ ## Built with
192
+
193
+ Designed with [Cursor](https://cursor.com) models Opus and Fable 5.
194
+
195
+ ## Community & policies
196
+
197
+ - [Code of Conduct](CODE_OF_CONDUCT.md) — Contributor Covenant 2.1; see also [CONTRIBUTING.md](CONTRIBUTING.md)
198
+ - [Privacy Policy](PRIVACY.md) — no phone-home telemetry; prompts and API keys stay with endpoints you configure
174
199
 
175
200
  ## License
176
201
 
data/Rakefile CHANGED
@@ -10,4 +10,32 @@ Rake::TestTask.new(:test) do |t|
10
10
  t.warning = true
11
11
  end
12
12
 
13
+ desc "Compile chimera_core native library (requires Rust/cargo)"
14
+ task :compile do
15
+ crate = File.expand_path("ext/chimera_core", __dir__)
16
+ unless system("cargo", "--version", out: File::NULL, err: File::NULL)
17
+ abort "cargo not found — install Rust from https://rustup.rs to compile chimera_core"
18
+ end
19
+ Dir.chdir(crate) do
20
+ sh "cargo", "build", "--release"
21
+ end
22
+ puts "chimera_core built under ext/chimera_core/target/release/"
23
+ end
24
+
25
+ desc "Compile chimera_core in debug mode"
26
+ task "compile:debug" do
27
+ crate = File.expand_path("ext/chimera_core", __dir__)
28
+ Dir.chdir(crate) do
29
+ sh "cargo", "build"
30
+ end
31
+ end
32
+
33
+ desc "Run Rust unit tests for chimera_core"
34
+ task "test:native" do
35
+ crate = File.expand_path("ext/chimera_core", __dir__)
36
+ Dir.chdir(crate) do
37
+ sh "cargo", "test"
38
+ end
39
+ end
40
+
13
41
  task default: :test
@@ -0,0 +1,14 @@
1
+ [package]
2
+ name = "chimera_core"
3
+ version = "2.0.0"
4
+ edition = "2021"
5
+ description = "Sovereign mesh core for ruby_llm_mesh — native node + intent execution"
6
+ license = "MIT"
7
+
8
+ [lib]
9
+ name = "chimera_core"
10
+ crate-type = ["cdylib"]
11
+
12
+ [profile.release]
13
+ lto = true
14
+ opt-level = 3