awnode 0.3.4__tar.gz → 0.3.5__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.
Files changed (84) hide show
  1. {awnode-0.3.4 → awnode-0.3.5}/PKG-INFO +7 -9
  2. {awnode-0.3.4 → awnode-0.3.5}/README.md +6 -5
  3. {awnode-0.3.4 → awnode-0.3.5}/aither-constellation.js +1 -0
  4. {awnode-0.3.4 → awnode-0.3.5}/awnode/__init__.py +2 -2
  5. {awnode-0.3.4 → awnode-0.3.5}/awnode/cli.py +26 -42
  6. {awnode-0.3.4 → awnode-0.3.5}/awnode/extensions.py +2 -2
  7. {awnode-0.3.4 → awnode-0.3.5}/awnode/hub.py +12 -0
  8. {awnode-0.3.4 → awnode-0.3.5}/awnode/license.py +6 -6
  9. {awnode-0.3.4 → awnode-0.3.5}/awnode/proxy.py +3 -3
  10. awnode-0.3.5/awnode/rea_sidecar_bridge.py +291 -0
  11. {awnode-0.3.4 → awnode-0.3.5}/awnode/server.py +9 -32
  12. {awnode-0.3.4 → awnode-0.3.5}/awnode/sync.py +9 -10
  13. awnode-0.3.5/awnode/tools/__init__.py +44 -0
  14. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/_scopes.py +0 -1
  15. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/documents.py +17 -27
  16. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/embeddings.py +28 -28
  17. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/extensions.py +1 -1
  18. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/mermaid.py +20 -27
  19. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/orchestrator.py +27 -37
  20. {awnode-0.3.4 → awnode-0.3.5}/docs/aither-manifest.json +4 -4
  21. {awnode-0.3.4 → awnode-0.3.5}/docs/index.html +15 -6
  22. {awnode-0.3.4 → awnode-0.3.5}/pyproject.toml +2 -3
  23. {awnode-0.3.4 → awnode-0.3.5}/tests/test_custom_backend.py +9 -9
  24. {awnode-0.3.4 → awnode-0.3.5}/tests/test_extension_contract.py +1 -1
  25. {awnode-0.3.4 → awnode-0.3.5}/tests/test_proxy_plane.py +0 -1
  26. awnode-0.3.4/awnode/components/ollama.yaml +0 -22
  27. awnode-0.3.4/awnode/tools/__init__.py +0 -17
  28. awnode-0.3.4/awnode/tools/ollama.py +0 -129
  29. {awnode-0.3.4 → awnode-0.3.5}/.github/workflows/publish.yml +0 -0
  30. {awnode-0.3.4 → awnode-0.3.5}/.gitignore +0 -0
  31. {awnode-0.3.4 → awnode-0.3.5}/CLAUDE.md +0 -0
  32. {awnode-0.3.4 → awnode-0.3.5}/Dockerfile +0 -0
  33. {awnode-0.3.4 → awnode-0.3.5}/LICENSE +0 -0
  34. {awnode-0.3.4 → awnode-0.3.5}/_smoke_check.py +0 -0
  35. {awnode-0.3.4 → awnode-0.3.5}/aither-manifest.json +0 -0
  36. {awnode-0.3.4 → awnode-0.3.5}/awnode/__main__.py +0 -0
  37. {awnode-0.3.4 → awnode-0.3.5}/awnode/_doctor.py +0 -0
  38. {awnode-0.3.4 → awnode-0.3.5}/awnode/comfyui_setup.py +0 -0
  39. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/__init__.py +0 -0
  40. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/autorig.yaml +0 -0
  41. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/canvas.yaml +0 -0
  42. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/comfyui-3d.yaml +0 -0
  43. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/comfyui.yaml +0 -0
  44. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/design.yaml +0 -0
  45. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/iris.yaml +0 -0
  46. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/muse.yaml +0 -0
  47. {awnode-0.3.4 → awnode-0.3.5}/awnode/components/sd-webui.yaml +0 -0
  48. {awnode-0.3.4 → awnode-0.3.5}/awnode/mcp_server.py +0 -0
  49. {awnode-0.3.4 → awnode-0.3.5}/awnode/service_install.py +0 -0
  50. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/_http.py +0 -0
  51. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/commands.py +0 -0
  52. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/context.py +0 -0
  53. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/filesystem.py +0 -0
  54. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/fleet_host.py +0 -0
  55. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/fleet_verbs.py +0 -0
  56. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/generation.py +0 -0
  57. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/git_tools.py +0 -0
  58. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/http_client.py +0 -0
  59. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/knowledge.py +0 -0
  60. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/memory.py +0 -0
  61. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/notebooks.py +0 -0
  62. {awnode-0.3.4 → awnode-0.3.5}/awnode/tools/search.py +0 -0
  63. {awnode-0.3.4 → awnode-0.3.5}/awnode/update_check.py +0 -0
  64. {awnode-0.3.4 → awnode-0.3.5}/dist_validate/aithernode-0.1.0-py3-none-any.whl +0 -0
  65. {awnode-0.3.4 → awnode-0.3.5}/docker-entrypoint.sh +0 -0
  66. {awnode-0.3.4 → awnode-0.3.5}/docs/aither-constellation.js +0 -0
  67. {awnode-0.3.4 → awnode-0.3.5}/docs/llms.txt +0 -0
  68. {awnode-0.3.4 → awnode-0.3.5}/packaging/aithernode-stub/README.md +0 -0
  69. {awnode-0.3.4 → awnode-0.3.5}/packaging/aithernode-stub/pyproject.toml +0 -0
  70. {awnode-0.3.4 → awnode-0.3.5}/tests/test_awnix_host_install.py +0 -0
  71. {awnode-0.3.4 → awnode-0.3.5}/tests/test_chat_endpoint_auth.py +0 -0
  72. {awnode-0.3.4 → awnode-0.3.5}/tests/test_component_image_env.py +0 -0
  73. {awnode-0.3.4 → awnode-0.3.5}/tests/test_fleet_host_tools.py +0 -0
  74. {awnode-0.3.4 → awnode-0.3.5}/tests/test_fleet_verbs_tools.py +0 -0
  75. {awnode-0.3.4 → awnode-0.3.5}/tests/test_hub_error_cooldown.py +0 -0
  76. {awnode-0.3.4 → awnode-0.3.5}/tests/test_mcp_api_compat.py +0 -0
  77. {awnode-0.3.4 → awnode-0.3.5}/tests/test_mcp_mode_reprobe.py +0 -0
  78. {awnode-0.3.4 → awnode-0.3.5}/tests/test_mcp_server_auth.py +0 -0
  79. {awnode-0.3.4 → awnode-0.3.5}/tests/test_mcp_sse_transport.py +0 -0
  80. {awnode-0.3.4 → awnode-0.3.5}/tests/test_pair_mode_route.py +0 -0
  81. {awnode-0.3.4 → awnode-0.3.5}/tests/test_server_route_hygiene.py +0 -0
  82. {awnode-0.3.4 → awnode-0.3.5}/tests/test_server_security_hardening.py +0 -0
  83. {awnode-0.3.4 → awnode-0.3.5}/tests/test_sync_enrollment_lifecycle.py +0 -0
  84. {awnode-0.3.4 → awnode-0.3.5}/tests/test_update_check.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: awnode
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Summary: awnode — lightweight local gateway for AitherOS
5
5
  Project-URL: Homepage, https://aitherium.com
