Skip to content

Commit cefae61

Browse files
committed
release: merge develop into main for v0.30.2
2 parents e0ec879 + f5961e2 commit cefae61

16 files changed

Lines changed: 973 additions & 410 deletions

File tree

.github/workflows/dashboard.yml

Lines changed: 0 additions & 64 deletions
This file was deleted.

.github/workflows/docker-publish.yml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,29 @@ name: Build & Publish Docker Images (Swarm)
22

33
# Builds evo-nexus-runtime and evo-nexus-dashboard images using the
44
# Swarm-specific Dockerfiles (Dockerfile.swarm and Dockerfile.swarm.dashboard)
5-
# and pushes them to GitHub Container Registry (ghcr.io). The upstream
6-
# Dockerfile and Dockerfile.dashboard are intentionally NOT used here:
7-
# they are for local `docker compose up`, while these variants carry the
8-
# Swarm-specific bootstrap (entrypoint.sh, start-dashboard.sh, terminal-
5+
# and pushes them to Docker Hub under the `evoapicloud` namespace. The
6+
# upstream Dockerfile and Dockerfile.dashboard are intentionally NOT used
7+
# here: they are for local `docker compose up`, while these variants carry
8+
# the Swarm-specific bootstrap (entrypoint.sh, start-dashboard.sh, terminal-
99
# server native build, both CLIs on PATH).
1010
#
1111
# Triggers:
1212
# * push to main -> builds + publishes :latest
1313
# * push of a version tag -> builds + publishes :vX.Y.Z and :latest
1414
# * manual dispatch -> builds without pushing (dry-run)
15+
#
16+
# Required repository secrets:
17+
# * DOCKERHUB_USERNAME — Docker Hub account with push rights to evoapicloud
18+
# * DOCKERHUB_TOKEN — access token (Settings → Security → New Access Token)
1519
on:
1620
push:
1721
branches: [main]
1822
tags: ['v*']
1923
workflow_dispatch:
2024

2125
env:
22-
REGISTRY: ghcr.io
26+
REGISTRY: docker.io
27+
NAMESPACE: evoapicloud
2328
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
2429

2530
jobs:
@@ -28,7 +33,6 @@ jobs:
2833
runs-on: ubuntu-latest
2934
permissions:
3035
contents: read
31-
packages: write
3236
strategy:
3337
fail-fast: false
3438
matrix:
@@ -42,26 +46,22 @@ jobs:
4246
- name: Checkout
4347
uses: actions/checkout@v4
4448

45-
- name: Lowercase owner for ghcr.io
46-
id: owner
47-
run: echo "owner_lc=${GITHUB_REPOSITORY_OWNER,,}" >> "$GITHUB_OUTPUT"
48-
4949
- name: Set up Docker Buildx
5050
uses: docker/setup-buildx-action@v3
5151

52-
- name: Login to GitHub Container Registry
52+
- name: Login to Docker Hub
5353
if: github.event_name != 'workflow_dispatch'
5454
uses: docker/login-action@v3
5555
with:
5656
registry: ${{ env.REGISTRY }}
57-
username: ${{ github.actor }}
58-
password: ${{ secrets.GITHUB_TOKEN }}
57+
username: ${{ secrets.DOCKERHUB_USERNAME }}
58+
password: ${{ secrets.DOCKERHUB_TOKEN }}
5959

6060
- name: Extract metadata (tags, labels)
6161
id: meta
6262
uses: docker/metadata-action@v5
6363
with:
64-
images: ${{ env.REGISTRY }}/${{ steps.owner.outputs.owner_lc }}/${{ matrix.image }}
64+
images: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ matrix.image }}
6565
# Boa prática: publicar :latest junto com a tag versionada sempre
6666
# que um release (tag v*) for empurrado. Push para a branch main
6767
# sem tag também atualiza :latest.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ config/workspace.yaml
8282
config/routines.yaml
8383
config/triggers.yaml
8484
config/heartbeats.yaml
85+
config/smart-router.json
8586

8687
# ── Claude Code session data ─────────────
8788
.claude/projects/

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.30.2] - 2026-04-23
9+
10+
Patch release focused on CI/distribution: Docker images now ship from the official `evoapicloud` namespace on Docker Hub (public, no auth required on Swarm managers), and the legacy dashboard-only workflow was removed to unblock the build pipeline.
11+
12+
### Changed
13+
14+
- **Docker images published to Docker Hub under `evoapicloud/`** — the Swarm workflow (`.github/workflows/docker-publish.yml`) now pushes `evo-nexus-runtime` and `evo-nexus-dashboard` to `docker.io/evoapicloud/*` instead of `ghcr.io`. Requires `DOCKERHUB_USERNAME` + `DOCKERHUB_TOKEN` secrets on the repo. The `evonexus.stack.yml` template and `README.swarm.md` were updated to reference the public images — no `OWNER` placeholder to fill in, no `docker login` needed on Swarm managers.
15+
16+
### Removed
17+
18+
- **Redundant `dashboard.yml` workflow** — deleted `.github/workflows/dashboard.yml`, which built a Python+React-only dashboard image (`Dockerfile.dashboard`) that nothing consumes. The Swarm workflow already produces a strict superset (with terminal-server and both CLIs). This also fixes the build failure on `main` caused by a TypeScript peer-dep conflict in the legacy Dockerfile.
19+
820
## [0.30.1] - 2026-04-23
921

