Hero OS Enhancements #23

Open
opened 2026-03-11 22:49:49 +00:00 by mik-tf · 0 comments
Owner

Hero OS Enhancements

Context

Follow-up from #17 (Docker build pipeline). Tracks UI improvements, service integration, and deployment across Hero OS environments.

Active Deployments

Environment URL Image Tag Purpose
herodev2 https://herodev2.gent04.grid.tf :dev2 Active development target (gent04)
herodemo2 https://herodemo2.gent04.grid.tf :demo2 Demo environment (promoted from dev2)
herodev https://herodev.gent02.grid.tf :dev Frozen reference baseline
herodemo https://herodemo.gent02.grid.tf :demo Frozen reference baseline

Workflow

  • Git branching: development_{name} feature branches, squash merge to development
  • Cross-repo: use identical branch names across affected repos
  • Build & deploy: build-local.shDockerfile.pack → push → make update ENV=<env>
  • herodev2 runs Debian bookworm (glibc 2.36), build uses rust:1.93-bookworm

Session 1 — Completed

Toolbar/Dock

  • Books iframe integration with BASE_PATH
  • Biz tab added to dock
  • Forgejo → Foundry rename (icons, labels, socket symlinks)
  • Hero → Proxy rename in dock

Hero Indexer

  • /rpc proxy endpoint for JSON-RPC
  • Batch mode indexing
  • RPC helpers and socket symlinks (hero_indexer.sock)

Hero Embedder

  • Running on herodev2
  • Books search working via librarian
  • Bootstrap icons fixed (local font path)

Hero Books

  • BASE_PATH support for iframe routing
  • Theme sync (light/dark)
  • 21 books indexed (8,168 embeddings)
  • PDF export working

Hero Biz

  • BASE_PATH routing through proxy
  • CRM data loading in iframe

forge_url rename (fossil → foundry)

  • Updated across repos
  • Photos/Files islands working with new URLs
  • Socket symlinks: hero_foundry.sock, hero_forge.sock, hero_fossil.sock

Context switcher

  • Outside-click closes dropdown

Deploy Pipeline

  • OSIS seed data loaded (3 contexts)
  • Media seeding (Photos, Songs, Documents)
  • Smoke tests: 43/51 passing
  • :dev2 image rebuilt with 29 services

Session 2 — Completed

AIBroker Integration (TOP PRIORITY — done)

  • hero_aibroker server + UI running on herodev2 and herodemo2
  • 5 models configured: GPT-4o, GPT-4o Mini, Claude 3.5 Sonnet, Llama 3.3 70B, Llama 3.1 8B
  • 2 providers: OpenRouter + Groq
  • ZinitLifecycle API fixed (removed dead binary_path, added .branch() builder)
  • BASE_PATH proxy routing for iframe integration
  • Template script ordering fixed (rpcCall before content block)
  • zinit_sdk branch: development_kristofdevelopment
  • Service TOML: modelsconfig.yml seed heredoc (5 models auto-created on first start)
  • GROQ_API_KEY added to env config alongside OPENROUTER_API_KEYS
  • Build scripts updated: build-local.sh, build-services.sh, Dockerfile.pack
  • API keys auto-injected: app.env → container env → service config
  • Fresh :dev2 built, tested, promoted to :demo2
  • Both herodev2 and herodemo2 verified working
  • Theme sync: all templates use Bootstrap CSS variables, light/dark follows Hero OS

Commits:

  • hero_services development: Dockerfile.pack fix, build scripts, service TOML with 5-model seed
  • hero_aibroker development_timur: ZinitLifecycle API, BASE_PATH, script ordering, theme sync — PR #21 ready for devops review

Session 3 — Completed

MCP Integration: Hero Shrimp + AIBroker — VERIFIED on herodev2

Architecture Decision

Chose Path B (broker-mediated) over Path A (direct spawn):

Path A — Direct Spawn Path B — Broker-Mediated (chosen)
Flow Shrimp spawns mcp_hero as stdio child process Shrimp → hero_proxy → AIBroker UI → mcp_hero (stdio)
Config mcp.json in Shrimp workspace MCP_BROKER_ENDPOINT env var in Shrimp
Tool source Shrimp-local only Centralized in AIBroker for all consumers
AIBroker dependency Still needed (mcp_hero calls broker for LLM) Same

Why Path B:

  • Single source of truth — AIBroker owns all MCP server lifecycle and tool aggregation. Any consumer (Shrimp, Hero OS, future agents) sees the same tools.
  • Centralized AI/model management — models, API keys, and routing configured in AIBroker once; Shrimp just uses it.
  • AIBroker is required anywaymcp_hero's generate_code tool calls the broker's own /v1/chat/completions via Unix socket for LLM access.
  • Consistent with Hero OS design — all inter-service communication goes through hero_proxy.
  • Zero code changes in Shrimpmcp.ts already supports REST broker discovery via MCP_BROKER_ENDPOINT.

Production Flow