6
6
  Author-email: Aitherium <hello@aitherium.com>
@@ -15,13 +15,10 @@ Requires-Dist: mcp<3.0.0,>=1.0.0
15
15
  Requires-Dist: pyyaml>=6.0
16
16
  Requires-Dist: uvicorn[standard]>=0.27.0
17
17
  Provides-Extra: all
18
- Requires-Dist: ollama>=0.1.0; extra == 'all'
19
18
  Requires-Dist: starlette>=0.27.0; extra == 'all'
20
19
  Provides-Extra: dev
21
20
  Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
22
21
  Requires-Dist: pytest>=7.0; extra == 'dev'
23
- Provides-Extra: ollama
24
- Requires-Dist: ollama>=0.1.0; extra == 'ollama'
25
22
  Provides-Extra: sse
26
23
  Requires-Dist: starlette>=0.27.0; extra == 'sse'
27
24
  Description-Content-Type: text/markdown
@@ -32,7 +29,7 @@ Description-Content-Type: text/markdown
32
29
 
33
30
  **[Docs](https://aitherium.github.io/awnode/)** · [Source](https://github.com/Aitherium/awnode) · `pip install awnode` · [The Aither World](https://aitherium.github.io/)
34
31
 
35
- > **The Aither World** is an operating system for agents — a Linux you can hand to one, the runtimes it works in, and the tools it works with. [awnix](https://github.com/Aitherium/awnix) is the Linux underneath it; **awnode** is one of its 67 bricks — each installs on its own, runs offline, and needs no account.
32
+ > **The Aither World** is an operating system for agents — a Linux you can hand to one, the runtimes it works in, and the tools it works with. [awnix](https://github.com/Aitherium/awnix) is the Linux underneath it; **awnode** is one of its 68 bricks — each installs on its own, runs offline, and needs no account.
36
33
  >
37
34
  > **Start here:** Run it once and point one app at it instead of a vendor URL.
38
35
 
@@ -54,7 +51,7 @@ curl -fsSL https://launch.aitherium.com | bash
54
51
  ## Quick Start
55
52
 
56
53
  ```bash
57
- # Start with auto-detection (finds Genesis, vLLM, llama.cpp, LM Studio, Ollama, or cloud)
54
+ # Start with auto-detection (finds Genesis, vLLM, llama.cpp, LM Studio, or cloud)
58
55
  awnode start
59
56
 
60
57
  # Run the published container
@@ -83,8 +80,7 @@ awnode deploy my-service --target docker --strategy rolling
83
80
  3. **llama.cpp** (localhost:8200) / **Bonsai** (localhost:8092) — OpenAI-compatible llama.cpp servers
84
81
  4. **LM Studio** (127.0.0.1:1234) — LM Studio's local server (OpenAI-compatible; start it from LM Studio's Developer tab)
85
82
  5. **Elysium** (cloud) — hosted AitherOS (requires API key)
86
- 6. **Ollama** (localhost:11434) — local CPU/GPU inference
87
- 7. **Standalone** — no LLM, tools-only mode
83
+ 6. **Standalone** — no LLM, tools-only mode
88
84
 
89
85
  OpenAI-compatible backends (vLLM, llama.cpp, Bonsai, LM Studio, custom) are detected by a
90
86
  200 on `/v1/models`, never by `/health`, so an unrelated service on the same port is not
@@ -123,7 +119,7 @@ the read-only set; for full tool access from an IDE use `awnode mcp`.
123
119
  |---|---|---|
124
120
  | `AITHER_URL` | `http://localhost:8001` | Genesis URL |
125
121
  | `AITHER_VLLM_URL` | `http://localhost:8120` | vLLM URL |
126
- | `OLLAMA_HOST` | `http://localhost:11434` | Ollama URL |
122
+ | `LLAMACPP_URL` | `http://localhost:8200` | llama.cpp `llama-server` URL (OpenAI-compatible) |
127
123
  | `AITHERNODE_LMSTUDIO_URL` | `http://127.0.0.1:1234` | LM Studio server URL (`LMSTUDIO_URL` also read) |
128
124
  | `AWNODE_EXTENSION_IDS` | | Extra extension ids admitted on the extension routes (comma-separated) |
129
125
  | `AWNODE_BROWSER_FULL_TOOLS` | | `1` lets direct loopback callers (browser/extension included) run every tool without a credential; tunnelled/remote callers stay read-only |
@@ -173,6 +169,7 @@ Each installs on its own, works offline, and needs no account.
173
169
  | [awrelay](https://github.com/Aitherium/awrelay) | a SaaS in the middle of your agents | findings, alerts and coordination over your own transport |
174
170
  | [awask](https://github.com/Aitherium/awask) | that anyone read the paragraph where you asked | the ask itself, with a button that steers the session that raised it |
175
171
  | [awmail](https://github.com/Aitherium/awmail) | a mailbox somebody else can read | mail your agents send and receive over your own server |
172
+ | [awdiscord](https://github.com/Aitherium/awdiscord) | a self-bot on someone's account, or a bot that acts without asking | slash commands, rate limits, and approval buttons only your operators can press |
176
173
  | [awswarm](https://github.com/Aitherium/awswarm) | that a model either fits your GPU or it doesn't run at all | a placement plan and an acquisition-probability estimate before you spend on a run |
177
174
  | [awfind](https://github.com/Aitherium/awfind) | one vendor's idea of the web | results from whichever providers you configured |
178
175
  | [awbrowse](https://github.com/Aitherium/awbrowse) | that the page said what you were told | the render, the DOM and the requests it made |
@@ -243,6 +240,7 @@ Every repository here is public. Each publishes an `aither-manifest.json` beside
243
240
  | [awrelay](https://github.com/Aitherium/awrelay) | Portable agent messaging — findings, alerts, coordination | [docs](https://aitherium.github.io/awrelay/) |
244
241
  | [awask](https://github.com/Aitherium/awask) | Your agent asks you a question — and acts on your answer | [docs](https://aitherium.github.io/awask/) |
245
242
  | [awmail](https://github.com/Aitherium/awmail) | Give an agent an email address — send, and actually receive | [docs](https://aitherium.github.io/awmail/) |
243
+ | [awdiscord](https://github.com/Aitherium/awdiscord) | Put any agent on Discord as a real bot, with an operator in the loop | — |
246
244
  | [awnet](https://github.com/Aitherium/awnet) | The agentic web — agents host a mesh, and agents join one | [docs](https://aitherium.github.io/awnet/) |
247
245
  | [awswarm](https://github.com/Aitherium/awswarm) | Run one model too big for any single GPU across a pool of small ones | — |
248
246
  | [awfind](https://github.com/Aitherium/awfind) | A portable search client — query, results, ranking | [docs](https://aitherium.github.io/awfind/) |
@@ -4,7 +4,7 @@
4
4
 
5
5
  **[Docs](https://aitherium.github.io/awnode/)** · [Source](https://github.com/Aitherium/awnode) · `pip install awnode` · [The Aither World](https://aitherium.github.io/)
6
6
 
7
- > **The Aither World** is an operating system for agents — a Linux you can hand to one, the runtimes it works in, and the tools it works with. [awnix](https://github.com/Aitherium/awnix) is the Linux underneath it; **awnode** is one of its 67 bricks — each installs on its own, runs offline, and needs no account.
7
+ > **The Aither World** is an operating system for agents — a Linux you can hand to one, the runtimes it works in, and the tools it works with. [awnix](https://github.com/Aitherium/awnix) is the Linux underneath it; **awnode** is one of its 68 bricks — each installs on its own, runs offline, and needs no account.
8
8
  >
9
9
  > **Start here:** Run it once and point one app at it instead of a vendor URL.
10
10
 
@@ -26,7 +26,7 @@ curl -fsSL https://launch.aitherium.com | bash
26
26
  ## Quick Start
27
27
 
28
28
  ```bash
29
- # Start with auto-detection (finds Genesis, vLLM, llama.cpp, LM Studio, Ollama, or cloud)
29
+ # Start with auto-detection (finds Genesis, vLLM, llama.cpp, LM Studio, or cloud)
30
30
  awnode start
31
31
 
32
32
  # Run the published container
@@ -55,8 +55,7 @@ awnode deploy my-service --target docker --strategy rolling
55
55
  3. **llama.cpp** (localhost:8200) / **Bonsai** (localhost:8092) — OpenAI-compatible llama.cpp servers
56
56
  4. **LM Studio** (127.0.0.1:1234) — LM Studio's local server (OpenAI-compatible; start it from LM Studio's Developer tab)
57
57
  5. **Elysium** (cloud) — hosted AitherOS (requires API key)
58
- 6. **Ollama** (localhost:11434) — local CPU/GPU inference
59
- 7. **Standalone** — no LLM, tools-only mode
58
+ 6. **Standalone** — no LLM, tools-only mode
60
59
 
61
60
  OpenAI-compatible backends (vLLM, llama.cpp, Bonsai, LM Studio, custom) are detected by a
62
61
  200 on `/v1/models`, never by `/health`, so an unrelated service on the same port is not
@@ -95,7 +94,7 @@ the read-only set; for full tool access from an IDE use `awnode mcp`.
95
94
  |---|---|---|
96
95
  | `AITHER_URL` | `http://localhost:8001` | Genesis URL |
97
96
  | `AITHER_VLLM_URL` | `http://localhost:8120` | vLLM URL |
98
- | `OLLAMA_HOST` | `http://localhost:11434` | Ollama URL |
97
+ | `LLAMACPP_URL` | `http://localhost:8200` | llama.cpp `llama-server` URL (OpenAI-compatible) |
99
98
  | `AITHERNODE_LMSTUDIO_URL` | `http://127.0.0.1:1234` | LM Studio server URL (`LMSTUDIO_URL` also read) |
100
99
  | `AWNODE_EXTENSION_IDS` | | Extra extension ids admitted on the extension routes (comma-separated) |
101
100
  | `AWNODE_BROWSER_FULL_TOOLS` | | `1` lets direct loopback callers (browser/extension included) run every tool without a credential; tunnelled/remote callers stay read-only |
@@ -145,6 +144,7 @@ Each installs on its own, works offline, and needs no account.
145
144
  | [awrelay](https://github.com/Aitherium/awrelay) | a SaaS in the middle of your agents | findings, alerts and coordination over your own transport |
146
145
  | [awask](https://github.com/Aitherium/awask) | that anyone read the paragraph where you asked | the ask itself, with a button that steers the session that raised it |
147
146
  | [awmail](https://github.com/Aitherium/awmail) | a mailbox somebody else can read | mail your agents send and receive over your own server |
147
+ | [awdiscord](https://github.com/Aitherium/awdiscord) | a self-bot on someone's account, or a bot that acts without asking | slash commands, rate limits, and approval buttons only your operators can press |
148
148
  | [awswarm](https://github.com/Aitherium/awswarm) | that a model either fits your GPU or it doesn't run at all | a placement plan and an acquisition-probability estimate before you spend on a run |
149
149
  | [awfind](https://github.com/Aitherium/awfind) | one vendor's idea of the web | results from whichever providers you configured |
150
150
  | [awbrowse](https://github.com/Aitherium/awbrowse) | that the page said what you were told | the render, the DOM and the requests it made |
@@ -215,6 +215,7 @@ Every repository here is public. Each publishes an `aither-manifest.json` beside
215
215
  | [awrelay](https://github.com/Aitherium/awrelay) | Portable agent messaging — findings, alerts, coordination | [docs](https://aitherium.github.io/awrelay/) |
216
216
  | [awask](https://github.com/Aitherium/awask) | Your agent asks you a question — and acts on your answer | [docs](https://aitherium.github.io/awask/) |
217
217
  | [awmail](https://github.com/Aitherium/awmail) | Give an agent an email address — send, and actually receive | [docs](https://aitherium.github.io/awmail/) |
218
+ | [awdiscord](https://github.com/Aitherium/awdiscord) | Put any agent on Discord as a real bot, with an operator in the loop | — |
218
219
  | [awnet](https://github.com/Aitherium/awnet) | The agentic web — agents host a mesh, and agents join one | [docs](https://aitherium.github.io/awnet/) |
219
220
  | [awswarm](https://github.com/Aitherium/awswarm) | Run one model too big for any single GPU across a pool of small ones | — |
220
221
  | [awfind](https://github.com/Aitherium/awfind) | A portable search client — query, results, ranking | [docs](https://aitherium.github.io/awfind/) |
@@ -42,6 +42,7 @@
42
42
  { id: "awrecover", label: "awrecover", blurb: "Labelled snapshots with an all-or-nothing..." },
43
43
  { id: "awrelay", label: "awrelay", blurb: "Portable agent messaging — findings, alerts,..." },
44
44
  { id: "awmail", label: "awmail", blurb: "Give an agent an email address — send, and..." },
45
+ { id: "awdiscord", label: "awdiscord", blurb: "Put any agent on Discord as a real bot,..." },
45
46
  { id: "awnet", label: "awnet", blurb: "The agentic web — agents host a mesh, and..." },
46
47
  { id: "awfind", label: "awfind", blurb: "A portable search client — query, results,..." },
47
48
  { id: "awbrowse", label: "awbrowse", blurb: "A portable browser client — navigate,..." },
@@ -7,7 +7,7 @@ The bridge between local apps (Shell, Desktop, Connect) and AitherOS services.
7
7
  Modes:
8
8
  1. **Local Genesis** — proxy to localhost:8001 (full AitherOS Docker stack)
9
9
  2. **Cloud** — proxy to mcp.aitherium.com (SaaS inference + MCP tools)
10
- 3. **Standalone** — local Ollama + basic tools (no Genesis needed)
10
+ 3. **Standalone** — local llama.cpp + basic tools (no Genesis needed)
11
11
  4. **Hybrid** — local tools + cloud LLM (best of both)
12
12
 
13
13
  Install:
@@ -17,4 +17,4 @@ Install:
17
17
  aithernode status # Check what's connected
18
18
  """
19
19
 
20
- __version__ = "0.3.4"
20
+ __version__ = "0.3.5"
@@ -72,7 +72,7 @@ def main():
72
72
  start_p.add_argument("--cloud", action="store_true", help="Force cloud mode (Elysium)")
73
73
  start_p.add_argument("--local", action="store_true", help="Force local mode (no cloud)")
74
74
  start_p.add_argument("--vllm-url", type=str, help="vLLM URL (default: http://localhost:8120)")
75
- start_p.add_argument("--ollama-url", type=str, help="Ollama URL (default: http://localhost:11434)")
75
+ start_p.add_argument("--llamacpp-url", type=str, help="llama.cpp server URL (default: http://localhost:8200)")
76
76
  start_p.add_argument("--genesis-url", type=str, help="Genesis URL (default: http://localhost:8001)")
77
77
 
78
78
  # status
@@ -105,7 +105,8 @@ def main():
105
105
  "AitherOS fabric. Omit for the default GPU/backend setup.",
106
106
  )
107
107
  setup_p.add_argument("--cloud", action="store_true", help="Cloud-only mode (skip local GPU)")
108
- setup_p.add_argument("--model", type=str, help="Specific Ollama model to pull")
108
+ setup_p.add_argument("--model", type=str,
109
+ help="GGUF model id the local llama.cpp server should serve")
109
110
  setup_p.add_argument("--skip-model", action="store_true", help="Skip model download")
110
111
  # `setup comfyui` flags (ignored by the bare `setup` path)
111
112
  setup_p.add_argument("--profile", type=str, default="studio",
@@ -191,8 +192,8 @@ def main():
191
192
  os.environ["AITHERNODE_MODE"] = "local"
192
193
  if args.vllm_url:
193
194
  os.environ["AITHER_VLLM_URL"] = args.vllm_url
194
- if args.ollama_url:
195
- os.environ["OLLAMA_HOST"] = args.ollama_url
195
+ if args.llamacpp_url:
196
+ os.environ["LLAMACPP_URL"] = args.llamacpp_url
196
197
  if args.genesis_url:
197
198
  os.environ["AITHER_URL"] = args.genesis_url
198
199
  os.environ["AITHERNODE_PORT"] = str(args.port)
@@ -347,7 +348,7 @@ async def _doctor(*, emit_json: bool = False, timeout: float = 3.0) -> int:
347
348
  backends = {
348
349
  "genesis": os.environ.get("AITHER_URL", "http://localhost:8001"),
349
350
  "vllm": os.environ.get("AITHER_VLLM_URL", "http://localhost:8120"),
350
- "ollama": os.environ.get("OLLAMA_HOST", "http://localhost:11434"),
351
+ "llamacpp": os.environ.get("LLAMACPP_URL", "http://localhost:8200"),
351
352
  # LM Studio has no /health; its OpenAI-compatible /v1/models is the liveness surface.
352
353
  "lmstudio": os.environ.get(
353
354
  "AITHERNODE_LMSTUDIO_URL", os.environ.get("LMSTUDIO_URL", "http://127.0.0.1:1234")
@@ -356,7 +357,7 @@ async def _doctor(*, emit_json: bool = False, timeout: float = 3.0) -> int:
356
357
  }
357
358
  async with httpx.AsyncClient(timeout=timeout) as client:
358
359
  for name, url in backends.items():
359
- health_path = {"ollama": "/api/tags", "lmstudio": "/v1/models"}.get(name, "/health")
360
+ health_path = {"lmstudio": "/v1/models"}.get(name, "/health")
360
361
  try:
361
362
  r = await client.get(url.rstrip("/") + health_path)
362
363
  if r.status_code < 500:
@@ -364,7 +365,7 @@ async def _doctor(*, emit_json: bool = False, timeout: float = 3.0) -> int:
364
365
  else:
365
366
  record(name, "warn", f"{url} -> {r.status_code}")
366
367
  except Exception as e:
367
- # gateway/vllm/ollama unreachable is a warn (not everyone runs them)
368
+ # gateway/vllm/llamacpp unreachable is a warn (not everyone runs them)
368
369
  record(name, "warn", f"{url} unreachable: {type(e).__name__}")
369
370
 
370
371
  # Compute exit code
@@ -403,7 +404,7 @@ async def _status():
403
404
  checks = {
404
405
  "Genesis": os.environ.get("AITHER_URL", "http://localhost:8001"),
405
406
  "vLLM": os.environ.get("AITHER_VLLM_URL", os.environ.get("VLLM_URL", "http://localhost:8120")),
406
- "Ollama": os.environ.get("OLLAMA_HOST", "http://localhost:11434"),
407
+ "llama.cpp": os.environ.get("LLAMACPP_URL", "http://localhost:8200"),
407
408
  "Elysium": "https://mcp.aitherium.com",
408
409
  }
409
410
 
@@ -412,7 +413,7 @@ async def _status():
412
413
  for name, url in checks.items():
413
414
  try:
414
415
  async with httpx.AsyncClient(timeout=3.0) as c:
415
- health_path = "/api/tags" if name == "Ollama" else "/health"
416
+ health_path = "/health"
416
417
  r = await c.get(f"{url.rstrip('/')}{health_path}")
417
418
  status = "UP" if r.status_code == 200 else f"HTTP {r.status_code}"
418
419
  except Exception:
@@ -684,7 +685,7 @@ async def _connect(
684
685
  try:
685
686
  result = await gw.register_agent(
686
687
  name=f"node-{hostname}",
687
- capabilities=["chat", "code", "filesystem", "git", "vllm", "ollama"],
688
+ capabilities=["chat", "code", "filesystem", "git", "vllm", "llamacpp"],
688
689
  description=f"awnode on {hostname} ({platform.system()})",
689
690
  )
690
691
  print(f"Connected! Agent ID: {result.get('agent_id', '?')}")
@@ -796,42 +797,25 @@ async def _setup(cloud_only: bool = False, model: str = None, skip_model: bool =
796
797
  print(" Local models will use your GPU for fast inference.")
797
798
  elif gpu_vram >= 4096:
798
799
  cfg["mode"] = "auto"
799
- print(f" Recommended: Ollama with small models ({gpu_vram}MB VRAM)")
800
+ print(f" Recommended: llama.cpp with a small GGUF model ({gpu_vram}MB VRAM)")
800
801
  else:
801
802
  cfg["mode"] = "auto"
802
- print(" Recommended: Ollama CPU mode or cloud")
803
-
804
- # -- Ollama Detection & Model Pull --
805
- has_ollama = shutil.which("ollama") is not None
806
- if has_ollama:
807
- print(" Ollama: installed")
808
- cfg["ollama"] = {"available": True}
809
-
810
- if not skip_model and not cloud_only:
811
- target_model = model
812
- if not target_model:
813
- if gpu_vram >= 16384:
814
- target_model = "llama3.1:8b"
815
- elif gpu_vram >= 8192:
816
- target_model = "llama3.2:3b"
817
- else:
818
- target_model = "llama3.2:1b"
819
-
820
- print(f"\n Pulling model: {target_model}...")
821
- pull_result = subprocess.run(
822
- ["ollama", "pull", target_model],
823
- timeout=600,
824
- )
825
- if pull_result.returncode == 0:
826
- cfg["ollama"]["default_model"] = target_model
827
- print(f" Model ready: {target_model}")
828
- else:
829
- print(f" Model pull failed (exit {pull_result.returncode})")
803
+ print(" Recommended: llama.cpp CPU mode or cloud")
804
+
805
+ # -- llama.cpp Detection --
806
+ # Weights are GGUF files from artifact.aitherium.com (awrtifact); awnode does not
807
+ # download them -- it records which model the local llama-server should serve.
808
+ has_llamacpp = shutil.which("llama-server") is not None
809
+ cfg["llamacpp"] = {"available": has_llamacpp}
810
+ if has_llamacpp:
811
+ print(" llama.cpp: llama-server installed")
830
812
  else:
831
- print(" Ollama: not installed")
813
+ print(" llama.cpp: llama-server not on PATH")
832
814
  if not cloud_only:
833
- print(" Install: https://ollama.com/download")
834
- cfg["ollama"] = {"available": False}
815
+ print(" Install: https://github.com/ggml-org/llama.cpp/releases")
816
+ if model and not skip_model and not cloud_only:
817
+ cfg["llamacpp"]["default_model"] = model
818
+ print(f" Default local model: {model}")
835
819
 
836
820
  # -- vLLM Detection --
837
821
  import httpx
@@ -9,8 +9,8 @@ alongside awnode on customer hardware.
9
9
  `awdk.adk.addon_manager` reads component manifests from three sources (a pip-installed
10
10
  brick's `aither.components` entry point, `~/.aither/components/*.yaml`, the bundled
11
11
  `adk/addon_manifests/`) and this manager renders them in the shape `awnode ext` has
12
- always shown. The nine entries that used to be hardcoded in BUILTIN_CATALOG (canvas,
13
- comfyui, comfyui-3d, muse, sd-webui, ollama, iris, design, autorig) are manifests now,
12
+ always shown. The entries that used to be hardcoded in BUILTIN_CATALOG (canvas,
13
+ comfyui, comfyui-3d, muse, sd-webui, iris, design, autorig) are manifests now,
14
14
  so `awnode ext start canvas` runs the same declaration awdk, the aitheros launcher, awsh
15
15
  and the Living Desktop read. Two hosts with two catalogs of "what can run here" was the
16
16
  silence this ended: an extension present in one and absent from the other looked like
@@ -90,6 +90,18 @@ DEFAULT_BRICKS: List[Dict[str, Any]] = [
90
90
  {"name": "awfind", "main": "awfind.cli:main", "args": ["mcp"]},
91
91
  {"name": "awprism", "main": "awprism.cli:main", "args": ["mcp"]},
92
92
  {"name": "awsh", "module": "adk.harnesses.mcp_stdio"},
93
+ # REA reverse-engineering toolkit. The heavy toolchain (Node 22, Ghidra, the
94
+ # pinned rea-agents CLI) lives in the policy-gated ``aitheros-rea`` awnix
95
+ # sidecar, never in this process; this brick is a thin stdio->HTTP bridge to
96
+ # that sidecar's MCP endpoint, so every rea_* call is served THROUGH the
97
+ # sidecar's in-process policy proxy (lib.agents.packs.rea.policy.authorize:
98
+ # target_class + per-tool grant, fail-closed). Disabled by default so boots
99
+ # on a host without the sidecar never try to start it; enable per host via
100
+ # ~/.aither/aw-hub config ``{"bricks": {"rea": {"disabled": false}}}`` or the
101
+ # AITHER_REA_SIDECAR_URL env the argv reads.
102
+ {"name": "rea", "disabled": True, "module": "awnode.rea_sidecar_bridge",
103
+ "args": ["--url", os.environ.get("AITHER_REA_SIDECAR_URL",
104
+ "https://aitheros-rea:8791/mcp")]},
93
105
  ]
94
106
 
95
107
  _CREATE_NO_WINDOW = 0x08000000
@@ -13,7 +13,7 @@ Flow:
13
13
 
14
14
  If the subscription lapses:
15
15
  - Tools/agents/extensions that require a paid tier stop working
16
- - Free-tier tools (filesystem, git, search, Ollama) keep working
16
+ - Free-tier tools (filesystem, git, search, local llama.cpp) keep working
17
17
  - Clear error messages tell the user to renew
18
18
 
19
19
  If offline:
@@ -49,8 +49,8 @@ PLAN_FEATURES: Dict[str, Dict[str, Any]] = {
49
49
  "free": {
50
50
  "tools": {"filesystem", "git_tools", "search", "commands", "context",
51
51
  "memory", "knowledge", "notebooks", "documents", "mermaid",
52
- "http_client", "ollama", "orchestrator", "embeddings"},
53
- "extensions": {"ollama"},
52
+ "http_client", "orchestrator", "embeddings"},
53
+ "extensions": set(),
54
54
  "agents": set(),
55
55
  "max_agents": 1,
56
56
  "image_generation": False,
@@ -60,9 +60,9 @@ PLAN_FEATURES: Dict[str, Dict[str, Any]] = {
60
60
  "developer": {
61
61
  "tools": {"filesystem", "git_tools", "search", "commands", "context",
62
62
  "memory", "knowledge", "notebooks", "documents", "mermaid",
63
- "http_client", "ollama", "orchestrator", "embeddings",
63
+ "http_client", "orchestrator", "embeddings",
64
64
  "generation", "extensions", "vision"},
65
- "extensions": {"ollama", "canvas", "comfyui"},
65
+ "extensions": {"canvas", "comfyui"},
66
66
  "agents": {"iris"},
67
67
  "max_agents": 3,
68
68
  "image_generation": True,
@@ -71,7 +71,7 @@ PLAN_FEATURES: Dict[str, Dict[str, Any]] = {
71
71
  },
72
72
  "pro": {
73
73
  "tools": {"*"}, # All tools
74
- "extensions": {"ollama", "canvas", "comfyui", "comfyui-3d", "muse",
74
+ "extensions": {"canvas", "comfyui", "comfyui-3d", "muse",
75
75
  "sd-webui", "iris", "design"},
76
76
  "agents": {"iris", "demiurge", "atlas", "hydra", "viviane"},
77
77
  "max_agents": 15,
@@ -57,8 +57,8 @@ _DEFAULT_SERVICES: Dict[str, str] = {
57
57
  "genesis": os.environ.get("AITHER_URL", "http://127.0.0.1:8001"),
58
58
  # Bonsai-27B llama.cpp server (PrismML fork) — OpenAI-compatible /v1
59
59
  "bonsai": os.environ.get("AITHER_BONSAI_URL", "http://127.0.0.1:8092"),
60
- # Ollama — generic local model host
61
- "ollama": os.environ.get("OLLAMA_HOST", "http://127.0.0.1:11434"),
60
+ # llama.cpp llama-server — generic local OpenAI-compatible model host
61
+ "llamacpp": os.environ.get("LLAMACPP_URL", "http://127.0.0.1:8200"),
62
62
  # AitherMarketplace — unified catalog (agent/skill/tool packs, apps,
63
63
  # tools, plugins, extensions) with the fail-closed entitlement gate.
64
64
  "marketplace": os.environ.get("AITHER_MARKETPLACE_URL", "https://127.0.0.1:8260"),
@@ -80,7 +80,7 @@ def _load_service_map() -> Dict[str, str]:
80
80
 
81
81
  def _norm(url: str) -> str:
82
82
  url = url.strip().rstrip("/")
83
- # OLLAMA_HOST is commonly "0.0.0.0:11434" (no scheme) — normalize so
83
+ # A host env is commonly "0.0.0.0:<port>" (no scheme) — normalize so
84
84
  # httpx gets an absolute URL, and rewrite wildcard binds to loopback.
85
85
  if url and "://" not in url:
86
86
  url = f"http://{url}"