1022
Patch release focused on thread UX polish: session now swaps cleanly when switching threads via the sidebar, the agent is briefed explicitly about running inside a persistent thread (not a fresh one-shot session), the assignee dropdown stops hiding agents, and fresh installs no longer inherit Evolution-specific goal seed data.

README.swarm.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ long-running service. External REST APIs do not.
7575
resolver called `letsencryptresolver` (rename in the stack labels if
7676
your resolver has a different name).
7777
- A DNS A record pointing `evonexus.<yourdomain>` to the Swarm ingress.
78-
- Docker images published to a registry (the included GitHub Actions
79-
workflow publishes to `ghcr.io/<owner>/evo-nexus-{dashboard,runtime}`).
80-
- Either make the ghcr.io packages public, or run `docker login ghcr.io`
81-
on every Swarm manager before deploying.
78+
- Docker images are pulled from Docker Hub at
79+
`evoapicloud/evo-nexus-{dashboard,runtime}` (published by the included
80+
GitHub Actions workflow on every version tag and push to `main`).
81+
- The images are public, so no `docker login` is needed on the Swarm
82+
managers. If you fork the project and publish to your own namespace,
83+
update the `image:` lines in `evonexus.stack.yml`.
8284

8385
### Steps
8486

@@ -90,9 +92,10 @@ long-running service. External REST APIs do not.
9092
2. **Open Portainer → Stacks → Add stack.**
9193
- Name: `evonexus`
9294
- Paste the contents of `evonexus.stack.yml`
93-
- Replace the three placeholders: `OWNER` (your ghcr.io namespace),
94-
`evonexus.example.com` (your hostname, two places), and
95-
`traefik-public` (your Traefik overlay network name, several places)
95+
- Replace the placeholders: `evonexus.example.com` (your hostname,
96+
two places) and `traefik-public` (your Traefik overlay network
97+
name, several places). The images already point at the official
98+
`evoapicloud/evo-nexus-*` namespace on Docker Hub.
9699
- Click **Deploy**
97100

98101
3. **Watch the containers come up.** `evonexus_dashboard` serves the SPA

cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@evoapi/evo-nexus",
3-
"version": "0.30.1",
3+
"version": "0.30.2",
44
"description": "Unofficial open source toolkit for Claude Code — AI-powered business operating system",
55
"keywords": [
66
"claude-code",

config/smart-router.example.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"_comment": "OpenRouter Smart Router config. Copy to config/smart-router.json to customize. IDs validated against https://openrouter.ai/api/v1/models on 2026-04-23 — verify before editing. All listed models support tool/function calling.",
3+
"enabled": true,
4+
"port": 4891,
5+
"host": "127.0.0.1",
6+
"cooldown_ms": 60000,
7+
"upstream_timeout_ms": 60000,
8+
"breaker": {
9+
"enabled": true,
10+
"failure_threshold": 20,
11+
"window_ms": 10000,
12+
"reset_ms": 30000
13+
},
14+
"free_models": [
15+
"openai/gpt-oss-120b:free",
16+
"qwen/qwen3-coder:free",
17+
"meta-llama/llama-3.3-70b-instruct:free",
18+
"z-ai/glm-4.5-air:free"
19+
],
20+
"paid_models": [
21+
"google/gemini-2.5-flash",
22+
"moonshotai/kimi-k2",
23+
"anthropic/claude-sonnet-4.5"
24+
]
25+
}

dashboard/backend/knowledge/health_check.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,20 @@ def _schedule_hc(get_app_fn) -> None:
122122

123123

124124
def start_health_check_thread(get_app_fn) -> None:
125-
"""Start the background health check scheduler (idempotent)."""
126-
global _hc_started
125+
"""Start the background health check scheduler (idempotent).
126+
127+
Runs the first pass on a short-delay timer (not inline) so app startup
128+
isn't blocked by slow/unreachable Postgres connections. Without this
129+
initial pass, the classify_worker would spam the log for up to
130+
_INTERVAL_S (5 min) on boot if a connection is offline, because stale
131+
status='ready' from the last session won't be reconciled until the
132+
first scheduled tick.
133+
"""
134+
global _hc_started, _hc_timer
127135
with _hc_lock:
128136
if _hc_started:
129137
return
130138
_hc_started = True
131-
_schedule_hc(get_app_fn)
139+
_hc_timer = threading.Timer(5.0, _hc_loop, args=(get_app_fn,))
140+
_hc_timer.daemon = True
141+
_hc_timer.start()

0 commit comments

Comments
 (0)