User → Shrimp (agent loop, tool routing)
          ↓ HTTP via hero_proxy
       AIBroker UI (/mcp/* endpoints)
          ↓ stdio JSON-RPC
       mcp_hero (5 tools: register_service, list_services,
                get_interface, generate_code, execute_code)
          ↓ Unix socket
       Any Hero service (hero_auth, hero_redis, hero_osis, ...)

Changes Made

hero_aibroker (development_timur):

  • mcp_servers.json: Added mcp_hero entry, fixed mcp-*mcp_* binary names, set HERO_LLM_MODEL to gpt-4o-mini
  • mcp_servers.example.json: Same model fix

hero_services (development):

  • services/user/hero_aibroker.toml: Added mcp_servers.json heredoc generation at startup, added MCP_CONFIG_PATH env var
  • services/user/hero_shrimp.toml: Added depends_on = ["hero_aibroker"], MCP_BROKER_ENDPOINT, AIBROKER_API_ENDPOINT, SHRIMP_WORKSPACE_DIR, model config
  • services/user/hero_shrimp.toml: Changed SHRIMP_OPENROUTER_MODELS from OpenRouter-format names (google/gemini-3-flash-preview) to AIBroker model names (gpt-4o-mini,claude-sonnet,llama-70b) so all LLM traffic routes through AIBroker
  • docker/build-local.sh: Added mcp_hero binary to aibroker build step, skill file copy to dist/var/

hero_shrimp (development_timur):

  • examples/mcp.json.hero_example: Fixed LLM model to gpt-4o-mini

Verification Results on herodev2

# MCP health: 1 server, 5 tools loaded
$ curl /hero_aibroker_ui/mcp/health
{"servers":1,"status":"ok","tools":5}

# Tools discovered:
hero_register_service, hero_list_services, hero_get_interface,
hero_generate_code, hero_execute_code

# Service registration test:
$ POST /mcp/tools/hero_register_service {socket_path: hero_redis_server.sock}
→ "Registered service 'hero_redis_server': 20 methods"

# Interface retrieval:
$ POST /mcp/tools/hero_get_interface {service_name: hero_redis_server}
→ Full Python interface with 20 typed methods (MSET, MGET, DATABASE_CREATE, etc.)

Issues Found and Fixed

  1. Model mismatch: mcp_hero defaulted to google/gemini-2.0-flash-001 which isn't in modelsconfig.yml → fixed to gpt-4o-mini
  2. Binary names: Active config used old dash names (mcp-ping) but binaries use underscores (mcp_ping) → fixed
  3. Build pipeline: build-local.sh didn't include mcp_hero in the aibroker build step → fixed
  4. Shrimp model routing bypass: Shrimp used OpenRouter-format model names (google/gemini-3-flash-preview) which AIBroker didn't recognize, causing fallback directly to OpenRouter → fixed by using AIBroker model names (gpt-4o-mini,claude-sonnet,llama-70b), now all LLM traffic goes through AIBroker

Session 4 — Completed

Shrimp Chat UI + Model Selection + Agent Loop Integration

  • Chat input added to Shrimp admin dashboard (Messages tab)
  • Model selector dropdown: 4 verified models (claude-sonnet, gpt-4o, claude-haiku, llama-70b)
  • AIBroker model config: removed broken models (gpt-4o-mini, llama-8b), added claude-haiku
  • Agent model override: POST /api/chat accepts model, passes through to agent loop
  • Rebuilt and deployed to herodev2 + herodemo2
  • Full chain verified: chat input → model selection → agent loop → MCP tools → result displayed

TODO — Next Sessions

Session 5.1 — Completed

Books Navigation

  • Prev/next buttons on book page view — server now returns prevPath/nextPath in books.getPage RPC response
  • "Other Pages" sidebar populated with full page list for current book (was empty because server didn't return otherPages)
  • Deployed to herodev2 and herodemo2 (incremental deploy)
  • Commit: hero_books developmentfeat(server): add page navigation to books.getPage RPC response

Session 5.2 — Completed

Embedder UI — Load Documents fix

  • Root cause: UI called async corpus.load (returns immediately, no progress). Switched to synchronous corpus.load_batch API with batched loop (250 docs/batch), real progress bar, and optimistic sidebar updates.
  • Fixed start_idx to begin from current namespace doc count (avoids re-processing existing docs as no-ops).
  • Added window.isLoadingCorpus guard to prevent pollNamespaceStats() from overwriting optimistic UI updates with stale async data.
  • Deployed to herodev2 — verified loading 500, 1K, 5K docs with accurate progress and sidebar count updates.
  • Commit: hero_embedder developmentfix(ui): use corpus.load_batch for real progress bar in Load Documents (52abf5c)

hero_books server.health fix

  • collectionsCount now returns real library count via discover_namespaces() instead of hardcoded 0.
  • embedderConnected now tests actual embedder connectivity via VectorStore::connect() instead of hardcoded false.
  • Commit: hero_books developmentfix(server): report real collectionsCount and embedderConnected in server.health (887da1c)

Service lifecycle fixes

  • hero_books_server zinit config: added serve subcommand (binary requires it, was exiting immediately → inactive).
  • Learned: zinit stop/start does NOT reload TOML config changes — must use zinit reload first.
  • Commit: hero_services developmentfix: add serve subcommand to hero_books_server exec (c9315c9)

Watchdog (stopgap for #25)

  • Added service watchdog to entrypoint.sh: polls every 60s, restarts inactive non-oneshot services.
  • Excludes .health/.install/.test oneshots and hero_cloud.
  • This is a temporary fix until #25 (zinit 0.4.0 native restart policies + health probes).
  • Commit: hero_services developmentfix: add serve subcommand to hero_books_ui + service watchdog (06e2cff)

Librarian UX — done

  • Loading spinner on search submit — button shows spinner + "Searching..." across all pages (search, library, book)
  • Voice transcription fix — transcribed text populates input for review instead of auto-submitting
  • Voice search on main search page — wired up initVoiceSearch() (was calling non-existent toggleVoiceRecording())
  • Deployed to herodev2 (incremental deploy). Note: hero_books_ui now requires serve subcommand (zinit config updated).
  • Commit: hero_books developmentfix(ui): add search spinner, fix voice transcription auto-submit

Session 6 — Island & Service UI Polish

Files island

  • Verify all features work 100% — upload, download, rename, delete, move, preview

Songs island

  • Right-click context menu should stay within Hero OS — not trigger browser native context menu

Contacts island

  • Forms need better layout — current fields are just bunched together, needs proper structure/grouping
  • Use Calendar right-panel info section as reference for good form layout

Business / Biz

  • Biz page seed data regression after fresh deploy
  • Search in Biz must work
  • Finance dashboard empty — needs data or placeholder
  • Once Biz (iframe) is fully working, remove the Business island (archipelago) to avoid duplication

Store island

  • Should work 100% or not be shown
  • Clicking "Install" should NOT change the toolbar — toolbar must stay consistent
  • Installed apps should appear in the dock/toolbar after install (not replace it)

Calendar island

  • Should be filled with sample/seed data
  • Right-section info panel is a good UI reference — consider reusing that pattern for other forms

Redis admin UI

  • Should be able to browse/switch between different databases

Books

  • Prev/next page buttons
  • Private book repos authentication (ourworld, geomind need authenticated git clone)

Session 7 — Code/Development & Foundry

  • Code/Development island is basically the API docs / tool explorer from Foundry
  • Decision needed: keep both separate, remove one, or merge Foundry + Code into a single integrated view

Backlog

Owned by devops team (timur, thabeta, kristof) — see #18

  • Shrimp model config: remove SHRIMP_OPENROUTER_MODELS duplication, fetch models dynamically from AIBroker /v1/models at startup (see #18 thabeta feedback)

Verify later

  • Voice transcription inconsistency — sometimes returns raw transcription, sometimes includes AI-generated answer text mixed in. Observed on herodemo2 after deploy, settled after a few calls (possible cold start / model warmup). Needs deeper investigation of /api/transcribe handler if it recurs.

Low priority / non-blocking

  • Install wasm-pack in Dockerfile.base for standalone island builds
  • Remaining 8 smoke test failures (43/51 currently passing)

After #23 — Infrastructure

  • #25: Migrate hero_services to zinit 0.4.0 job model (restart + health checks). Currently covered by watchdog hotfix (#24).

Cross-Repo Branch Status

Repo Branch Status
hero_services development Committed, pushed (Session 5.2: watchdog, serve subcommands, Makefile TAG)
hero_embedder development Committed, pushed (Session 5.2: corpus.load_batch UI fix)
hero_books development Committed, pushed (Session 5.2: server.health fix, serve subcommand)
hero_aibroker development_timur Committed, pushed, PR #21 open → development (needs devops review)
hero_shrimp development_timur Committed, pushed (no merge to development without devops review)

Reference — Operational Context

This section provides the details needed to pick up work in a new session without rediscovering everything.

SSH Access (via Mycelium IPv6)

Environment SSH Command
herodev2 ssh -6 root@503:b4a2:f8d6:8660:ff0f:a5a3:4288:fd88
herodemo2 ssh -6 root@519:bd05:a120:4128:ff0f:c6f8:677c:aa63

Container names match environment: herodev2, herodemo2. Access container shell with docker exec -it herodev2 bash.

Relevant Claude Code Skills

Check these skills for patterns and conventions when working on specific areas:

Skill When to use
hero_service Server, SDK, UI crate structure, Unix socket binding, OpenRPC spec, RPC proxy
hero_ui_dashboard Bootstrap 5.3, layout, tabs, cards, SSE, dark/light mode, JSON-RPC, auth
hero_ui_openrpc_proxy Standard /rpc proxy pattern for admin UIs
hero_rpc_server_lifecycle OServer::run_cli(), zinit integration, socket conventions
env_secrets Canonical env var names, sourcing pattern, secrets management
tfgrid_deploy Single-VM deployment, envs/ directory, Makefile orchestration
hero_sockets Unix socket strategy, health endpoint, discovery manifest
web_embed Embedding and CORS for web applications in iframes
hero_ecosystem Complete map of all repos, services, dependencies
zinit_cmd zinit CLI: add, list, status, start, stop, restart, logs
hero_branching Git branching model, development as default, merge workflow

Build Pipeline

Two deployment workflows: clean image build for shipping, hotfix deploy for rapid dev iteration.

Clean image build (from hero_services/ directory):

make dist              # Compile all binaries → dist/ (~3-15 min, incremental ~1-3 min)
make dist-quick        # Same but skip WASM + shrimp (faster iteration)
make pack              # Pack into hero_zero:dev2 Docker image
make push              # Push :dev2 to forge registry
make deploy            # Full pipeline: dist → pack → push → update herodev2

Promote dev2 → demo2 (after validating on herodev2):

make demo              # Tags :dev2 → :demo2, pushes, deploys to herodemo2

The TAG variable defaults to dev2. Override with make pack TAG=custom.

Hotfix deploy (patch a single binary without full image rebuild):

# 1. Build binary in bookworm container (glibc ≤ 2.36 required)
docker run --rm -v "$PWD:/src" -v hero-cargo-registry:/usr/local/cargo/registry \
  -w /src rust:1.93-bookworm cargo build --release -p hero_embedder_ui

# 2. Copy to VM, then into running container
scp -6 target/release/hero_embedder_ui root@[503:b4a2:...fd88]:/tmp/
ssh -6 root@[503:...] "docker cp /tmp/hero_embedder_ui herodev2:/root/hero/bin/"

# 3. Restart the service
ssh -6 root@[503:...] "docker exec herodev2 zinit stop user.hero_embedder_ui"
ssh -6 root@[503:...] "docker exec herodev2 zinit start user.hero_embedder_ui"

Hotfix caveats:

  • Changes are lost on container restart (container boots from the image)
  • If you changed a zinit TOML config, use zinit reload before stop/start
  • Must build with glibc ≤ 2.36 (bookworm) — native builds on newer distros fail with GLIBC_2.39 not found
  • Askama templates are compiled into the binary — template changes require rebuild
  • Use only on herodev2 for iteration; ship via clean image build for herodemo2

Full ops documentation: hero_services/docs/ops/deployment.md

Key Technical Patterns

BASE_PATH for iframe routing:

  • UI services behind hero_proxy need BASE_PATH env var (e.g., /hero_aibroker_ui)
  • Set in service TOML [env] section, read in main.rs, injected into Tera templates
  • All fetch URLs in JS must be prefixed: fetch(BASE_PATH + '/rpc', ...)
  • Use {{ base_path | safe }} in templates (the | safe prevents HTML escaping of /)

Template paths (CARGO_MANIFEST_DIR):

  • Templates are compiled with CARGO_MANIFEST_DIR baked into the binary
  • In the build container, source is mounted at /src/lhumina_code/<repo>/
  • So runtime template path = /src/lhumina_code/<repo>/crates/<crate>/templates/
  • Dockerfile.pack must COPY templates to this exact path

Theme sync (Hero OS ↔ service iframes):

  • All service UIs must include the hero:theme message listener JS
  • Use Bootstrap CSS variables (var(--bs-body-bg), var(--bs-body-color), var(--bs-tertiary-bg), var(--bs-border-color)) — NOT hardcoded colors
  • Do NOT use bg-dark text-white classes on form controls — Bootstrap handles this via data-bs-theme
  • The listener sets data-bs-theme on <html> when Hero OS sends a theme message

Env var resolution in service TOMLs:

  • __HERO_BIN__, __HERO_VAR__ patterns are resolved by hero_services_server
  • ${VAR_NAME} patterns (e.g., ${OPENROUTER_API_KEY}) reference container environment variables
  • API keys flow: app.envdocker run -e → container env → zinit service env
  • The update.sh script regenerates the container run script with API keys from app.env

Service TOML Structure

Service configs live in hero_services/services/user/. Each TOML has:

  • [service] — name, description
  • [build] — git URL, branch, install method
  • [server] — exec command (can be heredoc for seed data), kill_others
  • [ui] — exec command, kill_others
  • [env] — env vars (__VAR__ for paths, ${VAR} for secrets)
  • [profile] — actions list

Example with seed heredoc (hero_aibroker): the server exec uses sh -c 'mkdir -p ... && cat > config.yml << EOF ... EOF\nexec binary serve' to create config on first start.

API Key Management

Keys are stored in deploy/single-vm/envs/<env>/app.env and passed into the container via docker run -e. Current keys:

  • OPENROUTER_API_KEY — OpenRouter (GPT-4o, GPT-4o Mini, Claude Sonnet)
  • GROQ_API_KEY — Groq (Llama 70B, Llama 8B)
  • FORGEJO_TOKEN — Forge registry login + git clone

To update a key: edit app.env, then make update ENV=<env> to regenerate the container run script.

# Hero OS Enhancements ## Context Follow-up from #17 (Docker build pipeline). Tracks UI improvements, service integration, and deployment across Hero OS environments. ### Active Deployments | Environment | URL | Image Tag | Purpose | |-------------|-----|-----------|---------| | herodev2 | https://herodev2.gent04.grid.tf | `:dev2` | Active development target (gent04) | | herodemo2 | https://herodemo2.gent04.grid.tf | `:demo2` | Demo environment (promoted from dev2) | | herodev | https://herodev.gent02.grid.tf | `:dev` | Frozen reference baseline | | herodemo | https://herodemo.gent02.grid.tf | `:demo` | Frozen reference baseline | ### Workflow - Git branching: `development_{name}` feature branches, squash merge to `development` - Cross-repo: use identical branch names across affected repos - Build & deploy: `build-local.sh` → `Dockerfile.pack` → push → `make update ENV=<env>` - herodev2 runs Debian bookworm (glibc 2.36), build uses `rust:1.93-bookworm` --- ## Session 1 — Completed **Toolbar/Dock** - [x] Books iframe integration with BASE_PATH - [x] Biz tab added to dock - [x] Forgejo → Foundry rename (icons, labels, socket symlinks) - [x] Hero → Proxy rename in dock **Hero Indexer** - [x] `/rpc` proxy endpoint for JSON-RPC - [x] Batch mode indexing - [x] RPC helpers and socket symlinks (`hero_indexer.sock`) **Hero Embedder** - [x] Running on herodev2 - [x] Books search working via librarian - [x] Bootstrap icons fixed (local font path) **Hero Books** - [x] BASE_PATH support for iframe routing - [x] Theme sync (light/dark) - [x] 21 books indexed (8,168 embeddings) - [x] PDF export working **Hero Biz** - [x] BASE_PATH routing through proxy - [x] CRM data loading in iframe **forge_url rename (fossil → foundry)** - [x] Updated across repos - [x] Photos/Files islands working with new URLs - [x] Socket symlinks: `hero_foundry.sock`, `hero_forge.sock`, `hero_fossil.sock` **Context switcher** - [x] Outside-click closes dropdown **Deploy Pipeline** - [x] OSIS seed data loaded (3 contexts) - [x] Media seeding (Photos, Songs, Documents) - [x] Smoke tests: 43/51 passing - [x] `:dev2` image rebuilt with 29 services --- ## Session 2 — Completed **AIBroker Integration (TOP PRIORITY — done)** - [x] hero_aibroker server + UI running on herodev2 and herodemo2 - [x] 5 models configured: GPT-4o, GPT-4o Mini, Claude 3.5 Sonnet, Llama 3.3 70B, Llama 3.1 8B - [x] 2 providers: OpenRouter + Groq - [x] ZinitLifecycle API fixed (removed dead `binary_path`, added `.branch()` builder) - [x] BASE_PATH proxy routing for iframe integration - [x] Template script ordering fixed (`rpcCall` before content block) - [x] zinit_sdk branch: `development_kristof` → `development` - [x] Service TOML: modelsconfig.yml seed heredoc (5 models auto-created on first start) - [x] GROQ_API_KEY added to env config alongside OPENROUTER_API_KEYS - [x] Build scripts updated: `build-local.sh`, `build-services.sh`, `Dockerfile.pack` - [x] API keys auto-injected: app.env → container env → service config - [x] Fresh `:dev2` built, tested, promoted to `:demo2` - [x] Both herodev2 and herodemo2 verified working - [x] Theme sync: all templates use Bootstrap CSS variables, light/dark follows Hero OS **Commits:** - hero_services `development`: Dockerfile.pack fix, build scripts, service TOML with 5-model seed - hero_aibroker `development_timur`: ZinitLifecycle API, BASE_PATH, script ordering, theme sync — PR [#21](https://forge.ourworld.tf/lhumina_code/hero_aibroker/pulls/21) ready for devops review --- ## Session 3 — Completed **MCP Integration: Hero Shrimp + AIBroker — VERIFIED on herodev2** ### Architecture Decision Chose **Path B (broker-mediated)** over Path A (direct spawn): | | Path A — Direct Spawn | Path B — Broker-Mediated (chosen) | |---|---|---| | Flow | Shrimp spawns `mcp_hero` as stdio child process | Shrimp → hero_proxy → AIBroker UI → `mcp_hero` (stdio) | | Config | `mcp.json` in Shrimp workspace | `MCP_BROKER_ENDPOINT` env var in Shrimp | | Tool source | Shrimp-local only | Centralized in AIBroker for all consumers | | AIBroker dependency | Still needed (mcp_hero calls broker for LLM) | Same | **Why Path B:** - **Single source of truth** — AIBroker owns all MCP server lifecycle and tool aggregation. Any consumer (Shrimp, Hero OS, future agents) sees the same tools. - **Centralized AI/model management** — models, API keys, and routing configured in AIBroker once; Shrimp just uses it. - **AIBroker is required anyway** — `mcp_hero`'s `generate_code` tool calls the broker's own `/v1/chat/completions` via Unix socket for LLM access. - **Consistent with Hero OS design** — all inter-service communication goes through `hero_proxy`. - **Zero code changes in Shrimp** — `mcp.ts` already supports REST broker discovery via `MCP_BROKER_ENDPOINT`. ### Production Flow ``` User → Shrimp (agent loop, tool routing) ↓ HTTP via hero_proxy AIBroker UI (/mcp/* endpoints) ↓ stdio JSON-RPC mcp_hero (5 tools: register_service, list_services, get_interface, generate_code, execute_code) ↓ Unix socket Any Hero service (hero_auth, hero_redis, hero_osis, ...) ``` ### Changes Made **hero_aibroker** (`development_timur`): - [x] `mcp_servers.json`: Added `mcp_hero` entry, fixed `mcp-*` → `mcp_*` binary names, set `HERO_LLM_MODEL` to `gpt-4o-mini` - [x] `mcp_servers.example.json`: Same model fix **hero_services** (`development`): - [x] `services/user/hero_aibroker.toml`: Added `mcp_servers.json` heredoc generation at startup, added `MCP_CONFIG_PATH` env var - [x] `services/user/hero_shrimp.toml`: Added `depends_on = ["hero_aibroker"]`, `MCP_BROKER_ENDPOINT`, `AIBROKER_API_ENDPOINT`, `SHRIMP_WORKSPACE_DIR`, model config - [x] `services/user/hero_shrimp.toml`: Changed `SHRIMP_OPENROUTER_MODELS` from OpenRouter-format names (`google/gemini-3-flash-preview`) to AIBroker model names (`gpt-4o-mini,claude-sonnet,llama-70b`) so all LLM traffic routes through AIBroker - [x] `docker/build-local.sh`: Added `mcp_hero` binary to aibroker build step, skill file copy to `dist/var/` **hero_shrimp** (`development_timur`): - [x] `examples/mcp.json.hero_example`: Fixed LLM model to `gpt-4o-mini` ### Verification Results on herodev2 ``` # MCP health: 1 server, 5 tools loaded $ curl /hero_aibroker_ui/mcp/health {"servers":1,"status":"ok","tools":5} # Tools discovered: hero_register_service, hero_list_services, hero_get_interface, hero_generate_code, hero_execute_code # Service registration test: $ POST /mcp/tools/hero_register_service {socket_path: hero_redis_server.sock} → "Registered service 'hero_redis_server': 20 methods" # Interface retrieval: $ POST /mcp/tools/hero_get_interface {service_name: hero_redis_server} → Full Python interface with 20 typed methods (MSET, MGET, DATABASE_CREATE, etc.) ``` ### Issues Found and Fixed 1. **Model mismatch**: `mcp_hero` defaulted to `google/gemini-2.0-flash-001` which isn't in modelsconfig.yml → fixed to `gpt-4o-mini` 2. **Binary names**: Active config used old dash names (`mcp-ping`) but binaries use underscores (`mcp_ping`) → fixed 3. **Build pipeline**: `build-local.sh` didn't include `mcp_hero` in the aibroker build step → fixed 4. **Shrimp model routing bypass**: Shrimp used OpenRouter-format model names (`google/gemini-3-flash-preview`) which AIBroker didn't recognize, causing fallback directly to OpenRouter → fixed by using AIBroker model names (`gpt-4o-mini,claude-sonnet,llama-70b`), now all LLM traffic goes through AIBroker --- ## Session 4 — Completed **Shrimp Chat UI + Model Selection + Agent Loop Integration** - [x] Chat input added to Shrimp admin dashboard (Messages tab) - [x] Model selector dropdown: 4 verified models (`claude-sonnet`, `gpt-4o`, `claude-haiku`, `llama-70b`) - [x] AIBroker model config: removed broken models (`gpt-4o-mini`, `llama-8b`), added `claude-haiku` - [x] Agent model override: `POST /api/chat` accepts `model`, passes through to agent loop - [x] Rebuilt and deployed to herodev2 + herodemo2 - [x] Full chain verified: chat input → model selection → agent loop → MCP tools → result displayed --- ## TODO — Next Sessions ### Session 5.1 — Completed **Books Navigation** - [x] Prev/next buttons on book page view — server now returns `prevPath`/`nextPath` in `books.getPage` RPC response - [x] "Other Pages" sidebar populated with full page list for current book (was empty because server didn't return `otherPages`) - [x] Deployed to herodev2 and herodemo2 (incremental deploy) - [x] Commit: `hero_books` `development` — `feat(server): add page navigation to books.getPage RPC response` ### Session 5.2 — Completed **Embedder UI — Load Documents fix** - [x] Root cause: UI called async `corpus.load` (returns immediately, no progress). Switched to synchronous `corpus.load_batch` API with batched loop (250 docs/batch), real progress bar, and optimistic sidebar updates. - [x] Fixed `start_idx` to begin from current namespace doc count (avoids re-processing existing docs as no-ops). - [x] Added `window.isLoadingCorpus` guard to prevent `pollNamespaceStats()` from overwriting optimistic UI updates with stale async data. - [x] Deployed to herodev2 — verified loading 500, 1K, 5K docs with accurate progress and sidebar count updates. - [x] Commit: `hero_embedder` `development` — `fix(ui): use corpus.load_batch for real progress bar in Load Documents` (52abf5c) **hero_books server.health fix** - [x] `collectionsCount` now returns real library count via `discover_namespaces()` instead of hardcoded `0`. - [x] `embedderConnected` now tests actual embedder connectivity via `VectorStore::connect()` instead of hardcoded `false`. - [x] Commit: `hero_books` `development` — `fix(server): report real collectionsCount and embedderConnected in server.health` (887da1c) **Service lifecycle fixes** - [x] `hero_books_server` zinit config: added `serve` subcommand (binary requires it, was exiting immediately → inactive). - [x] Learned: `zinit stop/start` does NOT reload TOML config changes — must use `zinit reload` first. - [x] Commit: `hero_services` `development` — `fix: add serve subcommand to hero_books_server exec` (c9315c9) **Watchdog (stopgap for #25)** - [x] Added service watchdog to `entrypoint.sh`: polls every 60s, restarts inactive non-oneshot services. - [x] Excludes `.health`/`.install`/`.test` oneshots and `hero_cloud`. - [x] This is a temporary fix until #25 (zinit 0.4.0 native restart policies + health probes). - [x] Commit: `hero_services` `development` — `fix: add serve subcommand to hero_books_ui + service watchdog` (06e2cff) **Librarian UX — done ✅** - [x] Loading spinner on search submit — button shows spinner + "Searching..." across all pages (search, library, book) - [x] Voice transcription fix — transcribed text populates input for review instead of auto-submitting - [x] Voice search on main search page — wired up `initVoiceSearch()` (was calling non-existent `toggleVoiceRecording()`) - [x] Deployed to herodev2 (incremental deploy). Note: `hero_books_ui` now requires `serve` subcommand (zinit config updated). - [x] Commit: `hero_books` `development` — `fix(ui): add search spinner, fix voice transcription auto-submit` ### Session 6 — Island & Service UI Polish **Files island** - [ ] Verify all features work 100% — upload, download, rename, delete, move, preview **Songs island** - [ ] Right-click context menu should stay within Hero OS — not trigger browser native context menu **Contacts island** - [ ] Forms need better layout — current fields are just bunched together, needs proper structure/grouping - [ ] Use Calendar right-panel info section as reference for good form layout **Business / Biz** - [ ] Biz page seed data regression after fresh deploy - [ ] Search in Biz must work - [ ] Finance dashboard empty — needs data or placeholder - [ ] Once Biz (iframe) is fully working, remove the Business island (archipelago) to avoid duplication **Store island** - [ ] Should work 100% or not be shown - [ ] Clicking "Install" should NOT change the toolbar — toolbar must stay consistent - [ ] Installed apps should appear in the dock/toolbar after install (not replace it) **Calendar island** - [ ] Should be filled with sample/seed data - [ ] Right-section info panel is a good UI reference — consider reusing that pattern for other forms **Redis admin UI** - [ ] Should be able to browse/switch between different databases **Books** - [ ] Prev/next page buttons - [ ] Private book repos authentication (ourworld, geomind need authenticated git clone) ### Session 7 — Code/Development & Foundry - [ ] Code/Development island is basically the API docs / tool explorer from Foundry - [ ] Decision needed: keep both separate, remove one, or merge Foundry + Code into a single integrated view ### Backlog **Owned by devops team (timur, thabeta, kristof) — see #18** - [ ] Shrimp model config: remove `SHRIMP_OPENROUTER_MODELS` duplication, fetch models dynamically from AIBroker `/v1/models` at startup (see [#18 thabeta feedback](https://forge.ourworld.tf/lhumina_code/home/issues/18#issuecomment-11910)) **Verify later** - [ ] Voice transcription inconsistency — sometimes returns raw transcription, sometimes includes AI-generated answer text mixed in. Observed on herodemo2 after deploy, settled after a few calls (possible cold start / model warmup). Needs deeper investigation of `/api/transcribe` handler if it recurs. **Low priority / non-blocking** - [ ] Install `wasm-pack` in `Dockerfile.base` for standalone island builds - [ ] Remaining 8 smoke test failures (43/51 currently passing) ### After #23 — Infrastructure - #25: Migrate hero_services to zinit 0.4.0 job model (restart + health checks). Currently covered by watchdog hotfix (#24). --- ## Cross-Repo Branch Status | Repo | Branch | Status | |------|--------|--------| | hero_services | `development` | Committed, pushed (Session 5.2: watchdog, serve subcommands, Makefile TAG) | | hero_embedder | `development` | Committed, pushed (Session 5.2: corpus.load_batch UI fix) | | hero_books | `development` | Committed, pushed (Session 5.2: server.health fix, serve subcommand) | | hero_aibroker | `development_timur` | Committed, pushed, PR [#21](https://forge.ourworld.tf/lhumina_code/hero_aibroker/pulls/21) open → `development` (needs devops review) | | hero_shrimp | `development_timur` | Committed, pushed (no merge to `development` without devops review) | --- ## Reference — Operational Context This section provides the details needed to pick up work in a new session without rediscovering everything. ### SSH Access (via Mycelium IPv6) | Environment | SSH Command | |-------------|-------------| | herodev2 | `ssh -6 root@503:b4a2:f8d6:8660:ff0f:a5a3:4288:fd88` | | herodemo2 | `ssh -6 root@519:bd05:a120:4128:ff0f:c6f8:677c:aa63` | Container names match environment: `herodev2`, `herodemo2`. Access container shell with `docker exec -it herodev2 bash`. ### Relevant Claude Code Skills Check these skills for patterns and conventions when working on specific areas: | Skill | When to use | |-------|-------------| | `hero_service` | Server, SDK, UI crate structure, Unix socket binding, OpenRPC spec, RPC proxy | | `hero_ui_dashboard` | Bootstrap 5.3, layout, tabs, cards, SSE, dark/light mode, JSON-RPC, auth | | `hero_ui_openrpc_proxy` | Standard `/rpc` proxy pattern for admin UIs | | `hero_rpc_server_lifecycle` | `OServer::run_cli()`, zinit integration, socket conventions | | `env_secrets` | Canonical env var names, sourcing pattern, secrets management | | `tfgrid_deploy` | Single-VM deployment, envs/ directory, Makefile orchestration | | `hero_sockets` | Unix socket strategy, health endpoint, discovery manifest | | `web_embed` | Embedding and CORS for web applications in iframes | | `hero_ecosystem` | Complete map of all repos, services, dependencies | | `zinit_cmd` | zinit CLI: add, list, status, start, stop, restart, logs | | `hero_branching` | Git branching model, development as default, merge workflow | ### Build Pipeline Two deployment workflows: **clean image build** for shipping, **hotfix deploy** for rapid dev iteration. **Clean image build** (from `hero_services/` directory): ```bash make dist # Compile all binaries → dist/ (~3-15 min, incremental ~1-3 min) make dist-quick # Same but skip WASM + shrimp (faster iteration) make pack # Pack into hero_zero:dev2 Docker image make push # Push :dev2 to forge registry make deploy # Full pipeline: dist → pack → push → update herodev2 ``` **Promote dev2 → demo2** (after validating on herodev2): ```bash make demo # Tags :dev2 → :demo2, pushes, deploys to herodemo2 ``` The `TAG` variable defaults to `dev2`. Override with `make pack TAG=custom`. **Hotfix deploy** (patch a single binary without full image rebuild): ```bash # 1. Build binary in bookworm container (glibc ≤ 2.36 required) docker run --rm -v "$PWD:/src" -v hero-cargo-registry:/usr/local/cargo/registry \ -w /src rust:1.93-bookworm cargo build --release -p hero_embedder_ui # 2. Copy to VM, then into running container scp -6 target/release/hero_embedder_ui root@[503:b4a2:...fd88]:/tmp/ ssh -6 root@[503:...] "docker cp /tmp/hero_embedder_ui herodev2:/root/hero/bin/" # 3. Restart the service ssh -6 root@[503:...] "docker exec herodev2 zinit stop user.hero_embedder_ui" ssh -6 root@[503:...] "docker exec herodev2 zinit start user.hero_embedder_ui" ``` > **Hotfix caveats:** > - Changes are **lost on container restart** (container boots from the image) > - If you changed a zinit TOML config, use `zinit reload` before stop/start > - Must build with glibc ≤ 2.36 (bookworm) — native builds on newer distros fail with `GLIBC_2.39 not found` > - Askama templates are compiled into the binary — template changes require rebuild > - Use only on herodev2 for iteration; ship via clean image build for herodemo2 Full ops documentation: `hero_services/docs/ops/deployment.md` ### Key Technical Patterns **BASE_PATH for iframe routing:** - UI services behind hero_proxy need `BASE_PATH` env var (e.g., `/hero_aibroker_ui`) - Set in service TOML `[env]` section, read in `main.rs`, injected into Tera templates - All fetch URLs in JS must be prefixed: `fetch(BASE_PATH + '/rpc', ...)` - Use `{{ base_path | safe }}` in templates (the `| safe` prevents HTML escaping of `/`) **Template paths (CARGO_MANIFEST_DIR):** - Templates are compiled with `CARGO_MANIFEST_DIR` baked into the binary - In the build container, source is mounted at `/src/lhumina_code/<repo>/` - So runtime template path = `/src/lhumina_code/<repo>/crates/<crate>/templates/` - `Dockerfile.pack` must COPY templates to this exact path **Theme sync (Hero OS ↔ service iframes):** - All service UIs must include the `hero:theme` message listener JS - Use Bootstrap CSS variables (`var(--bs-body-bg)`, `var(--bs-body-color)`, `var(--bs-tertiary-bg)`, `var(--bs-border-color)`) — NOT hardcoded colors - Do NOT use `bg-dark text-white` classes on form controls — Bootstrap handles this via `data-bs-theme` - The listener sets `data-bs-theme` on `<html>` when Hero OS sends a theme message **Env var resolution in service TOMLs:** - `__HERO_BIN__`, `__HERO_VAR__` patterns are resolved by hero_services_server - `${VAR_NAME}` patterns (e.g., `${OPENROUTER_API_KEY}`) reference container environment variables - API keys flow: `app.env` → `docker run -e` → container env → zinit service env - The `update.sh` script regenerates the container run script with API keys from `app.env` ### Service TOML Structure Service configs live in `hero_services/services/user/`. Each TOML has: - `[service]` — name, description - `[build]` — git URL, branch, install method - `[server]` — exec command (can be heredoc for seed data), `kill_others` - `[ui]` — exec command, `kill_others` - `[env]` — env vars (`__VAR__` for paths, `${VAR}` for secrets) - `[profile]` — actions list Example with seed heredoc (hero_aibroker): the server exec uses `sh -c 'mkdir -p ... && cat > config.yml << EOF ... EOF\nexec binary serve'` to create config on first start. ### API Key Management Keys are stored in `deploy/single-vm/envs/<env>/app.env` and passed into the container via `docker run -e`. Current keys: - `OPENROUTER_API_KEY` — OpenRouter (GPT-4o, GPT-4o Mini, Claude Sonnet) - `GROQ_API_KEY` — Groq (Llama 70B, Llama 8B) - `FORGEJO_TOKEN` — Forge registry login + git clone To update a key: edit `app.env`, then `make update ENV=<env>` to regenerate the container run script.
mik-tf added this to the ACTIVE project 2026-03-11 23:01:24 +00:00
mik-tf changed title from Hero OS UI polish: toolbar fixes, Books/Biz integration, seed data, icon rendering to Hero OS UI polish: service dashboards, iframe integration, seed data, icon rendering 2026-03-12 12:34:57 +00:00
mik-tf changed title from Hero OS UI polish: service dashboards, iframe integration, seed data, icon rendering to Hero OS Enhancements 2026-03-12 20:21:34 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/home#23
No description provided.