Compare commits
8 Commits
824232aaa7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e827a10680 | |||
| b8cb8908e7 | |||
| e8b2dfda36 | |||
| 42016cda27 | |||
| 2c5e64039a | |||
| 7e7b884cc6 | |||
| af91bad87b | |||
| 7d89dac788 |
@@ -1,6 +1,9 @@
|
|||||||
|
{"_type":"issue","id":"nix-overlay-dv3","title":"Fix Config screen crash on F2","description":"F2 opens ConfigScreen then Textual raises InvalidSelectValueError because _refresh_aggregator_dropdown assigns Select.BLANK, resolved as False, instead of clearing selection.\\n\\nAcceptance: Config screen opens with saved consensus configuration; regression covers no selected aggregator; targeted tests pass.","status":"in_progress","priority":1,"issue_type":"bug","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-20T11:34:03Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-20T11:34:07Z","started_at":"2026-08-20T11:34:07Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"_type":"issue","id":"nix-overlay-a9m","title":"Fix haivemind startup after MainScreen mount","description":"Restore deferred engine startup while preserving MainScreen widget lookup fix.","status":"closed","priority":1,"issue_type":"bug","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-20T11:20:36Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-20T11:21:43Z","started_at":"2026-08-20T11:20:43Z","closed_at":"2026-08-20T11:21:43Z","close_reason":"Restored engine startup after MainScreen mount and verified package build.","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"_type":"issue","id":"nix-overlay-q00","title":"Add haivemind package","description":"Package https://github.com/dev-boz/haivemind in the Nix overlay, document it, validate the build, and complete repository workflow.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-08T16:32:37Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-08T16:36:41Z","started_at":"2026-08-08T16:33:00Z","closed_at":"2026-08-08T16:36:41Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"nix-overlay-67e","title":"Add traycer package","description":"Add new package for traycer from https://github.com/traycerai/traycer. Steps: research repo build system, create packages/traycer/, stage with git add, test nix build, update README.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T08:59:25Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T09:22:07Z","started_at":"2026-08-07T09:00:29Z","closed_at":"2026-08-07T09:22:07Z","close_reason":"Traycer package added, built, pushed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"nix-overlay-67e","title":"Add traycer package","description":"Add new package for traycer from https://github.com/traycerai/traycer. Steps: research repo build system, create packages/traycer/, stage with git add, test nix build, update README.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T08:59:25Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T09:22:07Z","started_at":"2026-08-07T09:00:29Z","closed_at":"2026-08-07T09:22:07Z","close_reason":"Traycer package added, built, pushed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"nix-overlay-2gf","title":"Update all packages to latest versions","description":"## Why\\nUser request: update every package in the overlay to its latest upstream version.\\n\\n## What\\nBump version + src hash (and cargoHash for Rust) in each packages/\u003cname\u003e/package.nix, update README table if needed, verify builds.\\n\\n## Acceptance\\n- Every package builds with nix build .#\u003cname\u003e\\n- README reflects new versions\\n- Changes committed and pushed","notes":"All packages updated and built successfully. Commit 1f3f0f468bdd on local main. PUSH BLOCKED: git.millerson.name:22002 and DoltHub unreachable from this network (SSH connect timeout). Re-run git push + bd dolt push when network is back, then close.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T07:22:50Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T13:17:34Z","started_at":"2026-08-07T07:22:55Z","closed_at":"2026-08-07T13:17:34Z","close_reason":"All packages updated to latest versions, verified building, pushed to origin","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"nix-overlay-2gf","title":"Update all packages to latest versions","description":"## Why\\nUser request: update every package in the overlay to its latest upstream version.\\n\\n## What\\nBump version + src hash (and cargoHash for Rust) in each packages/\u003cname\u003e/package.nix, update README table if needed, verify builds.\\n\\n## Acceptance\\n- Every package builds with nix build .#\u003cname\u003e\\n- README reflects new versions\\n- Changes committed and pushed","notes":"All packages updated and built successfully. Commit 1f3f0f468bdd on local main. PUSH BLOCKED: git.millerson.name:22002 and DoltHub unreachable from this network (SSH connect timeout). Re-run git push + bd dolt push when network is back, then close.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T07:22:50Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T13:17:34Z","started_at":"2026-08-07T07:22:55Z","closed_at":"2026-08-07T13:17:34Z","close_reason":"All packages updated to latest versions, verified building, pushed to origin","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"nix-overlay-9xs","title":"Update all packages to latest versions","description":"Update every package in packages/ to its latest upstream version, refresh source hashes and cargoHashes, verify builds, update README.","status":"in_progress","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T05:45:16Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T05:45:22Z","started_at":"2026-08-07T05:45:22Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"nix-overlay-9xs","title":"Update all packages to latest versions","description":"Update every package in packages/ to its latest upstream version, refresh source hashes and cargoHashes, verify builds, update README.","status":"in_progress","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T05:45:16Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T05:45:22Z","started_at":"2026-08-07T05:45:22Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"nix-overlay-f8c","title":"Add nftablesbuilder package","description":"Package NftablesBuilder (github.com/AiseBouma/NftablesBuilder) web interface to manage nftables. Upstream source is incomplete (missing settings crate, no GUI build tooling, no Cargo.lock) so: patch in authored settings crate (schema from release artifacts), build Rust workspace from pinned commit, reuse built GUI assets from hash-pinned release tarball.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T04:58:22Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T05:38:40Z","started_at":"2026-08-07T04:58:25Z","closed_at":"2026-08-07T05:38:40Z","close_reason":"Package added, builds green, committed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"nix-overlay-f8c","title":"Add nftablesbuilder package","description":"Package NftablesBuilder (github.com/AiseBouma/NftablesBuilder) web interface to manage nftables. Upstream source is incomplete (missing settings crate, no GUI build tooling, no Cargo.lock) so: patch in authored settings crate (schema from release artifacts), build Rust workspace from pinned commit, reuse built GUI assets from hash-pinned release tarball.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T04:58:22Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T05:38:40Z","started_at":"2026-08-07T04:58:25Z","closed_at":"2026-08-07T05:38:40Z","close_reason":"Package added, builds green, committed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"nix-overlay-bjd","title":"Add nftables-analyzer CLI package","description":"Add python3Packages.buildPythonApplication derivation for reinaldosaraiva/nftables-analyzer (CLI only). Pin to main commit 5fc78d0c9ce173e3baa80a5655bcadb1b2f78493 (no tags upstream). sourceRoot=source/backend, hatchling build system. Category: Networking. Frontend excluded - upstream repo missing frontend/src/lib modules.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T04:48:07Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T04:50:25Z","started_at":"2026-08-07T04:48:10Z","closed_at":"2026-08-07T04:50:25Z","close_reason":"Package added, built, smoke-tested, committed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"nix-overlay-bjd","title":"Add nftables-analyzer CLI package","description":"Add python3Packages.buildPythonApplication derivation for reinaldosaraiva/nftables-analyzer (CLI only). Pin to main commit 5fc78d0c9ce173e3baa80a5655bcadb1b2f78493 (no tags upstream). sourceRoot=source/backend, hatchling build system. Category: Networking. Frontend excluded - upstream repo missing frontend/src/lib modules.","status":"closed","priority":2,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T04:48:07Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T04:50:25Z","started_at":"2026-08-07T04:48:10Z","closed_at":"2026-08-07T04:50:25Z","close_reason":"Package added, built, smoke-tested, committed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"_type":"issue","id":"nix-overlay-vhq","title":"Note missing Dolt remote in AGENTS.md","description":"## Why\\nAgents running bd dolt push see 'No remote is configured - skipping' and may mistake it for a failure (blocking session close). Document that this is expected: no Dolt remote is set up, beads state is versioned locally in .beads/ and committed via git.\\n\\n## What\\nAdd a short note in the Beads Issue Tracker / Session Completion section of AGENTS.md.\\n\\n## Acceptance\\n- AGENTS.md explains the expected bd dolt push output and that git push is the actual sync mechanism","status":"in_progress","priority":3,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T13:18:33Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T13:18:51Z","started_at":"2026-08-07T13:18:51Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"_type":"issue","id":"nix-overlay-vhq","title":"Note missing Dolt remote in AGENTS.md","description":"## Why\\nAgents running bd dolt push see 'No remote is configured - skipping' and may mistake it for a failure (blocking session close). Document that this is expected: no Dolt remote is set up, beads state is versioned locally in .beads/ and committed via git.\\n\\n## What\\nAdd a short note in the Beads Issue Tracker / Session Completion section of AGENTS.md.\\n\\n## Acceptance\\n- AGENTS.md explains the expected bd dolt push output and that git push is the actual sync mechanism","status":"closed","priority":3,"issue_type":"task","assignee":"Alexander Miroshnichenko","owner":"alex@millerson.name","created_at":"2026-08-07T13:18:33Z","created_by":"Alexander Miroshnichenko","updated_at":"2026-08-07T13:19:26Z","started_at":"2026-08-07T13:18:51Z","closed_at":"2026-08-07T13:19:26Z","close_reason":"AGENTS.md updated and pushed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ A custom Nix overlay and flake providing additional packages not found in upstre
|
|||||||
|
|
||||||
| Package | Description | Category |
|
| Package | Description | Category |
|
||||||
|---------|-------------|----------|
|
|---------|-------------|----------|
|
||||||
|
| `awg-tool` | CLI for AmneziaWG self-hosting — generates 1.0/1.5/2.0/3.0 obfuscation parameters, exports .conf and vpn:// configs, installs servers over SSH | Networking |
|
||||||
| `aionui` | Free, open-source, Cowork app with AI Agents | AI Coding Agents |
|
| `aionui` | Free, open-source, Cowork app with AI Agents | AI Coding Agents |
|
||||||
| `container-use` | Containerized environments for coding agents | AI Coding Agents |
|
| `container-use` | Containerized environments for coding agents | AI Coding Agents |
|
||||||
| `desloppify` | Multi-language codebase health scanner and technical debt tracker for AI agents | AI Coding Agents |
|
| `desloppify` | Multi-language codebase health scanner and technical debt tracker for AI agents | AI Coding Agents |
|
||||||
| `ds4` | DeepSeek 4 Flash and PRO local inference engine for ROCm (Strix Halo) | AI Inference |
|
| `ds4` | DeepSeek 4 Flash and PRO local inference engine for ROCm (Strix Halo) | AI Inference |
|
||||||
| `freebuff` | The world's strongest free coding agent | AI Coding Agents |
|
| `freebuff` | The world's strongest free coding agent | AI Coding Agents |
|
||||||
| `graphify` | Turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph | AI Coding Agents |
|
| `graphify` | Turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph | AI Coding Agents |
|
||||||
|
| `haivemind` | Multi-model AI consensus, aggregation, and fusion runner for popular AI CLIs | AI Coding Agents |
|
||||||
| `hipengine` | ROCm-native local LLM inference engine with torch-free runtime for AMD RDNA GPUs | AI Inference |
|
| `hipengine` | ROCm-native local LLM inference engine with torch-free runtime for AMD RDNA GPUs | AI Inference |
|
||||||
| `mcp-gateway` | Universal Model Context Protocol gateway that sits between AI client and MCP tools/servers | MCP Servers |
|
| `mcp-gateway` | Universal Model Context Protocol gateway that sits between AI client and MCP tools/servers | MCP Servers |
|
||||||
| `nftables-analyzer` | Analyze nftables firewall rules and evaluate traffic queries | Networking |
|
| `nftables-analyzer` | Analyze nftables firewall rules and evaluate traffic queries | Networking |
|
||||||
@@ -140,6 +142,7 @@ nix-overlay/
|
|||||||
│ ├── default.nix # Binary-cache-friendly overlay
|
│ ├── default.nix # Binary-cache-friendly overlay
|
||||||
│ └── shared-nixpkgs.nix # Dependency-sharing overlay
|
│ └── shared-nixpkgs.nix # Dependency-sharing overlay
|
||||||
├── packages/ # Package definitions
|
├── packages/ # Package definitions
|
||||||
|
│ ├── awg-tool/ # AmneziaWG parameter generation and SSH deployment CLI
|
||||||
│ ├── aionui/ # AionUi - AI Cowork desktop app
|
│ ├── aionui/ # AionUi - AI Cowork desktop app
|
||||||
│ ├── container-use/ # Containerized environments for coding agents
|
│ ├── container-use/ # Containerized environments for coding agents
|
||||||
│ ├── default/ # Meta-package listing all packages
|
│ ├── default/ # Meta-package listing all packages
|
||||||
@@ -148,6 +151,7 @@ nix-overlay/
|
|||||||
│ ├── flake-inputs/ # Utility for caching flake inputs
|
│ ├── flake-inputs/ # Utility for caching flake inputs
|
||||||
│ ├── freebuff/ # Free coding agent (Codebuff)
|
│ ├── freebuff/ # Free coding agent (Codebuff)
|
||||||
│ ├── graphify/ # Knowledge graph generator for code folders
|
│ ├── graphify/ # Knowledge graph generator for code folders
|
||||||
|
│ ├── haivemind/ # Multi-model AI consensus runner
|
||||||
│ ├── hipengine/ # ROCm-native LLM inference engine for AMD GPUs
|
│ ├── hipengine/ # ROCm-native LLM inference engine for AMD GPUs
|
||||||
│ ├── kubernetes-mcp-server/ # MCP server for Kubernetes and OpenShift
|
│ ├── kubernetes-mcp-server/ # MCP server for Kubernetes and OpenShift
|
||||||
│ ├── loop/ # Corporate messenger for your team
|
│ ├── loop/ # Corporate messenger for your team
|
||||||
|
|||||||
5
packages/awg-tool/default.nix
Normal file
5
packages/awg-tool/default.nix
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
pkgs.callPackage ./package.nix { }
|
||||||
51
packages/awg-tool/package.nix
Normal file
51
packages/awg-tool/package.nix
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
rustPlatform,
|
||||||
|
fetchFromGitHub,
|
||||||
|
cmake,
|
||||||
|
perl,
|
||||||
|
}:
|
||||||
|
|
||||||
|
rustPlatform.buildRustPackage rec {
|
||||||
|
pname = "awg-tool";
|
||||||
|
version = "0.2.2";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "Vadim-Khristenko";
|
||||||
|
repo = "awg-containers-and-tools";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-z4LG+z60uqsfkRyt7Dc8Fc5GMfpiF7G0N9PXnzTUJms=";
|
||||||
|
};
|
||||||
|
|
||||||
|
# awg-core builds ssh2 with vendored-openssl, which compiles libssh2
|
||||||
|
# (via cmake) and OpenSSL (via perl Configure) from source.
|
||||||
|
nativeBuildInputs = [
|
||||||
|
cmake
|
||||||
|
perl
|
||||||
|
];
|
||||||
|
|
||||||
|
cargoHash = "sha256-Nb5tmwvhzKAldHai7yxtYapjbZmai0ujBX9c6nRGZk0=";
|
||||||
|
|
||||||
|
# Upstream tests exercise Docker/SSH targets; unit tests are already
|
||||||
|
# covered by the upstream CI before a release is cut.
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
category = "Networking";
|
||||||
|
updateScript = [
|
||||||
|
"nix-update"
|
||||||
|
"--flake"
|
||||||
|
".#awg-tool"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "CLI for AmneziaWG self-hosting — generates 1.0/1.5/2.0/3.0 obfuscation parameters, exports .conf and vpn:// configs, installs servers over SSH";
|
||||||
|
homepage = "https://github.com/Vadim-Khristenko/awg-containers-and-tools";
|
||||||
|
changelog = "https://github.com/Vadim-Khristenko/awg-containers-and-tools/releases/tag/v${version}";
|
||||||
|
license = licenses.mit;
|
||||||
|
sourceProvenance = with sourceTypes; [ fromSource ];
|
||||||
|
mainProgram = "awg-tool";
|
||||||
|
platforms = platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
||||||
1
packages/haivemind/default.nix
Normal file
1
packages/haivemind/default.nix
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ pkgs, ... }: pkgs.callPackage ./package.nix { }
|
||||||
459
packages/haivemind/fix-chat-log-race.patch
Normal file
459
packages/haivemind/fix-chat-log-race.patch
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
--- a/haivemind_tui.py
|
||||||
|
+++ b/haivemind_tui.py
|
||||||
|
@@ -1197,0 +1198,8 @@
|
||||||
|
+ def on_mount(self) -> None:
|
||||||
|
+ app = self.app
|
||||||
|
+ if (
|
||||||
|
+ getattr(app, "_prompt", None) is not None
|
||||||
|
+ and getattr(app, "_config", None) is not None
|
||||||
|
+ ):
|
||||||
|
+ app.start_run(app._prompt, app._config)
|
||||||
|
+
|
||||||
|
@@ -1220,13 +1220,13 @@
|
||||||
|
self._engine: HaivemindEngine | None = None
|
||||||
|
self._run_started = False
|
||||||
|
self._run_start_time: float = 0.0
|
||||||
|
+ self._main_screen = None
|
||||||
|
|
||||||
|
def on_mount(self) -> None:
|
||||||
|
- self.push_screen(MainScreen())
|
||||||
|
+ self._main_screen = MainScreen()
|
||||||
|
+ self.push_screen(self._main_screen)
|
||||||
|
self.set_interval(0.15, self._tick_spinner)
|
||||||
|
- if self._prompt is not None and self._config is not None:
|
||||||
|
- self.start_run(self._prompt, self._config)
|
||||||
|
- else:
|
||||||
|
+ if self._prompt is None or self._config is None:
|
||||||
|
self.push_screen(ConfigScreen())
|
||||||
|
|
||||||
|
def start_run(self, prompt: str, config: HaivemindConfig) -> None:
|
||||||
|
@@ -1303,7 +1303,7 @@
|
||||||
|
def _tick_spinner(self) -> None:
|
||||||
|
_advance_spinner()
|
||||||
|
try:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
if "streaming" in hbar._model_status.values():
|
||||||
|
hbar._refresh()
|
||||||
|
except NoMatches:
|
||||||
|
@@ -1315,20 +1315,20 @@
|
||||||
|
def _on_probe_start(self) -> None:
|
||||||
|
import time as _time
|
||||||
|
self._run_start_time = _time.time()
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
chat.add_summary("[bold yellow]Probing models...[/]")
|
||||||
|
if self._config is not None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_models(self._config.models)
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.consensus_info = "probing"
|
||||||
|
header.progress_pct = 0.0
|
||||||
|
|
||||||
|
@on(ProbeResult)
|
||||||
|
def _on_probe_result(self, event: ProbeResult) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "done" if event.ok else "failed")
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
if event.ok:
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
chat.add_summary(f"[{color}][probe] ok: {event.model}[/]")
|
||||||
|
@@ -1339,44 +1339,44 @@
|
||||||
|
|
||||||
|
@on(ProbeDone)
|
||||||
|
def _on_probe_done(self, event: ProbeDone) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
chat.add_summary(
|
||||||
|
f"[bold yellow]Probe complete:[/] {len(event.healthy)} healthy, "
|
||||||
|
f"{len(event.failures)} failed"
|
||||||
|
)
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.consensus_info = ""
|
||||||
|
if event.healthy:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_models(event.healthy)
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.update_layout(event.healthy, hbar._model_colors)
|
||||||
|
|
||||||
|
@on(RoundStart)
|
||||||
|
def _on_round_start(self, event: RoundStart) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
chat.add_summary(f"\n[bold cyan]\u2500\u2500 Round {event.round_idx}/{event.total} \u2500\u2500[/]")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.round_info = f"hAIvemind \u2502 Round {event.round_idx}/{event.total}"
|
||||||
|
header.consensus_info = ""
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.clear_all()
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@on(ModelStart)
|
||||||
|
def _on_model_start(self, event: ModelStart) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "streaming")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
total = len(hbar._model_status) if hbar._model_status else 0
|
||||||
|
done_count = sum(
|
||||||
|
1 for s in hbar._model_status.values() if s in ("streaming", "done")
|
||||||
|
)
|
||||||
|
header.model_info = f"Models: {done_count}/{total}"
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
active = [
|
||||||
|
m for m, s in hbar._model_status.items() if s != "dropped"
|
||||||
|
]
|
||||||
|
@@ -1386,27 +1386,27 @@
|
||||||
|
|
||||||
|
@on(ModelStream)
|
||||||
|
def _on_model_stream(self, event: ModelStream) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
t = event.fragment.strip()
|
||||||
|
if t:
|
||||||
|
chat.add_summary(f"[{color}][{event.model}][/] {t}")
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.stream_to_model(event.model, event.fragment)
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@on(ModelDone)
|
||||||
|
def _on_model_done(self, event: ModelDone) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
ar = event.agent_round
|
||||||
|
if ar.error and ar.error not in ("stderr",):
|
||||||
|
hbar.set_status(event.model, "failed")
|
||||||
|
else:
|
||||||
|
hbar.set_status(event.model, "done")
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
if ar.has_valid_draft:
|
||||||
|
chat.add_summary(
|
||||||
|
@@ -1419,14 +1419,14 @@
|
||||||
|
|
||||||
|
@on(ModelDropped)
|
||||||
|
def _on_model_dropped(self, event: ModelDropped) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "dropped")
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
chat.add_summary(
|
||||||
|
f"[red]\u26a0 {event.model} dropped:[/] {event.reason}"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
remaining = [
|
||||||
|
m for m, s in hbar._model_status.items() if s != "dropped"
|
||||||
|
]
|
||||||
|
@@ -1436,7 +1436,7 @@
|
||||||
|
|
||||||
|
@on(RoundDone)
|
||||||
|
def _on_round_done(self, event: RoundDone) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
dur = event.record.get("duration_s", 0)
|
||||||
|
chat.add_summary(
|
||||||
|
f"[dim]\u2500\u2500 end round {event.round_idx} ({dur}s) \u2500\u2500[/]"
|
||||||
|
@@ -1446,15 +1446,15 @@
|
||||||
|
best_sim = _compute_best_similarity(drafts)
|
||||||
|
threshold = self._config.threshold if self._config else 0.75
|
||||||
|
pct = min(1.0, best_sim / threshold) if threshold > 0 else 0.0
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.progress_pct = pct
|
||||||
|
header.consensus_info = f"sim: {best_sim:.2f}"
|
||||||
|
|
||||||
|
@on(Consensus)
|
||||||
|
def _on_consensus(self, event: Consensus) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
total_models = len(hbar._model_status) if hbar._model_status else 0
|
||||||
|
import time as _time
|
||||||
|
elapsed = (
|
||||||
|
@@ -1493,9 +1493,9 @@
|
||||||
|
|
||||||
|
@on(Fallback)
|
||||||
|
def _on_fallback(self, event: Fallback) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
total_models = len(hbar._model_status) if hbar._model_status else 0
|
||||||
|
header.consensus_info = "fallback"
|
||||||
|
header.progress_pct = 0.0
|
||||||
|
@@ -1518,30 +1518,30 @@
|
||||||
|
|
||||||
|
@on(EngineError)
|
||||||
|
def _on_engine_error(self, event: EngineError) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
chat.add_summary(f"[red]Error:[/] {event.message}")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.consensus_info = "error"
|
||||||
|
|
||||||
|
@on(EngineLog)
|
||||||
|
def _on_engine_log(self, event: EngineLog) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
chat.add_summary(event.message)
|
||||||
|
|
||||||
|
@on(MoaRefStart)
|
||||||
|
def _on_moa_ref_start(self, event: MoaRefStart) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "streaming")
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
chat.add_summary(f"[{color}]\U0001f4e1 [ref] {event.model} analyzing...[/]")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.round_info = "hAIvemind \u2502 MoA \u2502 References"
|
||||||
|
|
||||||
|
@on(MoaRefDone)
|
||||||
|
def _on_moa_ref_done(self, event: MoaRefDone) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
if event.err and not event.raw.strip():
|
||||||
|
hbar.set_status(event.model, "failed")
|
||||||
|
@@ -1552,32 +1552,32 @@
|
||||||
|
|
||||||
|
@on(MoaRefStream)
|
||||||
|
def _on_moa_ref_stream(self, event: MoaRefStream) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
t = event.fragment.strip()
|
||||||
|
if t:
|
||||||
|
chat.add_summary(f"[{color}][ref:{event.model}][/] {t}")
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.stream_to_model(event.model, event.fragment)
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@on(MoaAggStart)
|
||||||
|
def _on_moa_agg_start(self, event: MoaAggStart) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "streaming")
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
chat.add_summary(f"\n[bold {color}]\U0001f9e0 [aggregator] {event.model} synthesizing...[/]")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.round_info = "hAIvemind \u2502 MoA \u2502 Aggregating"
|
||||||
|
|
||||||
|
@on(MoaAggDone)
|
||||||
|
def _on_moa_agg_done(self, event: MoaAggDone) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
if event.raw.strip():
|
||||||
|
hbar.set_status(event.model, "done")
|
||||||
|
@@ -1588,14 +1588,14 @@
|
||||||
|
|
||||||
|
@on(MoaAggStream)
|
||||||
|
def _on_moa_agg_stream(self, event: MoaAggStream) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
t = event.fragment.strip()
|
||||||
|
if t:
|
||||||
|
chat.add_summary(f"[{color}][agg:{event.model}][/] {t}")
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.stream_to_model(event.model, event.fragment)
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
@@ -1604,18 +1604,18 @@
|
||||||
|
|
||||||
|
@on(FusionPanelStart)
|
||||||
|
def _on_fusion_panel_start(self, event: FusionPanelStart) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "streaming")
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
chat.add_summary(f"[{color}]\U0001f52c [panel] {event.model} analyzing...[/]")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.round_info = "hAIvemind \u2502 Fusion \u2502 Panel"
|
||||||
|
|
||||||
|
@on(FusionPanelDone)
|
||||||
|
def _on_fusion_panel_done(self, event: FusionPanelDone) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
if event.err and not event.raw.strip():
|
||||||
|
hbar.set_status(event.model, "failed")
|
||||||
|
@@ -1626,32 +1626,32 @@
|
||||||
|
|
||||||
|
@on(FusionPanelStream)
|
||||||
|
def _on_fusion_panel_stream(self, event: FusionPanelStream) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
t = event.fragment.strip()
|
||||||
|
if t:
|
||||||
|
chat.add_summary(f"[{color}][panel:{event.model}][/] {t}")
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.stream_to_model(event.model, event.fragment)
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@on(FusionJudgeStart)
|
||||||
|
def _on_fusion_judge_start(self, event: FusionJudgeStart) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "streaming")
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
chat.add_summary(f"\n[bold {color}]\u2696\ufe0f [judge] {event.model} analyzing...[/]")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.round_info = "hAIvemind \u2502 Fusion \u2502 Judging"
|
||||||
|
|
||||||
|
@on(FusionJudgeDone)
|
||||||
|
def _on_fusion_judge_done(self, event: FusionJudgeDone) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
if event.raw.strip():
|
||||||
|
hbar.set_status(event.model, "done")
|
||||||
|
@@ -1662,32 +1662,32 @@
|
||||||
|
|
||||||
|
@on(FusionJudgeStream)
|
||||||
|
def _on_fusion_judge_stream(self, event: FusionJudgeStream) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
t = event.fragment.strip()
|
||||||
|
if t:
|
||||||
|
chat.add_summary(f"[{color}][judge:{event.model}][/] {t}")
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.stream_to_model(event.model, event.fragment)
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@on(FusionSynthStart)
|
||||||
|
def _on_fusion_synth_start(self, event: FusionSynthStart) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
hbar.set_status(event.model, "streaming")
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
chat.add_summary(f"\n[bold {color}]\u270d\ufe0f [synth] {event.model} writing final answer...[/]")
|
||||||
|
- header = self.query_one("#header-bar", HeaderBar)
|
||||||
|
+ header = self._main_screen.query_one("#header-bar", HeaderBar)
|
||||||
|
header.round_info = "hAIvemind \u2502 Fusion \u2502 Synthesizing"
|
||||||
|
|
||||||
|
@on(FusionSynthDone)
|
||||||
|
def _on_fusion_synth_done(self, event: FusionSynthDone) -> None:
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
if event.raw.strip():
|
||||||
|
hbar.set_status(event.model, "done")
|
||||||
|
@@ -1698,14 +1698,14 @@
|
||||||
|
|
||||||
|
@on(FusionSynthStream)
|
||||||
|
def _on_fusion_synth_stream(self, event: FusionSynthStream) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
- hbar = self.query_one("#health-bar", ModelHealthBar)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
+ hbar = self._main_screen.query_one("#health-bar", ModelHealthBar)
|
||||||
|
color = hbar.model_color(event.model)
|
||||||
|
t = event.fragment.strip()
|
||||||
|
if t:
|
||||||
|
chat.add_summary(f"[{color}][synth:{event.model}][/] {t}")
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.stream_to_model(event.model, event.fragment)
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
@@ -1720,7 +1720,7 @@
|
||||||
|
|
||||||
|
def action_toggle_theatre(self) -> None:
|
||||||
|
try:
|
||||||
|
- tc = self.query_one("#theatre-container")
|
||||||
|
+ tc = self._main_screen.query_one("#theatre-container")
|
||||||
|
if tc.has_class("visible"):
|
||||||
|
tc.remove_class("visible")
|
||||||
|
else:
|
||||||
|
@@ -1734,13 +1734,13 @@
|
||||||
|
|
||||||
|
def action_clear_theatre(self) -> None:
|
||||||
|
try:
|
||||||
|
- theatre = self.query_one("#theatre-container", TheatrePanel)
|
||||||
|
+ theatre = self._main_screen.query_one("#theatre-container", TheatrePanel)
|
||||||
|
theatre.clear_all()
|
||||||
|
except NoMatches:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def action_show_artifacts(self) -> None:
|
||||||
|
- chat = self.query_one("#chat-log", ChatLog)
|
||||||
|
+ chat = self._main_screen.query_one("#chat-log", ChatLog)
|
||||||
|
if self._engine and self._engine.run_dir:
|
||||||
|
chat.add_summary(f"[bold]Artifacts:[/] {self._engine.run_dir}")
|
||||||
|
else:
|
||||||
62
packages/haivemind/package.nix
Normal file
62
packages/haivemind/package.nix
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
fetchFromGitHub,
|
||||||
|
python3Packages,
|
||||||
|
}:
|
||||||
|
|
||||||
|
python3Packages.buildPythonApplication rec {
|
||||||
|
pname = "haivemind";
|
||||||
|
version = "0.1.0";
|
||||||
|
pyproject = true;
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "dev-boz";
|
||||||
|
repo = "haivemind";
|
||||||
|
rev = "ce4a0437d41f57638b71a17e2ff3af524d5a1b6e";
|
||||||
|
hash = "sha256-x7NM2wHwi11i07jHTL9NgYJkzzlP+tOmJy027itRtWs=";
|
||||||
|
};
|
||||||
|
|
||||||
|
build-system = with python3Packages; [
|
||||||
|
setuptools
|
||||||
|
];
|
||||||
|
|
||||||
|
dependencies = with python3Packages; [
|
||||||
|
textual
|
||||||
|
];
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
./fix-chat-log-race.patch
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace haivemind_tui.py \
|
||||||
|
--replace-fail "sel.value = Select.BLANK" "sel.clear()" \
|
||||||
|
--replace-fail "v is Select.BLANK" "v is Select.NULL"
|
||||||
|
'';
|
||||||
|
|
||||||
|
doCheck = false;
|
||||||
|
pythonImportsCheck = [
|
||||||
|
"haivemind"
|
||||||
|
"haivemind_tui"
|
||||||
|
"haivemind_curses"
|
||||||
|
];
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
category = "AI Coding Agents";
|
||||||
|
updateScript = [
|
||||||
|
"nix-update"
|
||||||
|
"--flake"
|
||||||
|
".#haivemind"
|
||||||
|
"--version=branch=main"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Multi-model AI consensus, aggregation, and fusion runner for popular AI CLIs";
|
||||||
|
homepage = "https://github.com/dev-boz/haivemind";
|
||||||
|
changelog = "https://github.com/dev-boz/haivemind/commits/main";
|
||||||
|
license = licenses.mit;
|
||||||
|
mainProgram = "haivemind";
|
||||||
|
platforms = platforms.all;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user