Last updated: 2026-08-08. Branch: main. Working tree: clean.
11 commits are committed locally but NOT pushed (dff21d7..0119b7a).
Ongoing maintenance of Antares (Go backend + React/Vite dashboard in web/).
This session cleared the open PR, added an LLM provider, and fixed a run of
dashboard and Discord/Telegram gateway issues reported by the user. Everything
below is done and green unless called out under Next Steps.
- Toolchain: always build/test with
GOTOOLCHAIN=go1.26.3(the repo needs Go 1.26; httpcloak v1.6.8 forces it). A barego buildmay pick the wrong toolchain. - Dev:
make devruns BOTH the Air-reloaded backend on :8787 and Vite on :5173. Open :5173 — it hot-reloads the frontend and proxies/apito :8787. :8787 serves the embedded React bundle, which Air does NOT rebuild on frontend changes, so it shows a stale UI untilmake build-webruns. Several "the fix didn't work" reports this session were just the user viewing :8787. - Embedded bundle:
make build-webbuildsweb/distand copies it tointernal/server/dist(which is gitignored except.gitkeep— keep that file;make build-webdeletes it, sotouch internal/server/dist/.gitkeepafter). - Run the binary: on macOS use
antares serve --foreground. Cross-compiledCGO_ENABLED=0darwin binaries get an invalid ad-hoc signature and are SIGKILLed (exit 137) on other machines — fix withcodesign --force --sign -. - Tests:
GOTOOLCHAIN=go1.26.3 go test ./...→ 32 packages, all green.
- Merged PR #18 (
dff21d7) + review fixes (5d8406a): edit_file CRLF/line- prefix recovery, vps_run timeouts + new vps_upload/vps_download SFTP tools, persisted context compaction, dashboard session persistence, MCP refresh, composer history, Gemini thoughtSignature. Review fixes I added on top:ANTARES_API_KEY/ANTARES_BASE_URLhad gone silently inert (PR inverted credential precedence); restored env-override viainline*FromEnvflags.POST /api/mcp/refreshnil-panic when MCP unconfigured (typed-nil in interface); guarded.vps_download/vps_uploadcould truncate the destination on a mid-transfer timeout, and download copied the remote file's perm bits (world-writable risk); both now stream to a temp path + rename, download forces 0600.
- OpenCode Go (Zen) provider (
4693848): newkind: opencode. It routes per-model — MiniMax/Qwen → Anthropic/messages+ x-api-key, everything else → OpenAI/chat/completions+ Bearer (seeinternal/llm/opencode.go). Family match is prefix-based. Verified endpoints answer 401 (not 404) live. - Dashboard scroll judder while streaming (
b0b00ac): moved the streaming indicator out of the Virtuoso Footer, memoised components,followOutput={true}, stableinitialTopMostItemIndex. - Transcript OOM crash ("Aw, Snap!") on a tool-heavy turn (
e738c7c): the whole turn is ONE Virtuoso item (list virtualises messages, not segments), and unmemoised segment children made it O(N²) re-render. Fixed by memoisingToolCallCard,ReasoningBlock, newTextSegment. (LCS diff was ruled out by benchmark — write_file takes the cheap empty-old branch.) - Per-tab resumed session (
a16f4bb): the "resume last session" pointer moved fromlocalStorage(shared across tabs) tosessionStorage(per-tab), so two tabs can hold different sessions. Auth token stays in localStorage. - Gateway trio (
7abfb93):reply_mode: "always"now actually works (handleMessagenever read it before); per-user group sessions viaGatewaySessionKey(folds user id into the KV key in groups — thegroup_sessions_per_userflag was defined but never used); newnonetoolset for a tool-free chat turn. - Discord replies (
47ae931): the bot now replies to the triggering message (message_reference) + pings the author, first chunk only. Shared body builderdiscordMessagePayload. - Sender identity to the agent (
f76833e): captures Discord server nickname (member.nick) +global_name; system prompt gets aTalking to: <name> (<platform> user id <id>)line. Fixes the bot saying "I can't see your nick". - Per-user RAG (
0119b7a): opt-inrag.per_user. Each user gets their own RAG collection (rag.UserCollection);indexUserTurnsummarises each turn into durable facts via the aux model and indexes them;autoContextfolds the user's collection in first. Toggle surfaces automatically in the config editor.
- Benchmark before fixing. The OOM's first suspect (LCS diff) was cleared by a quick micro-benchmark — the real cause was O(N²) re-render. Don't fix by hypothesis alone here.
- Reflected config schema. Adding a
yaml-tagged field to a config struct makes it appear in the dashboard config editor automatically (config.Schema()walks the struct). Add the path tocommon/helptables ininternal/config/schema.gofor tier + description; no frontend work. - Small pure helpers + unit tests for the risky gateway logic
(
messageAddressesBot,discordDisplayName,GatewaySessionKey,discordMessagePayload,UserCollection) instead of trying to test the network-touching handlers. - Worktree + subagent to review the large PR #18 without polluting the main tree.
- Disk kept filling (ENOSPC, <500 MiB free) mid-session, which fails Go builds cryptically. The USER frees space themselves — do not delete anything without explicit say-so.
make devrun from inside the agent's tool sandbox gets killed on session teardown and leaves orphanair/viteprocesses that then hold ports 5173/8787. Tell the user to run it in their own terminal.- Viewing :8787 instead of :5173 repeatedly looked like "the fix didn't land". Always confirm which port the user is on.
ResolveBindingskips disabled bindings, so a binding withreply_mode: alwaysbutenabled: falsedoes nothing — the likely real cause of the user's original "always doesn't work". They must enable the binding.- gopls shows stale "undefined" diagnostics from a lowercase-path module alias;
the real
go buildis authoritative, trust it over the editor.
- Push the 11 local commits once the user is ready (they have not asked yet — do NOT push without confirmation).
- Agent loop guardrail (explicitly deferred, user picked "frontend first").
The agent can loop writing the same file with slightly different contents; the
repeat tracker fingerprints name+args so changing content never trips it, and
grContinuelets the 60-call hard stop reset up to 9× (~600 calls). Proposed fix: detect repeatedwrite_file/edit_fileto the SAME path (regardless of content) as a repeat. This is what produced the giant turn that caused the OOM in item 4 — the frontend is now hardened, but the loop itself remains. - Rotate exposed credentials. The Z.ai API key and Voyage embed key were
visible in
~/.antares/config.yamlread during earlier sessions. Still outstanding; user's call. - macOS release signing in
scripts/release-build.sh: darwin release binaries needcodesign --force --sign -or they SIGKILL on other Macs. - Live verification of this session's gateway/RAG work (needs a real Discord
bot + RAG enabled): nickname shows in prompt;
reply_mode: alwayson an ENABLED binding answers un-addressed messages; per-user sessions stay separate; replies thread correctly;rag.per_userpopulatesuser-discord-*collections. - Custom-provider "Add" UI — backend fully supports multiple custom providers; only the dashboard "add" form is missing. Deferred by the user earlier.
internal/llm/opencode.go,internal/llm/client.go— OpenCode provider + kind wiring.internal/gateway/discord.go,telegram.go,binding.go— reply_mode, replies, identity,GatewaySessionKey.internal/agent/ragcontext.go—autoContext,indexTurn,indexUserTurn,summariseUserTurn.internal/rag/user.go—UserCollection.internal/config/config.go,schema.go,load.go—rag.per_user, inline-cred env flags, reflected schema.internal/tools/registry.go—nonetoolset.web/src/pages/ChatPage.tsx— streaming indicator, memoised segments, per-tab session.web/src/components/chat/ToolCallCard.tsx— memoised.