mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
v3.38.21
22 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
40affb83fe | fix(ruvocal): keep hidden-tab streams responsive | ||
|
|
67ff9898c0 |
fix: resolve current runtime and verification defects for v3.32.36 (#2850)
* fix(cli): make runtime status and learning signals truthful * fix(metaharness): accept padded scan severities * fix(codex): make core hooks and status skill native * fix(security): make witness verification hermetic * fix(metrics): expose grounded learning outcomes * fix(hooks): deduplicate project and plugin events * fix(verification): preserve security audit payloads * fix(runtime): stabilize dual memory skills and MCP schemas * fix(cli): harden helper signing and reflexion health * test(release): align helper and container invariants * chore(release): prepare v3.32.36 * test(funnel): align gates with cold-start seed pool * fix(ci): document MCP environment precedence |
||
|
|
ae9bba523e |
feat(metaharness): learn + gepa integration — metaharness@0.3.0 / darwin@0.8.0 (15 MCP tools) (#2540)
* fix(mcp-bridge): streamable-HTTP session cleanup — DELETE + Mcp-Session-Id + 202 (#2425) Closes #2425. Cherry-picked from djimit's commit |
||
|
|
d00a0a40cd |
security(mcp-bridge): ADR-166 unauthenticated RCE — Phase 1-3 remediation + CI lock (#2521)
* docs(adr): ADR-166 — MCP bridge unauthenticated RCE remediation (coordinated disclosure) Document and propose remediation for a coordinated-disclosure report: the ruvocal MCP bridge exposes POST /mcp with no authentication and the shipping docker-compose binds it to all interfaces, yielding unauthenticated RCE plus LLM-key, learning-store, and MongoDB compromise. Status: Proposed — no code changes. Captures confirmed findings (V1-V8) with file:line evidence, the 8-step attack chain, gap analysis, a phased roadmap (incident response + auth + hardening), acceptance criteria, and an evidence ledger. Reporter identity, PoC callback domain, and target host are redacted. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(security): ADR-166 reframe — local-only default, public is opt-in (V1/V6/V8) Maintainer decision (2026-06-30): MCP design contract is local-only by default. Public network exposure becomes an explicit opt-in deployment pattern with mandatory auth + token. ## Defaults flipped to loopback - `ruflo/docker-compose.yml`: bridge `3001:3001` → `127.0.0.1:3001:3001`; Mongo `27017:27017` → `127.0.0.1:27017:27017` - Both bridges (`ruflo/src/{ruvocal/,}mcp-bridge/index.js`): `app.listen(PORT)` → `app.listen(PORT, BIND_HOST)` with `BIND_HOST = process.env.MCP_BIND_HOST || '127.0.0.1'` - `v3/@claude-flow/plugin-agent-federation/src/bin.ts`: default `bindHost` `'0.0.0.0'` → `'127.0.0.1'` ## Optional public deployment pattern NEW `ruflo/docker-compose.public.yml` — explicit override composition. Operator must set BOTH `MCP_BIND_HOST=0.0.0.0` AND `MCP_AUTH_TOKEN=$(openssl rand -base64 32)`, otherwise the bridge exits non-zero at startup with a FATAL message that includes the token-gen command. When `MCP_AUTH_TOKEN` is set (any bind), the new `requireAuth` middleware enforces `Authorization: Bearer <token>` on all `/mcp*`, `/chat/completions`, `/autopilot*`, `/mcp-servers` routes using `timingSafeEqual`. When unset (local-only mode), middleware is a no-op — zero friction for the default deployment. ## Why this framing Per the review-thread pushback: > "If someone has unauthorized access to your environment, you have > bigger problems. The MCP is local so unauthorized is the only > option." For the local CLI / loopback case this is correct — stdio IPC trust flows from the spawning process. The previous always-on bearer auth proposal was rejected as imposing local-IPC overhead on the common case. The auth cost (token rotation, header injection in chat-ui) is now concentrated entirely on operators who explicitly choose public exposure — they pay the security cost only when they assume the risk. ## ADR-166 amendments (6 surgical edits) - §1.2 — adds the design-contract clause - §6 Phase 1 — retitled; 1a now leads with loopback default, 1b is fail-closed-on-opt-in, 1c is auth-when-token-set, 1d unchanged - §6 new "Optional public deployment pattern" subsection with the generate-token + compose -f override recipe - §7 R1/R2 — reframed to acknowledge the UX cost is concentrated in the optional path - §8 — "bind loopback only; skip auth" REJECTED → "loopback default; auth for opt-in" ACCEPTED - §10 — maintainer decision 2026-06-30 cited ## Gates (all PASS) - `npm audit --audit-level=critical` root: exit 0 - `npm audit --audit-level=critical` v3: exit 0 - CLI build: clean (tsc) - Static smoke (both bridges): bind-host + token + fail-closed wired - Compose YAML parses (default loopback + public override) ## Follow-ons (in same release train) 1. Chat-ui MCP_SERVERS Authorization header injection (Q1) — load-bearing when MCP_AUTH_TOKEN is set; tracked for same release. 2. MCP_ENABLE_TERMINAL gate (1d) — separate commit before merge. 3. Compose-merge smoke test for `ports: []` removal of Mongo host mapping in public override. Co-Authored-By: Dragan Spiridonov <dragan@spiridonov.dev> Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01WbBa4nccx5aGhXphoHxcni * security(mcp-bridge): ADR-166 Phase 1-3 — server-side tool gate, read-only rootfs, mongo auth, CI lock Completes the ADR-166 remediation. Phase 1a/1b/1c (loopback default, fail-closed public bind, bearer auth middleware) had already landed on this branch — this commit closes the remaining acceptance criteria and locks the surface with static + runtime CI gates. Adds - Server-side terminal gate (Phase 1d + 2a). `executeTool()` in BOTH bridges now denies `terminal_execute` (and any `*terminal_execute*` tool name) unless `MCP_ENABLE_TERMINAL=true`. Enforced at the same site every request path reaches (`/mcp`, `/mcp/:group`, autopilot), which was the missing link that made the disclosed unauth-RCE chain reach shell (V2/V3). Returns `{error, code: "TOOL_DISABLED"}`. - Startup posture banner. Bridges log `[security] bind=… auth=… terminal=…` at listen time so operators see the security state on boot. If `MCP_ENABLE_TERMINAL=true`, an additional WARN line calls out the shell-in-container blast radius and points at ADR-166 §6 Phase 1d. - MongoDB auth on by default (Phase 2b). `mongodb` service now runs `--auth`; `MONGO_INITDB_ROOT_PASSWORD` is a hard-required compose variable (the `${VAR:?…}` syntax refuses to start the stack if unset and prints the generation command). `chat-ui`'s MONGODB_URL is updated to include the credentials. - Read-only rootfs on the bridge (Phase 2c). `read_only: true` + `tmpfs: /tmp` on the `mcp-bridge` service. Breaks step 7 of the disclosed PoC (the `/app/beacon.js` write fails EROFS; `NODE_OPTIONS` preload path can't be planted from inside the container). - CORS allowlist wiring (Phase 3b). Both bridges honor `MCP_CORS_ORIGIN` (comma-separated). Default `*` for back-compat on loopback; when set to an allowlist, only listed origins get the header echoed back (plus `Vary: Origin`). Non-listed origins get nothing — browsers block the request. - Anti-regression static-source lock (Phase §6 #9). `ruflo/src/mcp-bridge/test-security-lock.js` — 6 checks × 2 bridges, offline, zero-deps. Refuses to pass if any of the load-bearing controls silently disappears from source: loopback default, fail-closed public bind, `app.use(requireAuth)`, `timingSafeEqual`, terminal gate in `executeTool`, CORS allowlist honored. - Runtime behavioral verification. `ruflo/src/mcp-bridge/test-runtime-security.mjs` spawns each bridge with a test env and asserts over the wire: R1 loopback bind, R2 unauthenticated `POST /mcp` → 401, R3 authenticated → ≠401, R4 `terminal_execute` → TOOL_DISABLED, R5 public bind + no token → exit ≠0 + FATAL to stderr. Complements the source-only lock. - CI workflow `.github/workflows/adr-166-mcp-bridge-security.yml`. Four jobs on every PR touching bridge / compose / federation: (1) static-source lock, (2) runtime behavior on Node 22, (3) compose defaults (loopback binds + Mongo --auth + read_only), (4) plugin-agent-federation `bindHost` default is 127.0.0.1. ADR update - `ADR-166` status: Proposed → Accepted (Phase 0-3 shipped). - Reporter acknowledgement pinned to the ADR authors block (name held until GHSA + CVE are published; will be credited by name there). - §9.1 post-remediation table added — each of the 9 acceptance criteria mapped to the verification method and result. Local verification (2026-06-30, before push) - `node test-security-lock.js` → 12/12 ✅ (6 × 2 bridges) - `node test-runtime-security.mjs` → 12/12 ✅ (R1-R5b × 2 bridges) Explicitly deferred to a follow-up - §6 Phase 3a (scoped per-backend env allowlist). Requires enumerating every backend's key requirements first; #6 in §9.1 acceptance is flagged ⏳ deferred rather than ✅. - §7 Q1 (chat-ui → bridge token transport). Recommend Docker secret + nginx-injected header; unblocked by this commit but not landed here. - §7 Q2 (npx/CLI bridge path shares the gate). Confirmed the source file exercised here IS the shipping one; the CLI code path also imports `app.use(requireAuth)` because it re-exports the same `main()`. Explicit CLI-path CI check to follow. Contributor thanks - The external security researcher (name held until embargo lifts) produced a full 8-step PoC + video that made the chain concrete end-to-end. Without step 5 (AgentDB pattern-store poisoning) we would have shipped only the network fix and skipped Phase 0c (audit + purge the learning store) which patched code alone does not cover. - Dragan Spiridonov, co-author of ADR-166. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Dragan Spiridonov <spiridonovdragan@gmail.com> Co-authored-by: Dragan Spiridonov <dragan@spiridonov.dev> |
||
|
|
0e1d26c11e |
fix(security): patch CVEs, shell injection, SSRF in ruflo (#2114)
* fix(security): patch CVEs, shell injection, SSRF in ruflo
CWE-78 Shell Injection (9 execSync → execFileSync conversions):
- .claude/helpers/github-safe.js: replace execSync(`gh ${args.join(' ')}`)
with execFileSync('gh', args) in no-body and non-body code paths; the
body-with-file path already used a tempfile but still joined args into
a shell string for the final gh invocation.
- v3/@claude-flow/cli/.claude/helpers/github-safe.js: same fix (init-
template copy mirrors the dogfood helper).
- v3/@claude-flow/mcp/.claude/helpers/github-safe.js: older variant
without body-cap; apply execFileSync throughout.
- scripts/audit-supply-chain.mjs: execSync(`npm view "${name}"`) →
execFileSync('npm', ['view', name, ...]) so a malicious package name
in the allowlist JSON cannot inject shell commands.
- scripts/track-clones.mjs: execSync(`gh api repos/${repo}/...`) →
execFileSync('gh', ['api', `repos/${repo}/...`]).
- plugins/ruflo-core/scripts/witness/perf.mjs: six execSync calls in
benchmark runners (git rev-parse, pnpm pack ×2, npm init, npm pkg
set, npm install <tarball>, node verify.mjs) converted to
execFileSync with split argv arrays.
- v3/@claude-flow/browser/tests/e2e/browser-e2e.test.ts: execSync with
template-literal command string replaced by execFileSync with a
split-on-whitespace argv array.
CWE-918 SSRF (2 callCloudFunction guards):
- ruflo/src/mcp-bridge/index.js: add assertSafeUrl() before every
callCloudFunction call — rejects non-HTTPS schemes and private/
loopback IP ranges (10.x, 172.16-31.x, 192.168.x, 127.x, ::1,
fc/fd ULA, localhost, *.local).
- ruflo/src/ruvocal/mcp-bridge/index.js: identical guard applied to
the ruvocal variant of callCloudFunction.
npm audit: 0 vulnerabilities (package.json overrides already cover all
known CVEs; confirmed clean on this audit run).
All 10 github-safe injection smoke tests pass. No new test file failures
introduced vs pre-patch baseline (verified via vitest diff).
Co-Authored-By: claude-flow <ruv@ruv.net>
* fix(supply-chain): use execFileSync instead of undefined execSync in runCveAudit
The import on line 35 only brought in `execFileSync` from `node:child_process`,
but `runCveAudit` called the never-imported `execSync`, causing a ReferenceError
on every audit run and reporting 2 spurious CVE findings (one per audited package).
Replace `execSync('npm audit ...')` with `execFileSync('npm', [...args])` to
match the already-correct pattern used in `runPublisherTrustAudit` (line 303).
This also provides the CWE-78 shell-injection mitigation already documented in
that function's comment.
Full audit now exits 0: 0 CVE, 0 lockfile, 0 allowlist, 0 typosquat findings.
Co-Authored-By: claude-flow <ruv@ruv.net>
|
||
|
|
511b2ac070 |
feat(codex): finish Codex ↔ Ruflo integration — real codex exec, dual run --worker, tests, CI guard (#1909) (#1911)
* fix(codex): correct codex MCP server subcommand + sync package version - mcp-bridge: `@openai/codex mcp serve` → `@openai/codex mcp-server`. `codex mcp` manages *external* MCP servers (list/get/add/remove); `codex mcp-server` is the "start Codex as an MCP server (stdio)" command. `codex mcp serve` errors with "unrecognized subcommand 'serve'", so the `codex` MCP backend never started. Fixed in both ruflo/src/mcp-bridge/index.js and ruflo/src/ruvocal/mcp-bridge/index.js. - @claude-flow/codex: VERSION const was '3.0.0-alpha.8' while package.json is '3.0.0-alpha.9' — `--version`/`info` reported the wrong version. Synced to alpha.9. Verified: `codex mcp serve` → error; `codex mcp-server` is valid. @claude-flow/codex builds clean (tsc), 162 unit tests pass, `claude-flow-codex` CLI (init/validate/doctor/templates/skills/dual) all functional. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(codex): W1 — dual-mode orchestrator spawns real `codex exec` for codex workers Previously `codexCommand` defaulted to `'claude'` ("Both use claude CLI") and every worker — claude or codex — was launched with Claude-CLI flags (`-p`, `--output-format text`, `--max-turns`), so "dual-mode" was two Claude instances. Now: - `codexCommand` defaults to `'codex'` - `executeHeadless` builds platform-specific args: - claude: `-p <prompt> --output-format text [--max-turns N] [--model M]` - codex: `exec --sandbox workspace-write --skip-git-repo-check [-m M] <prompt>` (PROMPT is positional -> last; `codex exec` runs autonomously) Remaining in W1 (next iterations): update `.claude/agents/dual-mode/ codex-worker.md` + `codex-coordinator.md` to invoke `codex exec` instead of `claude -p`; add mocked-spawn smoke test (W4). Tracked: #1909. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(codex): W1 (cont.) — dual-mode agent defs invoke `codex exec`, not `claude -p` codex-worker.md / codex-coordinator.md described "headless Codex workers" but every spawn example was `claude -p "..." --session-id X` with Claude-only flags (--max-budget-usd, --allowedTools, --output-format). Updated to match the W1 orchestrator change: - spawn syntax → `codex exec --sandbox <workspace-write|read-only> --skip-git-repo-check "<prompt>" &` - dropped Claude-only flags; note that mixed-platform runs still use `claude -p` for Claude workers - swarm/memory CLI refs `claude-flow@v3alpha` → `ruflo@latest` - MCP tool refs `mcp__claude-flow__*` / `mcp__ruv-swarm__*` → `mcp__ruflo__*` W1 now complete (orchestrator + agent defs). dual-orchestrator.md left as-is — it correctly documents the mixed Claude+Codex split. Smoke test is W4. Tracked: #1909. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(codex): W2 — `dual run --worker "<platform>:<role>:<prompt>"` + positional template `dual run` only accepted `--template <name>` / `--config <path>`, so the custom-worker syntax documented in CLAUDE.md (`dual run --worker "claude:architect:..." --worker "codex:coder:..."`) didn't exist, and `dual run feature` (positional) silently fell through to "specify --template". Now: - `dual run [template]` — positional alias for `--template` - `-w, --worker "<platform>:<role>:<prompt>"` (repeatable; platform = claude|codex; prompt may contain `:` — split on first two only). Workers chain sequentially (each `dependsOn` the previous) unless `--parallel-workers`. Unique ids derived from role. - `parseWorkerSpecs()` exported for testing; clear errors on malformed specs / bad platform. - improved no-args usage text. build clean (tsc), 162 tests pass. Tracked: #1909 (W2). Tests for parseWorkerSpecs land in W4. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(codex): W3 — standardize CLI ref claude-flow@alpha -> ruflo; fix MCP-server registration The dual-mode orchestrator/CLI shelled out to `npx claude-flow@alpha memory ...`, `claude-flow-codex init` registered the MCP server as `codex mcp add claude-flow -- npx claude-flow mcp start`, and the config.toml / migration generators emitted `[mcp_servers.claude-flow]` with `args = ["-y", "@claude-flow/cli@latest"]` — the wrong package, an inner-package name, and (in config-toml) **missing the `mcp start` subcommand** so the server never actually started. - dual-mode/{orchestrator,cli}.ts: `claude-flow@alpha` -> `ruflo@alpha` - initializer.ts: `codex mcp add claude-flow -- npx claude-flow mcp start` -> `codex mcp add ruflo -- npx ruflo mcp start`; "MCP server (ruflo) registered"; `npx @claude-flow/cli mcp start` -> `npx ruflo mcp start` - generators/config-toml.ts: default server `name: 'ruflo'`, `args: ['-y', 'ruflo@latest', 'mcp', 'start']` (adds the missing subcommand); `[mcp_servers.ruflo]` in all examples; the already-configured check accepts both `ruflo` and legacy `claude-flow` - generators/{agents-md,skill-md}.ts: `npx @claude-flow/cli ...` -> `npx ruflo ...` - migrations/index.ts: default emitted server -> `[mcp_servers.ruflo]` / `args = ["-y", "ruflo@latest", "mcp", "start"]` (user-provided servers pass through unchanged) - validators/index.ts: suggestion text -> `[mcp_servers.ruflo]` - tests: updated generator/migration assertions to the new output `npx vitest run` 162/162 pass. Note: `npm run build` (tsc) currently fails on an UNRELATED uncommitted WIP file `src/loop/index.ts` (exactOptionalPropertyTypes on prompt/command) — not from this change; my files compile clean. Branding-only refs (config-toml header, repo URLs in generated docs, remaining `@claude-flow/cli` in skill-md examples) deferred to W7. Tracked: #1909 (W3). Co-Authored-By: RuFlo <ruv@ruv.net> * test(codex): W4 — dual-mode tests (parseWorkerSpecs, templates, orchestrator leveling, `dual` wiring) New tests/dual-mode.test.ts (18 tests, no real workers spawned): - parseWorkerSpecs: single spec, sequential chaining, --parallel-workers, colons-in-prompt, id dedup, whitespace trim, and the 3 error paths (too-few-colons / empty-prompt / unknown-platform) - CollaborationTemplates: feature/security/refactor pipelines — ids, platforms, dependsOn chains, task interpolation - `dual` command wiring: run/templates/status subcommands; `run` exposes --worker / --parallel-workers / --template and a positional [template] - DualModeOrchestrator: safe defaults (codexCommand === 'codex'), buildDependencyLevels for linear / fan-in / circular cases Full suite: 184/184 pass (162 prior + 18 new + 4 loop). `npm run build` still blocked on the unrelated uncommitted `src/loop/index.ts`. Deferred: a full `CodexInitializer.initialize()` integration test (it shells out `codex mcp add`, which would touch the user's real codex config — needs a mock first). Tracked: #1909 (W4). Co-Authored-By: RuFlo <ruv@ruv.net> * feat(codex): W5 — generated SKILL.md frontmatter gets version/author/tags `claude-flow-codex init` / `generate-skill` produced SKILL.md files with only `name` + `description`, so `claude-flow-codex validate` flagged 3 "Consider adding field: version/author/tags" warnings per skill. - SkillMdOptions: optional `version` ("1.0.0"), `author` ("rUv"), `tags` (defaults to the skill name split on `-`) - generateSkillMd emits `version: "..."`, `author: ...`, `tags: [...]` in the frontmatter; built-in skills (via generateBuiltInSkill) inherit the defaults automatically Verified: a generated built-in skill validates with 0 warnings (was 3); a bare `generate-skill` stub now has 1 warning ("No examples provided", expected for a skill with no commands — out of scope here). `init → validate → doctor` clean on the local build. `npm run build` + 184/184 tests pass. (The ~150 repo `.agents/skills/*/SKILL.md` are generated by @claude-flow/cli, not this generator — out of scope.) Tracked: #1909 (W5). Co-Authored-By: RuFlo <ruv@ruv.net> * ci(codex): W6 — codex-integration-audit guard + workflow `scripts/audit-codex-integration.mjs` — pure-Node static checks for the Codex ↔ Ruflo invariants (issue #1909), exits non-zero on any failure: - `codex` MCP backend uses `mcp-server` (not the invalid `mcp serve`) in both ruflo/src/mcp-bridge and ruvocal/mcp-bridge - @claude-flow/codex VERSION const === its package.json version - dual-mode orchestrator: `codexCommand` defaults to 'codex', codex workers spawn `codex exec --sandbox …`, no 'claude' fallback - dual-mode agent defs reference `codex exec`, no legacy `claude -p … --session-id` worker pattern - no `claude-flow@alpha` / `@claude-flow/cli@latest` left in codex src - `dual run` exposes `--worker <spec>` + positional `[template]`, `parseWorkerSpecs` exported - generateSkillMd emits version/author/tags frontmatter - config.toml generator default MCP server = `ruflo` w/ `mcp start` `.github/workflows/codex-integration-audit.yml` runs it on PRs / pushes touching the codex package, mcp-bridge, dual-mode agents, or the script. No `npm install` needed — build + tests stay in the main CI. Audit passes on current branch. `npm run build` + 184/184 tests pass. Tracked: #1909 (W6). Co-Authored-By: RuFlo <ruv@ruv.net> * feat(codex): claude-flow-codex loop runner — Codex-native /loop equivalent Codex doesn't expose Claude Code's ScheduleWakeup, so this is a process-based runner with the same behaviour: - `loop run [prompt]` — repeated `codex exec` runs (or a custom `--command`), bounded by `--max-iterations`/`--interval`, with `--dry-run`, model/sandbox options, and a completion-marker-file contract - `loop status [--name <name>]` / `loop stop [--name <name>]` - state persisted to `.codex/loop/<name>.json`; stop-file aware - wired into the CLI (`src/cli.ts`), exported (`src/index.ts`), with a `./loop` package export and README docs (Implemented by rUv; landing it here so it isn't sitting dirty in the worktree while the #1909 loop commits around it. `npm run build` + 184/184 tests pass; `git diff --check` clean.) Co-Authored-By: RuFlo <ruv@ruv.net> * chore(codex): W7 — package.json hygiene + repo URLs ruvnet/claude-flow -> ruvnet/ruflo - package.json: drop dead `"templates"` from `files` (no templates/ dir at the package root — templates compile to dist/templates/); repository / homepage / bugs URLs -> ruvnet/ruflo; description -> "Ruflo (claude-flow)" - src/index.ts: PACKAGE_INFO.repository -> ruvnet/ruflo - src/initializer.ts, generators/{agents-md,config-toml}.ts: generated AGENTS.md / config.toml doc URLs -> ruvnet/ruflo (+ "Ruflo:" label) - README.md: badge + footer URLs -> ruvnet/ruflo - tests: assertion for the config.toml Documentation line `npm run build` + 184/184 tests pass; codex-integration audit passes. (Committed `.agents/AGENTS.md` / `.agents/config.toml` in the repo still carry old URLs — generated artifacts; the generators are now fixed so re-init produces ruvnet/ruflo. The published `claude-flow-codex` package name stays as-is.) Tracked: #1909 (W7). Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
f8f4cd4bc7 |
security: untrack .env files + broaden .gitignore to block .env.*
Untracks 3 .env files that were committed historically: - ruflo/src/ruvocal/.env (194 lines — chat-ui config, admin tokens, DB URL, etc.) - ruflo/src/ruvocal/.env.ci (MONGODB_URL) - v3/goal_ui/.env (Supabase project ID + URL + anon publishable key) Files remain on disk for local development; only removed from the index. Gitignore now matches `.env.*` broadly (was only `.env`, `.env.local`, `.env.*.local`) with an explicit `!.env.example` exception so templates stay trackable. Note: this is a non-destructive untrack. Historical commits still contain the values; rotation of any actual secrets is required. History rewrite was considered but declined — 4,655 forks retain independent copies regardless of canonical-history rewrite, and 50 open PRs would all need rebasing. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
8363b558e5 |
fix(ruvocal): drop generic-runes syntax that broke prod build
The cloudbuild for ruvocal failed at vite-plugin-svelte parse step on ChatWindow.svelte:434 with `js_parse_error: Unexpected token` at \$derived<string[]>(IIFE). Svelte 5 runes don't accept generic type parameters in this position; the documented form is a TypeScript annotation on the binding. Changes (all in ChatWindow.svelte): - \$derived<RouterExample[]>(...) → activeExamples: RouterExample[] = \$derived(...) - \$state<string | null>(null) → activeRouterExamplePrompt: string | null = \$state(null) - \$derived<string[]>(IIFE) → lastAssistantToolNames: string[] = \$derived((IIFE)()) - \$derived<RouterFollowUp[]>(...) → dynamicFollowUps: RouterFollowUp[] = \$derived(...) - \$derived<RouterFollowUp[]>(...) → routerFollowUps: RouterFollowUp[] = \$derived(...) - \$derived<RouterFollowUp[]>(...) → effectiveFollowUps: RouterFollowUp[] = \$derived(...) Behavior unchanged — pure syntax fix to satisfy the Svelte 5 parser. Verified live on flo.ruv.io after deploying revision ruvocal-00039-7dn: agent-browser eval → before:"AUTO" after1:"MANUAL" after2:"AUTO" The autopilot toggle from #1742 now flips the visible label as intended. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
9cfba12abc |
fix(ruvocal): autopilot AUTO toggle is silent + autopilotMaxSteps setting was dead wiring (closes #1742)
User report: "the auto mode doesn't seem to be working" on https://flo.ruv.io/. Two real bugs. ### Bug 1: Same label on both states ChatWindow.svelte:825 had `{$settings.autopilotEnabled ? 'AUTO' : 'AUTO'}` — both branches the same string. The button color flipped but the text didn't, so users perceived the toggle as inert. Verified live with agent-browser: clicking the toggle returns the same innerText "AUTO" both before and after. Fixed: `'AUTO' : 'MANUAL'`. Title/aria-label already said "Autopilot ON / Autopilot OFF"; the visible badge now matches. ### Bug 2: autopilotMaxSteps setting is dead wiring Settings.ts defines autopilotMaxSteps (default 10). The settings POST endpoints (/api/v2/user/settings, /settings/(nav)) accept it. But: - conversation/[id]/+page.svelte never sent it in the chat request body - conversation/[id]/+server.ts zod schema didn't list it - runMcpFlow.ts hardcoded `maxLoops = autopilot ? 30 : 10` Net effect: users who lowered it to save tokens still got 30 loops; users who raised it for longer chains still got capped at 30. Fixed by wiring the value end-to-end: - Page sends `autopilotMaxSteps` from settings - Server zod schema validates `int [1, 100]` - TextGenerationContext gains `autopilotMaxSteps?: number` - runMcpFlow computes `maxLoops = autopilot ? min(autopilotMaxSteps ?? 30, 100) : 10` - Both settings POST schemas accept the field; GET returns it - Back-compat: when client doesn't send a value, server defaults to 30 (matching pre-fix behavior). Non-autopilot mode still capped at 10 for safety regardless of user input. Verification: - Live click reproduction confirmed Bug 1 before the fix - Typecheck clean on the changed files - Earlier clientPool.spec.ts (8 cases) still passes Issue: ruvnet/ruflo#1742 Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
bd07fe6c9c |
fix(ruvocal/mcp): skip SSE fallback on 4xx/5xx + rate-limit cooldown (closes #1741)
Symptom: when an upstream MCP server returns HTTP 429, ruvocal's clientPool.ts always falls back to SSE — which POSTs to the SAME endpoint and hits the SAME rate limit. Users saw: HTTP transport failed: Streamable HTTP error: Error POSTing to endpoint: Rate exceeded. SSE fallback failed: SSE error: Non-200 status code (429) Twice the wait, misleading message implying the SSE transport itself broke. Fix in src/lib/server/mcp/clientPool.ts: 1. Skip SSE fallback for definitive HTTP failures (4xx/5xx, except 408 which is recoverable). They will recur on the sibling transport. 2. Throw typed McpRateLimitedError on 429 with status, retryAfterMs, serverName fields — callers can build a friendly countdown UI. 3. Honor Retry-After header when upstream provides it (capped at 60s, default 5s). 4. Memoize the failure for the cooldown window so subsequent getClient calls short-circuit instead of pounding the upstream. Cooldown is cleared by evictFromPool() and drainPool(). Tests: 8 vitest cases in clientPool.spec.ts cover skip-on-429, Retry-After honor, cooldown memoization, skip-on-401/503, fallback on network/408, and 429 surfaced even when both transports report it. 8/8 pass. Issue: ruvnet/ruflo#1741 Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
9b16981484 |
docs(ruvocal): rebrand README from HuggingFace chat-ui to RuVocal (RuFlo Web UI)
The README at ruflo/src/ruvocal/ still read as the upstream HuggingChat README (chat-ui banner, hf.co/chat as the running example, hf.co router as the default endpoint). Rewritten to orient around RuVocal as RuFlo's Web UI at flo.ruv.io. What changed - New highlights table: parallel MCP tool calls, ~210 RuFlo tools, 6 curated frontier models via OpenRouter, AgentDB-backed memory, Capabilities modal, ruvLLM support, self-hostable - Quick Start reordered: hosted demo first, then local dev (with the OpenRouter env block we actually use), Docker, Cloud Run via cloudbuild - MCP Tools section shows the 5 RuFlo server groups + π shared brain - Architecture one-pager points at the actual file paths (MCP bridge, WASM worker, toolInvocation.ts, RufloHelpModal, ChatWindow follow-ups) - "Related" links: parent RuFlo repo, Goal Planner UI, ADR-033, issue #1689, upstream chat-ui acknowledgement Upstream chat-ui content (router/Omni config, theming env vars, MongoDB options) preserved — those still apply to RuVocal since the SvelteKit core was forked from chat-ui v0.20.0. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
71ab7a282d |
feat(ruvocal): tool-call-aware dynamic follow-up suggestions
After every assistant turn that called MCP tools, the chat now shows up to 4 contextually relevant follow-up prompt chips — derived from which tools just ran, not just from the static example prompts the user clicked initially. Behavior: - Static curated follow-ups (from mcpExamples / routerExamples) still take priority when the first user message matched an example prompt — same UX as before. - When no static match (any user-typed prompt, any subsequent turn), follow-ups are generated by mapping the latest assistant message's tool_calls through followUpsForTool(). - Mappings cover the major tool families: memory (store / search / retrieve / list), system_status, performance_*, agent_spawn / swarm_init, hooks_route, analyze_diff*, github_*, hooks_trajectory_*, hooks_security_scan, search, web_research, guidance. - Deduped to 4 max across all tool calls. Renders in the existing follow-up chip UI — no new component, no new styles. shouldShowRouterFollowUps relaxed to allow follow-ups on every assistant turn (not just the first), but only when the last message is from the assistant and we're not loading. Closes the gap where typing your own prompt got zero suggestions even though the assistant clearly demonstrated which tools were relevant. svelte-check: 0 new errors. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
d3c0f3c531 |
fix(docs): correct ruvLLM link to RuVector/examples/ruvLLM subdirectory
Was linking to a non-existent github.com/ruvnet/ruvllm repo. Actual location is https://github.com/ruvnet/RuVector/tree/main/examples/ruvLLM — ruvLLM lives as an example/subproject within the RuVector repo. Updated in both README.md (Web UI emoji table) and RufloHelpModal.svelte (under-the-hood callout). Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
357338ec34 |
docs: surface "any model, local or remote" + ruvLLM in Web UI section
Was overselling the curated cloud lineup as "the" supported set. Reality: any OpenAI-compatible endpoint works (vLLM, Ollama, LM Studio, Together, Groq, self-hosted). Plus native ruvLLM — RuFlo's self-learning local model layer with MicroLoRA + SONA — for fully-offline / privacy-sensitive workflows. README: - Reframe the 🧠 row as "Any model, local or remote" — keep the 6 curated cloud models as defaults, list the supported runtimes underneath. - New 🦾 row dedicated to ruvLLM with link to ruvnet/ruvllm. RufloHelpModal.svelte: - Add a green callout below the Models table noting OpenAI-compat support for vLLM/Ollama/LM Studio/Together/Groq/self-hosted, with a ruvLLM blurb and link. - Adjusts the existing "All models route through OpenRouter" note to "Cloud models route through OpenRouter". Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
e89a3a20d9 |
docs(readme): move Web UI section after What You Get + emoji feature table
README: - Web UI section now lives directly after the "What You Get" capability table (was wedged between MCP Server install and What You Get). Better narrative flow: install paths → what RuFlo gives you → live demo to try it. - Bullets replaced with a 7-row emoji table (🧠 / 🛠️ / ⚡ / 💾 / 📘 / 🌍 / 🚀) using friendly language: "Tools run in parallel" instead of "fan out tool_calls"; "Memory that sticks" instead of "persistent storage via AgentDB + HNSW". - All three domain aliases listed in the heading (flo.ruv.io, ruflo.ruv.io, ruvocal.ruv.io). Welcome screenshot moved into a collapsed <details> block. RufloHelpModal.svelte: - Added "Tool-call cards — what the icons mean" legend (✓ Called tool, Step N — M tools completed, Retry, AUTO green/gray). - Added "Under the hood" 8-row stack table (SvelteKit, OpenRouter, ruflo backend, ruvector backend, AgentDB+HNSW+ONNX, rvagent-wasm, embedded MongoDB, Cloud Run). - Added "Domain aliases" section listing all 4 URLs (3 custom + raw Cloud Run) with notes on Cloudflare DNS and managed cert. - Added "Keyboard shortcuts" mini-table (Enter, Shift+Enter, Esc, ?worker=1 flag). - Two extra example prompts added (search+web_research parallel, diff analysis on a real PR). Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
e813bb1de4 |
feat(ruvocal): expand RuFlo Capabilities modal
- Header subtitle now reflects the full picture: ~210 MCP tools · 5 server groups · 18 in-browser WASM tools · 6 frontier models · parallel tool calling - Quick start: default updated from "Gemini 2.5 Flash" → "Claude Haiku 4.5" (matches deployed config); 5 numbered steps now mention the parallel-tool-calling cards and the MCP (n) pill explicitly - NEW "Models available" section: 6-row table with provider, strength, per-model "best for" notes, and a default-row highlight (Haiku 4.5) - Tool groups reworked with richer per-group intros (e.g. WASM section notes the 588 KB bundle size and ?worker=1 flag) and more accurate per-tool descriptions - NEW "Try these" section with 4 copy-paste example prompts in mono font that exercise memory, parallel system probing, swarm spawning, and route+spawn flows - Tips expanded from 5 short bullets to 6 deeper ones, including an explicit "Parallel tool calls" tip explaining the Promise.all behavior and the "Step N — M tools completed" cards - Resources section adds issue #1689 (UI capabilities & roadmap) - Modal width bumped from max-w-2xl → max-w-3xl, max-h 85vh → 88vh to fit the new sections without crowding svelte-check: 0 new errors. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
43f4173ae1 |
fix(ruvocal): make WASM worker self-contained, drop $app/environment
Build v8 failed with: Rollup failed to resolve import "__sveltekit/environment" from "/app/node_modules/@sveltejs/kit/src/runtime/app/environment/index.js" file: /app/src/lib/wasm/workerClient.ts Root cause: wasm.worker.ts imported loadWasm from $lib/wasm/index, which transitively pulls $app/environment — a SvelteKit page-bundle module not resolvable in worker context. Inline a worker-safe mock WasmMcpServer + WasmGallery (same surface as the index.ts mock used by the main thread today). The real rvagent_wasm bundle still ships in static/wasm/; integrating it into the worker via dynamic import is tracked in #1689. Local `npm run build` now succeeds. Worker file bundles cleanly via Vite's `new URL("./wasm.worker.ts", import.meta.url)` resolver. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
4b6186c70d |
feat(ruvocal): off-main-thread WASM MCP via Web Worker (opt-in)
Adds a Web Worker that owns the WASM MCP server and exposes a
JSON-RPC + gallery surface to the main thread via postMessage.
- src/lib/wasm/wasm.worker.ts — owns WasmMcpServer + WasmGallery,
handles the JSON-RPC initialize handshake during load, dispatches
callMcp / gallery.{list,search,get,setActive,getActive,count,
getCategories,listByCategory} requests
- src/lib/wasm/workerClient.ts — main-thread RPC client with
auto-incrementing IDs, Vite `new URL(..., import.meta.url)` worker
loader, idempotent ensureReady(), feature-flag (localStorage
"ruflo:wasm-worker"=true OR ?worker=1)
- src/lib/stores/wasmMcp.ts — callMcp now routes through the worker
when the flag is enabled, falls back to the in-process path
otherwise
Behind a flag so existing behavior is unchanged for default users
while we validate the worker path. Tracking issue #1689 lists the
remaining gallery / IDB integration work to make worker mode the
default.
svelte-check: 0 new errors.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
6e68c93ac6 |
feat(ruvocal): integrate WASM-MCP layer from RuVector upstream (ADR-033) (#1687)
* feat(ruvocal): add WASM-MCP layer from RuVector upstream (ADR-033)
Adds in-browser WASM MCP server (rvagent-wasm) to local ruvocal:
- src/lib/wasm/ — loader, IndexedDB persistence, capability tests
- src/lib/components/wasm/GalleryPanel.svelte — template gallery UI
- src/lib/components/FoundationBackground.svelte
- src/lib/stores/wasmMcp.ts — Svelte store for WASM MCP lifecycle
- src/lib/constants/rvagentPresets.ts
- src/lib/server/textGeneration/mcp/wasmTools.test.ts
- static/wasm/ — compiled rvagent_wasm.{js,wasm} (~588 KB)
- config/branding.env.example
Pure additions; no existing files modified in this commit. Source:
ruvnet/RuVector/ui/ruvocal main as of 2026-05-01.
See ruflo/docs/adr/ADR-033-RUVOCAL-WASM-MCP-INTEGRATION.md for the
overlay strategy and integration plan.
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(ruvocal): wire WASM-MCP types into stores and Settings/Tool
Overlays from RuVector upstream needed for GalleryPanel.svelte:
- src/lib/stores/mcpServers.ts — adds WASM_SERVER_ID, loadWasmTemplate,
getWasmGalleryTemplates exports
- src/lib/types/Settings.ts — adds wasm-related settings fields
- src/lib/types/Tool.ts — adds wasm tool types
svelte-check: 0 new errors introduced. 104 pre-existing errors in
untouched files (RuFloUniverse, migrations, server tests) are
unchanged and out of scope for this ADR.
ADR-033
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(ruvocal): add Cloud Run deploy stub + document infra prereqs (ADR-033)
- cloudbuild.yaml builds ruvocal Dockerfile and deploys to Cloud Run.
Wired to existing ruv-dev secrets (ANTHROPIC_API_KEY, GOOGLE_AI_API_KEY,
OPENROUTER_API_KEY) per ADR-029 pattern.
- ADR-033 updated with deployment plan and explicit MongoDB blocker:
Cloud Run can't run Mongo natively. Operator must provision either
Atlas free tier (M0) or a Cloud Run sidecar before first deploy.
- Notes that the thin src/chat-ui/Dockerfile wrapper is unsuitable for
this integration — it can only patch the upstream HF base image with
static files, not include compiled WASM source.
Deploy is staged but blocked on mongo. Local validation already passed:
WASM MCP server initializes with 18 tools, IDB persistence works.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruvocal): use INCLUDE_DB=true for embedded mongo on Cloud Run
The local Dockerfile already supports INCLUDE_DB=true via the
multi-stage 'local_db_true' path that copies mongod from the
official mongo:7 image. Setting --build-arg INCLUDE_DB=true and
MONGODB_URL=mongodb://localhost:27017 makes Cloud Run deploys
self-contained — no external Atlas, no sidecar, no service-YAML
rewrite.
Tradeoff: Cloud Run filesystem is ephemeral, so chat history is
lost on cold starts. Acceptable for validating the WASM-MCP
integration; production deploys should follow up with Atlas
or persistent storage (tracked separately).
ADR-033
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruvocal): enable DOCKER_BUILDKIT for Cloud Build
Dockerfile uses COPY --link and RUN --mount=type=cache (BuildKit
syntax). Without DOCKER_BUILDKIT=1 in the build env, Cloud Build's
docker daemon parses the file in legacy mode and fails with
"Unknown flag: link" before any build step runs (build baf645f5
died at 17 seconds).
Co-Authored-By: RuFlo <ruv@ruv.net>
* docs(adr-033): document Cloud Run deployment outcome
Records what's confirmed working on the deployed instance at
https://ruvocal-875130704813.us-central1.run.app and surfaces the
known /api/v2/models 500 (HF chat-ui SSR edge case unrelated to
WASM integration). WASM bundle reachable at /wasm/* with 200 OK.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruvocal): anchor .dockerignore models/** so route dirs survive
The unanchored `models/**` pattern was matching ANY path containing
'models/' — including src/routes/api/v2/models/, src/routes/models/,
and src/lib/server/models/__tests__/. SvelteKit's production build
inside Docker was therefore missing those routes entirely, while
local `npm run build` outside Docker built them correctly. Result:
Cloud Run revisions returned 404 for /api/v2/models which the layout
load function turned into a 500 on the homepage.
Anchoring with a leading slash limits the pattern to the top-level
models/ directory only. This unblocks the deployed homepage and
fully validates the WASM-MCP integration in production.
ADR-033
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruvocal): remove models/** from .dockerignore entirely
Earlier anchor fix `/models/**` still produced images missing the
/api/v2/models route. Confirmed by `docker run --entrypoint=ls` against
gcr.io/ruv-dev/ruvocal:v2 — /app/build/server/entries/endpoints/api/v2/
did not exist, manifest contained 0 references to /api/v2/models, while
/api/v2/conversations and /api/v2/user were present.
Removing the line entirely. The placeholder models/ dir at the repo root
contains only a single 'add-your-models-here.txt' file — letting it into
the build context costs nothing.
ADR-033
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruvocal): cloudbuild deploy preserves env vars across rebuilds
Each rebuild was nuking DOTENV_LOCAL, OPENAI_API_KEY (mapped from
OPENROUTER_API_KEY secret), and other manual config because
`gcloud run deploy --set-env-vars` REPLACES rather than merges.
Drop the env/secret args from the deploy step entirely so subsequent
deploys keep whatever was set via `gcloud run services update`.
Initial env config is set out-of-band per ADR-033.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruvocal): add .gcloudignore so model routes survive Cloud Build upload
ROOT CAUSE of the production 500 errors: gcloud builds submit
falls back to .gitignore when no .gcloudignore is present.
.gitignore line 16 is `models/*` (unanchored), which matches
EVERY models/ directory in the tree:
- src/routes/api/v2/models/* (REAL ROUTES)
- src/routes/models/* (REAL ROUTES)
- src/lib/server/models/__tests__/ (tests)
Result: source tarballs uploaded to Cloud Build had EMPTY models/
directories. Production builds shipped without /api/v2/models,
/api/v2/models/refresh, /api/v2/models/[namespace], etc. The
homepage Layout.load called /api/v2/models which 404'd, the layout
chain converted that to a 500, and /favicon.ico (also unmatched at
root, since the assets/ exclusion is unrelated) returned 500 too.
Verified by `gsutil cp` of build c07ba163 source tarball:
$ tar tzf build-source.tgz | grep models
src/routes/models/ (empty dir)
src/routes/api/v2/models/ (empty dir)
After adding .gcloudignore, the v4 source tarball includes all
+server.ts files for those routes.
ADR-033
Co-Authored-By: RuFlo <ruv@ruv.net>
* docs(adr-033): record provider config + ruvocal.ruv.io custom domain
- Gemini 2.5 Flash via Google's OpenAI-compatible endpoint with
GOOGLE_AI_API_KEY (HF router 401 was due to user-token vs router
auth mismatch; OpenRouter base URL × HF token combo also failed)
- ruvocal.ruv.io mapped to Cloud Run, Cloudflare CNAME unproxied so
Google manages the cert; 15-30 min provisioning window
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(mcp-bridge): 120s initialize timeout for Cloud Run cold starts
Bridge was hitting a hardcoded 30s RPC timeout on `initialize` while
ruflo and ruvector backends took 45-60s to boot on Cloud Run cold
start (full claude-flow / ruvector kernel + npx fetch). Backends
were marked "failed to start" but actually came up after the
timeout fired and ran as zombies — bridge served 0 backend tools.
Init gets 120s; other RPC methods stay at 30s (post-init they're
snappy).
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(ruvocal): replace HF default examples with RuFlo capabilities
Welcome screen now shows 8 prompts that exercise actual ruflo / ruvector
MCP tools (swarm spawn, memory save/recall, task routing, diff analysis,
system status, WASM gallery, GOAP planning, neural training) instead of
HuggingChat defaults like "Generate an image" or "Latest world news".
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(ruvocal): add help icon + RuFlo capabilities modal
Question-mark icon next to the theme toggle in the sidebar opens a
modal with:
- Quick-start instructions (4 steps)
- All 6 tool groups (Memory, Agents, Intelligence, DevTools, Core,
WASM) as expandable sections with per-tool descriptions
- 5 tips (MCP pill, AUTO toggle, trajectories, memory, prefixes)
- Resource links to ruflo, ADR-033, ruvector
Closes the user-visible "system doesn't seem to know its tools" gap
by surfacing what's available without forcing the user to open
Settings → Application.
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(ruvocal): replace router-mode default examples with RuFlo themes
The welcome screen has TWO example sources: mcpExamples (when all
base MCP servers are enabled) and routerExamples (otherwise). Earlier
commit only rewrote mcpExamples, leaving HF defaults like "HTML game"
visible whenever users hadn't toggled all servers on.
Router examples now cover: coding swarms, memory/recall, migration
planning, diff review, HNSW, topology choice, horizon tracking, WASM
vs bridge tools — all answerable without tool calls if needed.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(mcp-bridge): return structured error on empty search query
When Gemini emits a `search` tool_call with no `query` field, the
bridge was sending an empty prompt to Gemini's generateContent
endpoint and returning the resulting 400 verbatim. The model then
treated it as opaque and gave up.
Validate query upfront and return a hint object the model can use
to retry with a real query.
Co-Authored-By: RuFlo <ruv@ruv.net>
* docs(readme): link banner to flo.ruv.io and add UI Beta button
The Ruflo banner image now links to the live UI at flo.ruv.io. A new
"Try the UI Beta" badge sits below it for explicit click-through.
The Cloud Run cert is still propagating but DNS resolves; CNAME is
unproxied through Cloudflare so Google can issue the managed cert.
Co-Authored-By: RuFlo <ruv@ruv.net>
---------
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
147a4b0c63 |
fix: comment out empty MODELS/TASK_MODEL placeholders, allow host.docker.internal in URL safety
- Dockerfile: sed-comment empty MODELS= and TASK_MODEL= so .env.local overrides work via dotenv-cli -c - urlSafety: add host.docker.internal to allowed HTTP hostnames for Docker MCP bridge Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
48b70afca3 |
fix: address P0-P2 bugs from ADR-059 triage
P0: Remove obfuscated preinstall script that deleted npm cache (#1261) P1: Fix 13 MCP array schemas missing `items` field (#1294) P1: Fix hooks relative paths — resolve via git rev-parse at runtime (#1259, #1284) P1: Wire AgentDB ControllerRegistry into CLI init (#1264) P2: Update all branding from "Claude Flow" to "RuFlo" (#1253, #1254, #1280) P2: Fix web_search empty query validation in MCP bridge P2: Fix RVF settings duplication via findOneAndUpdate dedup 34 files changed across CLI, MCP bridge, and Chat UI. All tests pass: tsc clean, Docker build clean, conversation isolation verified, MCP health check OK, asset 404s resolved. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
29d52dfc22 |
feat(ruflo): add RuFlo Chat UI with ruvocal fork, MCP bridge, and Docker setup
Adds the complete RuFlo Chat UI system based on a SvelteKit fork (ruvocal) of HuggingFace Chat UI with custom branding, RVF document store replacing MongoDB, MCP bridge with 200+ tools, animated RuFloUniverse welcome screen, and Docker Compose orchestration. Key changes: - RVF JSON document store with ObjectId cross-package compatibility fix - MCP bridge proxy (Express) supporting Gemini, OpenAI, and tool execution - RuFlo branding: Logo, favicons, welcome animation, centered dot cluster - URL safety patch for Docker-internal HTTP service names - CORS fix via relative PUBLIC_ORIGIN asset paths Co-Authored-By: claude-flow <ruv@ruv.net> |