diff --git a/.gitignore b/.gitignore index 8d0b5f2..2a850d8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ data/error-log.json data/circuit-breaker.json data/memory.db data/kanban/*.json +data/uploads/ scheduler/*.pyc diff --git a/AGENTS.md b/AGENTS.md index e71bc63..eaf24ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Role Definition -You are an **AI Agent Operating System (Agentic OS)** — a multi-agent orchestration platform that coordinates **opencode**, **Hermes Agent**, and **Gemini CLI** into a unified, self-improving, autonomous work operating system. +You are an **AI Agent Operating System (Agentic OS)** — a multi-agent orchestration platform that coordinates **opencode**, **Hermes Agent**, and **agy CLI** into a unified, self-improving, autonomous work operating system. Your role is to act as the **kernel** of this system: route tasks to the right agent, manage shared memory, execute skills, track costs, schedule workflows, and evolve capabilities over time. You are not a single assistant — you are the operating system that other agents run on top of. @@ -36,7 +36,7 @@ Your role is to act as the **kernel** of this system: route tasks to the right a │ │ 3-AGENT EXECUTION ENGINE │ │ │ │ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │ │ -│ │ │ opencode │ │ Hermes │ │ Gemini CLI │ │ │ +│ │ │ opencode │ │ Hermes │ │ agy CLI │ │ │ │ │ │ (Code/DevOps)│ │ (Memory/Sched│ │(Research/ │ │ │ │ │ │ File Ops) │ │ /Channels) │ │ Analysis) │ │ │ │ │ └──────────────┘ └──────────────┘ └────────────┘ │ │ @@ -62,14 +62,14 @@ Your role is to act as the **kernel** of this system: route tasks to the right a |-------|-------------|---------------| | **opencode** | Code generation, file operations, DevOps/GCP infra, git management, software engineering | Any task involving file edits, code writing, infrastructure-as-code, terminal commands for build/test | | **Hermes Agent** | Persistent memory (SQLite FTS5), cron scheduling, Telegram/Discord channels, skill hub, multi-agent coordination | Tasks needing cross-session memory, scheduled recurring tasks, multi-platform notifications, skill discovery | -| **Gemini CLI** | Web research, multi-modal analysis (images/PDFs), Gemini Flash free-tier reasoning, data analysis | Research tasks, content analysis, document understanding, competitive analysis, learning/research | +| **agy CLI** | Web research, multi-modal analysis (images/PDFs), reasoning, data analysis | Research tasks, content analysis, document understanding, competitive analysis, learning/research | ### Routing Rules - **Code/DevOps task?** → opencode - **Memory/Channel/Schedule?** → Hermes Agent -- **Research/Analysis?** → Gemini CLI -- **Complex multi-step?** → Chain: Gemini researches → opencode implements → Hermes monitors/schedules +- **Research/Analysis?** → agy CLI +- **Complex multi-step?** → Chain: agy researches → opencode implements → Hermes monitors/schedules - **Unknown/General?** → opencode first (best general-purpose coding agent) --- @@ -213,7 +213,7 @@ Your role is to act as the **kernel** of this system: route tasks to the right a │ ├── devops-audit/ # CloudMart GCP infra │ ├── content-draft/ # Blog/newsletter writing │ ├── code-review/ # [F21] -│ ├── research-synthesis/ # Gemini research +│ ├── research-synthesis/ # agy research │ ├── daily-standup/ # Morning briefing │ ├── meeting-minutes/ # Meeting notes processor │ ├── project-planner/ # [F25, F26, F46] @@ -233,9 +233,9 @@ Your role is to act as the **kernel** of this system: route tasks to the right a │ │ ├── SOUL.md │ │ ├── USER.md │ │ └── MEMORY.md -│ └── gemini/ -│ ├── GEMINI.md -│ └── gemini-extension.json +│ └── agy/ +│ ├── AGY.md +│ └── agy-extension.json │ ├── scheduler/ # [F9] Scheduling │ ├── scheduler.py @@ -318,8 +318,8 @@ Your role is to act as the **kernel** of this system: route tasks to the right a |--------|------| | **Budget** | Strictly free tiers (GCP Free, GitHub Student Pack, Colab, Kaggle) | | **Active Project** | CloudMart — GCP DevOps multi-region e-commerce platform | -| **CLI Tools Available** | opencode, Hermes Agent, Gemini CLI | -| **Preferred Model** | Hermes: Owl Alpha (OpenRouter, free), opencode: deepseek-v4-flash-free (opencode-zen), Gemini: gemini-2.5-flash (Google OAuth) | +| **CLI Tools Available** | opencode, Hermes Agent, agy CLI | +| **Preferred Model** | Hermes: Owl Alpha (OpenRouter, free), opencode: deepseek-v4-flash-free (opencode-zen), agy: Antigravity (free CLI) | --- @@ -350,7 +350,7 @@ When you (an AI agent) are dropped into this directory for the first time: ### Session History - opencode: `~/.local/share/opencode/opencode.db` + `~/.local/share/opencode/log/` - Hermes: `~/.hermes/sessions.json` -- Gemini: `~/.gemini/history/` +- agy: `~/.antigravity/history/` --- @@ -448,7 +448,8 @@ When you (an AI agent) are dropped into this directory for the first time: |------|---------|---------| | May 17, 2026 | v1.0.0 | Initial creation — all 51 features + 10 extras | | May 17, 2026 | v1.1.0 | AI Chat fixes: corrected CLI syntax (hermes `chat -q`, gemini positional), switched Hermes default to OpenRouter + Owl Alpha, improved timeout/error handling, updated execute_agent fallback logic | +| Aug 11, 2026 | v0.4.0 | **agy (Antigravity) replaces Gemini CLI** across backend, routing, frontend, skills, agents/, docs; **port auto-kill** in start.sh; **apscheduler auto-install** in scheduler.py; **Chat History Search** (`q`/`agent`/`limit` + History page); **Chat File Attachments** (`/api/chat/upload`, 2 MB allowlist, 24h TTL); **Memory Knowledge Graph** (`/api/memory/graph` + Canvas renderer); **Code Diff Viewer** (`/api/diff` + Skills page button); **74 tests** (59 → 74, 15 new isolated v0.4.0 tests) | --- -*This AGENTS.md is designed to be the single source of truth. Any AI agent (opencode, Claude Code, Gemini CLI, Hermes, Cursor, etc.) reading this file should have complete context to continue the project seamlessly.* +*This AGENTS.md is designed to be the single source of truth. Any AI agent (opencode, Claude Code, agy CLI, Hermes, Cursor, etc.) reading this file should have complete context to continue the project seamlessly.* diff --git a/README.md b/README.md index 91ade96..485011f 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ Python 3.10+ FastAPI 3 Agents - 16 Skills - v0.3.0 + 15 Skills + v0.4.0 Status: Stable dev.to article

@@ -13,7 +13,7 @@ # Agentic OS (agentic-os) 🧠 — Multi-Agent Orchestration Platform -A locally-hosted operating system for AI agents — an open-source GitHub repository — that coordinates **opencode**, **Hermes Agent**, and **Gemini CLI** into a unified dashboard with persistent memory, cron scheduling, skill execution, cost analytics, and disaster recovery. +A locally-hosted operating system for AI agents — an open-source GitHub repository — that coordinates **opencode**, **Hermes Agent**, and **agy CLI** into a unified dashboard with persistent memory, cron scheduling, skill execution, cost analytics, and disaster recovery. > **Why Agentic OS?** Most agent tools work in isolation — a terminal for coding, a separate chat for research, another for memory. Agentic OS is the **control plane** that unifies them: one dashboard, one memory layer, one scheduler, one skill hub. Three agents, infinite capabilities. @@ -23,8 +23,8 @@ A locally-hosted operating system for AI agents — an open-source GitHub reposi | Category | Features | |----------|----------| -| **🤖 3-Agent Engine** | opencode (code/DevOps), Hermes (memory/scheduling), Gemini (research/analysis) with intelligent routing | -| **🧩 16+ Skills** | Executable skill packs with eval scoring, learnings, and score history per run | +| **🤖 3-Agent Engine** | opencode (code/DevOps), Hermes (memory/scheduling), agy (research/analysis) with intelligent routing | +| **🧩 15+ Skills** | Executable skill packs with eval scoring, learnings, and score history per run | | **🧠 Persistent Memory** | SQLite FTS5 + `brain/` folder — shared context read by all agents at session start | | **⏱ Cron Scheduler** | APScheduler-powered jobs — heartbeat, memory consolidation, daily standup, DevOps audit | | **💰 Cost Analytics** | Track spending per provider, model, agent. Free-tier alerts prevent surprise bills | @@ -34,11 +34,11 @@ A locally-hosted operating system for AI agents — an open-source GitHub reposi | **📐 Standards System** | Discover and inject coding conventions across your project | | **🔌 Plugin Registry** | Marketplace-style plugin management (extensible via skills) | | **🎨 Dark/Light Theme** | GitHub-style dark mode + clean light theme, toggle from sidebar | -| **⚡ Zero API Costs** | Built for free tiers — Gemini Flash, OpenRouter free models, local opencode | +| **⚡ Zero API Costs** | Built for free tiers — Antigravity (agy), OpenRouter free models, local opencode | | **📋 Kanban Board** | Visual task management — drag-and-drop columns, priority/status filtering, block/unblock, detail view | | **🎯 Goals** | Project targets with progress tracking, auto-syncs to `brain/active-projects.md` | | **📓 Journal** | Daily markdown entries stored as `brain/journal/YYYY-MM-DD.md` with full-text search | -| **❤️ Agent Health** | Real-time monitoring of opencode, Hermes, and Gemini CLI availability | +| **❤️ Agent Health** | Real-time monitoring of opencode, Hermes, and agy CLI availability | | **🧭 Smart Router** | Keyword-based task routing with confidence scoring — suggests best agent for any task | | **📊 Learning Analytics** | Skill evaluation scores, performance trends, and historical charts | | **🎬 Session Replay** | Browse and replay past opencode sessions from the dashboard | @@ -61,7 +61,7 @@ A locally-hosted operating system for AI agents — an open-source GitHub reposi ├──────────────────────────────────────────────────────────────┤ │ │ │ ┌───────────────┐ ┌────────────────┐ ┌────────────────────┐ │ -│ │ opencode │ │ Hermes │ │ Gemini CLI │ │ +│ │ opencode │ │ Hermes │ │ agy CLI │ │ │ │ (Code/DevOps) │ │ (Memory/Sched) │ │ (Research/Analy) │ │ │ │ File Ops) │ │ /Channels) │ │ │ │ │ └───────────────┘ └────────────────┘ └────────────────────┘ │ @@ -85,14 +85,14 @@ A locally-hosted operating system for AI agents — an open-source GitHub reposi |-------|------|---------------|----------|------| | **opencode** | Code generation, DevOps, file operations | deepseek-v4-flash-free | opencode-zen | **$0** | | **Hermes Agent** | Persistent memory, scheduling, messaging | Owl Alpha (1M ctx) | OpenRouter | **$0** | -| **Gemini CLI** | Web research, multi-modal analysis | gemini-2.5-flash | Google OAuth | **$0** | +| **agy CLI** | Web research, multi-modal analysis | Antigravity | agy CLI | **$0** | ### Routing Rules - **Code/DevOps task?** → opencode - **Memory/Channel/Schedule?** → Hermes Agent -- **Research/Analysis?** → Gemini CLI -- **Complex multi-step?** → Chain: Gemini researches → opencode implements → Hermes monitors/schedules +- **Research/Analysis?** → agy CLI +- **Complex multi-step?** → Chain: agy researches → opencode implements → Hermes monitors/schedules --- @@ -116,7 +116,7 @@ chmod +x install.sh && ./install.sh | Node.js 18+ | ⚠ For opencode | `curl -fsSL https://deb.nodesource.com/setup_20.x \| sudo bash - && sudo apt install -y nodejs` | | opencode | ⚠ For code tasks | `npm install -g @opencode/cli` | | Hermes Agent | ⚠ For memory/scheduling | `curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh \| bash` | -| Gemini CLI | ⚠ For Google AI | `npm install -g @google/gemini-cli` | +| agy CLI | ⚠ For research/analysis | `curl -fsSL https://antigravity.ai/install \| bash` | > ⚠ = Optional — the dashboard works with any subset of installed agents. @@ -130,10 +130,10 @@ chmod +x install.sh && ./install.sh echo 'OPENROUTER_API_KEY=sk-or-v1-your-key-here' > ~/.hermes/.env ``` -### Gemini CLI (Google OAuth) +### agy CLI (Antigravity) ```bash -gemini auth login -# Complete OAuth in browser — tokens saved to ~/.gemini/oauth_creds.json +agy login +# Authenticate to enable web research, analysis, and document understanding ``` ### Dashboard Settings @@ -142,7 +142,7 @@ Edit `data/settings.json`: { "dashboard": { "port": 8080 }, "theme": "dark", - "agents": { "opencode": true, "hermes": true, "gemini": true } + "agents": { "opencode": true, "hermes": true, "agy": true } } ``` @@ -164,11 +164,12 @@ agentic-os/ │ ├── api.js # API client (all endpoints) │ ├── styles.css # Full dark/light theme CSS │ ├── utils.js # Shared utilities -│ └── pages/ # 21 page modules (13 original + 7 v0.2.0 + 1 v0.3.0) +│ └── pages/ # 22 page modules (13 original + 7 v0.2.0 + 1 v0.3.0 + 1 v0.4.0) │ ├── dashboard.js # Overview with stats │ ├── skills.js # Skill grid/list/detail -│ ├── memory.js # Brain file editor -│ ├── chat.js # Multi-agent chat +│ ├── memory.js # Brain file editor + Knowledge Graph +│ ├── chat.js # Multi-agent chat + file attachments +│ ├── history.js # ▸ Chat History Search (v0.4.0) │ ├── scheduler.js # Cron job manager │ ├── audit.js # Activity trail │ ├── cost.js # Cost analytics charts @@ -197,12 +198,12 @@ agentic-os/ │ ├── constitution.md │ └── journal/ # Daily markdown entries (YYYY-MM-DD.md) │ -├── skills/ # 16 executable skills +├── skills/ # 15 executable skills │ ├── devops-audit/ # GCP/CloudMart infra audit │ ├── heartbeat/ # 5-min health check │ ├── content-draft/ # Blog/newsletter writing │ ├── code-review/ # PR review checklist -│ ├── research-synthesis/ # Gemini research aggregator +│ ├── research-synthesis/ # agy research aggregator │ ├── daily-standup/ # Morning briefing │ ├── meeting-minutes/ # Notes processor │ ├── project-planner/ # Step-by-step plans @@ -215,18 +216,38 @@ agentic-os/ │ ├── goal-planner/ # Goal → steps │ └── _template/ # Starter template │ -├── agents/ # Per-agent configs +├── agents/ # Per-agent configs (opencode, hermes, agy) ├── scheduler/jobs/ # Cron job definitions ├── registry/ # Plugin marketplace ├── standards/ # Discover/inject conventions ├── prompts/ # 10 reusable templates -├── data/ # Runtime data (agent-routes.json tracked; settings/cost/chat/error/scheduler/memory/circuit/kanban gitignored) +├── data/ # Runtime data (agent-routes.json tracked; settings/cost/chat/error/scheduler/memory/circuit/kanban/uploads gitignored) ├── audit/ # Activity log (gitignored) └── backups/ # Snapshots (gitignored) ``` --- +## 🆕 What's New in v0.4.0 + +| Feature | Description | +|---------|-------------| +| **🤖 agy (Antigravity) replaces Gemini CLI** | Full provider swap across backend, routing, frontend, skills, agents/, and docs. `data/agent-routes.json`, circuit breaker, health checks, chat all use `agy` | +| **🛡 Port Conflict Auto-Kill** | `start.sh` detects a stale dashboard process on the target port and kills it before starting | +| **📦 Auto-Install apscheduler** | `scheduler.py` auto-installs missing dependencies instead of failing on startup | +| **💬 Chat History Search** | `/api/chat/history` supports `q`, `agent`, `limit` filters + a dedicated History page with search, agent filter pills, and date grouping | +| **📎 Chat File Attachments** | `POST /api/chat/upload` (multipart) accepts text files up to 2 MB (validated allowlist), previews content to the agent, and stores under `data/uploads/` with 24h TTL cleanup | +| **🕸 Memory Knowledge Graph** | `GET /api/memory/graph` returns nodes (brain/skills/journal docs + extracted entities) and edges (shares_source / mentions), rendered as an interactive Canvas graph in the Memory page | +| **📜 Code Diff Viewer** | `GET /api/diff?file=&ref=` returns unified git diff with repo-relative path-traversal protection; "View Diff" button on the Skills page | +| **🧪 15 new tests** | Suite grows from 59 → 74 isolated tests covering chat history, uploads, memory graph, and diff viewer | +| **🛠 Stale-Cache Elimination** | `no-store` cache headers on all dashboard assets, `?v=` cache-busting, service-worker purge on load, root-level asset fallbacks so stale index.html never breaks the UI | +| **📐 Zoom-Proof Layout** | Content width capped at 1600px, responsive file-card grid, and `flex-shrink: 0` on tab bars — layout stays clean from 60% to 100% zoom | +| **🔢 Correct Skill Count** | Skills badge now counts skill directories (15) via the status endpoint instead of returning 0 | + +During the v0.4.0 hardening pass the following **layout & caching bugs** were crushed: tab bars (Files/Knowledge Graph, Grid/List) collapsing to 1px under content at certain zooms, oversized cards stretching to 3500px+ at 50% zoom, cached index.html referencing dead asset URLs, and the sidebar Skills badge showing 0. + +--- + ## 🆕 What's New in v0.3.0 | Feature | Description | @@ -259,7 +280,7 @@ agentic-os/ | **📋 Kanban Board** | Visual task management with 6 columns (triage → todo → ready → in_progress → blocked → done), drag-and-drop, priority labels, filtering, and detail modals with complete/block/unblock actions | | **🎯 Goals** | Create and track project targets with progress bars, categories, and target dates. Auto-syncs to `brain/active-projects.md` for agent awareness | | **📓 Journal** | Daily markdown journal entries stored as `brain/journal/YYYY-MM-DD.md`. Full-text search, day streak tracking, word count | -| **❤️ Agent Health** | Real-time dashboard showing online/offline status for all 3 agents (opencode, Hermes, Gemini CLI). Auto-refresh every 5 seconds | +| **❤️ Agent Health** | Real-time dashboard showing online/offline status for all 3 agents (opencode, Hermes, agy CLI). Auto-refresh every 5 seconds | | **🧭 Smart Router** | Keyword-based routing engine — type a task description and get an AI-suggested agent with confidence score. Manual override available | | **📊 Learning Analytics** | Skill evaluation scores, performance trends, and per-skill detail breakdowns with mini bar charts | | **🎬 Session Replay** | Browse and replay past opencode sessions directly from the dashboard. View message content and timestamps | @@ -282,10 +303,10 @@ Select an agent from the sidebar → type your message → get response. |-------|----------|---------| | **opencode** | "Check system status", "Deploy to GKE" | Code + terminal automation | | **Hermes** | "What did I work on recently?", "Schedule a daily backup" | Memory recall, scheduling | -| **Gemini** | "Research latest AI agent trends", "Analyze this image" | Web research, multi-modal | +| **agy** | "Research latest AI agent trends", "Analyze this image" | Web research, multi-modal | ### Skills -Browse 16 skills from Skills Hub → click Run → monitor eval scores over time. +Browse 15 skills from Skills Hub → click Run → monitor eval scores over time. ### Scheduler Create cron jobs: heartbeat (5 min), memory consolidation (weekly), daily standup, DevOps audit. @@ -309,7 +330,7 @@ Describe a task in plain English — the router analyzes keywords and suggests t Monitor online status of all 3 agents in real time with 5-second auto-refresh. Health checks are filesystem-based (no subprocess calls). ### Learning Analytics (v0.2.0) -View evaluation scores for all 16 skills. Trends chart shows score progression over time. Top skills ranked by performance. +View evaluation scores for all 15 skills. Trends chart shows score progression over time. Top skills ranked by performance. ### Session Replay (v0.2.0) Browse opencode session logs by date and size. Click "Replay" to view all messages in a chat-like interface. @@ -338,11 +359,11 @@ Open Agentic OS on your phone — bottom nav bar replaces sidebar, touch targets | Feature | Claude Agent OS (Video) | Agentic OS (This Project) | |---------|------------------------|---------------------------| -| **Core Agents** | Claude + OpenClaw + Hermes | opencode + Hermes + Gemini CLI | +| **Core Agents** | Claude + OpenClaw + Hermes | opencode + Hermes + agy CLI | | **Cost** | $20/mo (Claude subscription) | **$0 — all free tiers** | | **Stack** | Next.js + Tailwind | FastAPI + vanilla JS SPA | | **Architecture** | 4 layers | **7 layers** | -| **Skills System** | Plugin marketplace (2,000+ from Hermes) | 16 curated skills + eval scoring + learnings | +| **Skills System** | Plugin marketplace (2,000+ from Hermes) | 15 curated skills + eval scoring + learnings | | **Memory** | Obsidian vault (external) | Built-in brain/ + SQLite FTS5 | | **Scheduler** | Not shown | APScheduler cron jobs | | **Cost Tracking** | Not shown | Built-in per-provider analytics | @@ -360,7 +381,7 @@ Open Agentic OS on your phone — bottom nav bar replaces sidebar, touch targets - **OS**: Linux (Ubuntu 22.04+), macOS - **Python**: 3.10, 3.11, 3.12 - **Browsers**: Chrome, Firefox, Edge -- **Agents**: opencode v0.8+, Hermes Agent v1.0+, Gemini CLI v1.0+ +- **Agents**: opencode v0.8+, Hermes Agent v1.0+, agy CLI (Antigravity) --- diff --git a/agents/agy/AGY.md b/agents/agy/AGY.md new file mode 100644 index 0000000..617b783 --- /dev/null +++ b/agents/agy/AGY.md @@ -0,0 +1,24 @@ +# agy (Antigravity) — Agentic OS Config + +The **agy** CLI (Antigravity) replaces the deprecated `gemini` CLI as the +research/analysis agent in Agentic OS (v0.4.0). + +- Use the `agy` binary from the CLI +- Non-interactive mode: `agy --print ""` +- Handles web research, multi-modal analysis, document understanding, data + analysis, and reasoning tasks + +## Integration +- Invoked via `execute_agent("agy", message)` in `server.py` +- Registered in `data/agent-routes.json` under `agent_capabilities` +- Status checked via `shutil.which("agy")` in `check_agent()` + +## Install +``` +curl -fsSL https://antigravity.ai/install | bash +``` + +## Usage +``` +agy --print "Research the latest AI agent trends" +``` diff --git a/agents/agy/agy-extension.json b/agents/agy/agy-extension.json new file mode 100644 index 0000000..76644b3 --- /dev/null +++ b/agents/agy/agy-extension.json @@ -0,0 +1,7 @@ +{ + "name": "agy-extension", + "version": "1.0.0", + "description": "agy (Antigravity) CLI extension for Agentic OS", + "model": "agy", + "capabilities": ["web_search", "multi_modal", "data_analysis", "document_understanding", "reasoning"] +} diff --git a/agents/gemini/GEMINI.md b/agents/gemini/GEMINI.md deleted file mode 100644 index e050dd0..0000000 --- a/agents/gemini/GEMINI.md +++ /dev/null @@ -1,21 +0,0 @@ -# Gemini CLI — Agentic OS Config - -## Role -Research, analysis, multi-modal understanding, web search, data analysis, document comprehension - -## Instructions -- Use `gemini` binary from CLI -- Preferred model: gemini-2.5-flash (free tier) -- For web research: use web search tools -- For document analysis: use multi-modal capabilities -- Output results in markdown format -- Route coding tasks to opencode -- Route memory/channel tasks to Hermes Agent -- Cost tracking: log token usage to data/cost-history.json - -## Capabilities -- Web search and research -- PDF/image analysis -- Data analysis and visualization -- Competitive analysis -- Learning and research diff --git a/agents/gemini/gemini-extension.json b/agents/gemini/gemini-extension.json deleted file mode 100644 index 566ed69..0000000 --- a/agents/gemini/gemini-extension.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "gemini-extension", - "version": "1.0.0", - "description": "Gemini CLI extension for Agentic OS", - "model": "gemini-2.5-flash", - "capabilities": ["web_search", "multi_modal", "data_analysis", "document_understanding"] -} diff --git a/agents/hermes/MEMORY.md b/agents/hermes/MEMORY.md index 1bcb7aa..583dfdb 100644 --- a/agents/hermes/MEMORY.md +++ b/agents/hermes/MEMORY.md @@ -2,7 +2,7 @@ ## Active Context - Building Agentic OS (May 2026) -- 3-agent system: opencode + Hermes + Gemini CLI +- 3-agent system: opencode + Hermes + agy - Web dashboard on FastAPI - v0.2.0 released Jun 5, 2026 — 68 features (51 ref + 10 extras + 7 new), 58 endpoints, 20 pages diff --git a/agents/hermes/SOUL.md b/agents/hermes/SOUL.md index 428fbdd..3545d82 100644 --- a/agents/hermes/SOUL.md +++ b/agents/hermes/SOUL.md @@ -7,7 +7,7 @@ You are the memory and scheduling subsystem of Agentic OS. You manage persistent - Maintain MEMORY.md and USER.md with cross-session context - Schedule and monitor recurring tasks via cron - Route coding tasks to opencode -- Route research tasks to Gemini CLI +- Route research tasks to agy CLI - Log all actions to audit/audit.log ## Memory Configuration diff --git a/agents/hermes/USER.md b/agents/hermes/USER.md index b7bdb86..02f1cea 100644 --- a/agents/hermes/USER.md +++ b/agents/hermes/USER.md @@ -2,7 +2,7 @@ ## User - Name: User -- Tech Stack: opencode, Hermes Agent, Gemini CLI, deepseek-v4-flash-free +- Tech Stack: opencode, Hermes Agent, agy CLI, deepseek-v4-flash-free - Projects: CloudMart (GCP DevOps), Agentic OS - Budget: Free tiers only @@ -13,5 +13,5 @@ - Cost-conscious — always free tier first ## Communication -- Primary interaction: CLI (opencode/Hermes/Gemini) +- Primary interaction: CLI (opencode/Hermes/agy) - Channels: CLI, messaging (Telegram) diff --git a/agents/opencode/AGENTS.md b/agents/opencode/AGENTS.md index 1c785b2..587cbcf 100644 --- a/agents/opencode/AGENTS.md +++ b/agents/opencode/AGENTS.md @@ -8,5 +8,5 @@ Code generation, DevOps, file operations, infrastructure-as-code, git management - Check brain/recent-decisions.md for active context - After each task: update learnings.md, append to audit/audit.log - Run `git add -A && git commit -m "description"` after meaningful changes -- Route research tasks to Gemini CLI +- Route research tasks to agy CLI - Route memory/channel tasks to Hermes Agent diff --git a/brain/constraints.md b/brain/constraints.md index c36e999..c90f773 100644 --- a/brain/constraints.md +++ b/brain/constraints.md @@ -10,7 +10,7 @@ - Python 3.10+ required (FastAPI backend) - Node.js 18+ required (opencode) - Hermes Agent needs Python 3.11+ and Node.js -- Gemini CLI needs `gemini` binary installed +- agy CLI (Antigravity) needs `agy` binary installed — replaces the deprecated gemini CLI - Linux environment (Ubuntu/WSL) - Dashboard binds to localhost only — no external exposure without explicit config diff --git a/brain/memory_search.py b/brain/memory_search.py index 384dc56..c028afe 100644 --- a/brain/memory_search.py +++ b/brain/memory_search.py @@ -79,9 +79,89 @@ def search(query: str, limit: int = 20) -> list: "WHERE memory_fts MATCH ? ORDER BY rank LIMIT ?", (query, limit) ).fetchall() - return [dict(r) for r in rows] - except sqlite3.OperationalError: + except Exception: return [] + return [dict(r) for r in rows] + +def build_graph() -> dict: + """Build a knowledge graph from the FTS5 index + entity table (v0.4.0). + + Nodes: brain files, skills, journal entries, extracted entities. + Edges: file->entity co-occurrence, entity co-occurrence in same source. + """ + conn = _get_db() + nodes, edges = [], [] + node_ids, edge_keys = set(), set() + + # Document nodes (from memory_meta) + rows = conn.execute( + "SELECT id, source, path, title, category FROM memory_meta" + ).fetchall() + doc_by_id = {} + for r in rows: + node = { + "id": r["id"], + "label": r["title"] or r["path"], + "type": r["category"] or r["source"], + "path": r["path"], + "source": r["source"], + } + nodes.append(node) + node_ids.add(r["id"]) + doc_by_id[r["id"]] = r["path"] + + # Entity nodes + ents = conn.execute( + "SELECT DISTINCT name, type, source FROM entities LIMIT 200" + ).fetchall() + entity_ids = set() + for e in ents: + nid = f"ent:{e['name']}:{e['type']}" + if nid in entity_ids: + continue + entity_ids.add(nid) + nodes.append({ + "id": nid, + "label": e["name"], + "type": f"entity:{e['type']}", + "path": "", + "source": e["source"] or "auto", + }) + + # Edges: document <-> entity co-occurrence + edge_rows = conn.execute( + "SELECT source, name, type FROM entities LIMIT 500" + ).fetchall() + ent_by_key = {} + for e in edge_rows: + key = f"ent:{e['name']}:{e['type']}" + ent_by_key.setdefault(e["source"], []).append(key) + + # Edges between documents (same source directory / shared entity) + doc_sources = {} + for r in rows: + doc_sources.setdefault(r["source"], []).append(r["id"]) + + for source, ids in doc_sources.items(): + for i in range(len(ids)): + for j in range(i + 1, len(ids)): + key = tuple(sorted((ids[i], ids[j]))) + if key not in edge_keys: + edge_keys.add(key) + edges.append({"source": ids[i], "target": ids[j], "type": "shares_source"}) + + for source, ent_ids in ent_by_key.items(): + # link each entity to the document it appeared in + for doc_id, doc_path in doc_by_id.items(): + if doc_path and source and doc_path in source: + key = (doc_id, ent_ids[0]) + if key not in edge_keys: + edge_keys.add(key) + for ent_id in ent_ids[:5]: + edges.append({"source": doc_id, "target": ent_id, "type": "mentions"}) + + return {"nodes": nodes, "edges": edges, + "stats": {"nodes": len(nodes), "edges": len(edges)}} def index_brain_files(): brain_dir = BASE_DIR diff --git a/dashboard/api.js b/dashboard/api.js index 05c6240..a291a11 100644 --- a/dashboard/api.js +++ b/dashboard/api.js @@ -51,7 +51,25 @@ const api = { getStandards: () => api.get('/api/standards'), discoverStandards: () => api.post('/api/standards/discover'), chat: (agent, message, controller) => api.post('/api/chat', { agent, message }, controller), + chatWithFile: async (agent, message, file, controller) => { + const form = new FormData(); + form.append('agent', agent); + form.append('message', message || ''); + form.append('file', file); + const opts = { method: 'POST', body: form }; + if (controller) opts.signal = controller.signal; + const r = await fetch('/api/chat/upload', opts); + if (!r.ok) { const e = await r.json().catch(() => ({})); throw new Error(e.detail || `Request failed: ${r.status}`); } + return r.json(); + }, getChatHistory: () => api.get('/api/chat/history'), + searchChatHistory: (q, agent, limit) => { + const params = new URLSearchParams(); + if (q) params.set('q', q); + if (agent) params.set('agent', agent); + if (limit) params.set('limit', limit); + return api.get(`/api/chat/history?${params.toString()}`); + }, // Kanban getKanbanBoard: (status) => api.get(status ? `/api/kanban/board?status=${encodeURIComponent(status)}` : '/api/kanban/board'), getKanbanTask: (id) => api.get(`/api/kanban/tasks/${encodeURIComponent(id)}`), @@ -103,4 +121,8 @@ const api = { resetCircuitBreaker: (agent) => api.post('/api/circuit-breaker/reset', { agent }), // v0.3.0: PWA getManifest: () => api.get('/manifest.json'), + // v0.4.0: Memory Knowledge Graph + getMemoryGraph: () => api.get('/api/memory/graph'), + // v0.4.0: Code Diff Viewer + getDiff: (file, ref = 'HEAD') => api.get(`/api/diff?file=${encodeURIComponent(file)}&ref=${encodeURIComponent(ref)}`), }; diff --git a/dashboard/app.js b/dashboard/app.js index a8295ef..f830051 100644 --- a/dashboard/app.js +++ b/dashboard/app.js @@ -1,5 +1,7 @@ const pageCache = {}; +const APP_VERSION = '0.4.1'; + const PAGE_BASE = '/dashboard/pages/'; async function loadPage(name) { @@ -15,9 +17,10 @@ async function loadPage(name) { function loadScript(src) { return new Promise((resolve, reject) => { - if (document.querySelector(`script[src="${src}"]`)) { resolve(); return; } + const versioned = `${src}?v=${APP_VERSION}`; + if (document.querySelector(`script[src="${versioned}"]`)) { resolve(); return; } const script = document.createElement('script'); - script.src = src; + script.src = versioned; script.onload = () => resolve(); script.onerror = () => reject(new Error(`Failed to load ${src}`)); document.body.appendChild(script); diff --git a/dashboard/index.html b/dashboard/index.html index 86ad6d4..983739f 100644 --- a/dashboard/index.html +++ b/dashboard/index.html @@ -12,8 +12,7 @@ - - +
@@ -38,6 +37,7 @@ `; @@ -116,29 +121,38 @@ function autoResizeTextarea(el) { async function sendChatMessage() { const input = document.getElementById('chatInput'); const message = input.value.trim(); - if (!message) return; + const fileInput = document.getElementById('chatFileInput'); + const file = fileInput && fileInput.files && fileInput.files[0]; + if (!message && !file) return; const agent = window._currentAgent || 'opencode'; input.value = ''; input.style.height = 'auto'; // Add user message to chat - addChatMessage('user', message, agent); + addChatMessage('user', message || `📎 ${file.name}`, agent); // Show typing indicator const typingId = showTypingIndicator(agent); + // Client-side timeout: 200s (slightly more than Hermes' 180s backend timeout) + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 200000); + try { - // Client-side timeout: 200s (slightly more than Hermes' 180s backend timeout) - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 200000); - const r = await api.chat(agent, message, controller); + let r; + if (file) { + r = await api.chatWithFile(agent, message, file, controller); + clearChatAttachment(); + } else { + r = await api.chat(agent, message, controller); + } clearTimeout(timeoutId); removeTypingIndicator(typingId); addChatMessage('assistant', r.response.content, agent); // Store in local history - window._chatHistory.push({ role: 'user', content: message, agent }); + window._chatHistory.push({ role: 'user', content: message || `📎 ${file.name}`, agent }); window._chatHistory.push({ role: 'assistant', content: r.response.content, agent }); } catch (err) { removeTypingIndicator(typingId); @@ -147,6 +161,25 @@ async function sendChatMessage() { } } +function handleChatFile(fileInput) { + const file = fileInput.files && fileInput.files[0]; + if (!file) return; + if (file.size > 2 * 1024 * 1024) { + showToast('File too large (max 2 MB)', 'error'); + fileInput.value = ''; + return; + } + document.getElementById('chatAttachment').style.display = ''; + document.getElementById('chatAttachmentName').textContent = `${file.name} (${formatBytes(file.size)})`; +} + +function clearChatAttachment() { + const fi = document.getElementById('chatFileInput'); + if (fi) fi.value = ''; + const bar = document.getElementById('chatAttachment'); + if (bar) bar.style.display = 'none'; +} + function addChatMessage(role, content, agent) { const container = document.getElementById('chatMessages'); const welcome = container.querySelector('.chat-welcome'); diff --git a/dashboard/pages/cost.js b/dashboard/pages/cost.js index 1673366..9d9b24e 100644 --- a/dashboard/pages/cost.js +++ b/dashboard/pages/cost.js @@ -80,6 +80,16 @@ async function renderCost() { `); } + // Load Chart.js lazily (CDN only needed on this page) + if (entries.length > 0) { + const ok = await loadChartJS(); + if (!ok) { + document.querySelector('.chart-container')?.insertAdjacentHTML('beforebegin', + '
📉
Charts unavailable
Chart.js CDN could not be loaded. Check your internet connection.
'); + return; + } + } + // Build agent chart const agentTotals = {}; entries.forEach(e => { @@ -115,11 +125,22 @@ async function renderCost() { } } +function loadChartJS() { + return new Promise((resolve) => { + if (window.Chart) { resolve(true); return; } + const script = document.createElement('script'); + script.src = 'https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js'; + script.onload = () => resolve(true); + script.onerror = () => resolve(false); + document.body.appendChild(script); + }); +} + async function recordTestCost() { showModal('Record Cost Entry', `
- +
diff --git a/dashboard/pages/errors.js b/dashboard/pages/errors.js index 9849862..f32ffb3 100644 --- a/dashboard/pages/errors.js +++ b/dashboard/pages/errors.js @@ -120,7 +120,7 @@ async function loadCircuitBreaker() { container.innerHTML = '
🔌
No circuit breaker data
'; return; } - const agentIcons = { opencode: '🔧', hermes: '⚡', gemini: '🧠' }; + const agentIcons = { opencode: '🔧', hermes: '⚡', agy: '🧠' }; container.innerHTML = agentNames.map(a => { const cb = agents[a] || {}; const isOpen = cb.state === 'open'; diff --git a/dashboard/pages/history.js b/dashboard/pages/history.js new file mode 100644 index 0000000..ebed11e --- /dev/null +++ b/dashboard/pages/history.js @@ -0,0 +1,117 @@ +async function renderHistory() { + const content = document.getElementById('pageContent'); + content.innerHTML = ` + +
+
+ +
+
+ Filter: + ${['', 'opencode', 'hermes', 'agy'].map(a => ` + + `).join('')} + + +
+
+
Loading history...
+ `; + + window._historyAgent = ''; + window._historyFilter = ''; + await loadHistory(); +} + +function filterHistoryByAgent(agent) { + window._historyAgent = agent; + document.querySelectorAll('#pageContent button[data-agent]').forEach(b => { + b.classList.toggle('btn-primary', b.dataset.agent === agent); + b.classList.toggle('btn-ghost', b.dataset.agent !== agent); + }); + loadHistory(); +} + +async function loadHistory() { + const container = document.getElementById('historyResults'); + if (!container) return; + const q = (document.getElementById('historySearch')?.value || '').trim(); + try { + const data = await api.searchChatHistory(q, window._historyAgent, 500); + const messages = data.messages || []; + renderHistoryList(container, messages, q); + } catch (err) { + container.innerHTML = `
${escapeHtml(err.message)}
`; + } +} + +function renderHistoryList(container, messages, q) { + if (messages.length === 0) { + container.innerHTML = '
💬
No conversations found
Messages appear here after you chat with an agent.
'; + return; + } + + // Group by date (YYYY-MM-DD) + const groups = {}; + messages.forEach(m => { + const day = (m.timestamp || '').slice(0, 10) || 'Unknown date'; + (groups[day] = groups[day] || []).push(m); + }); + + const agentIcons = { opencode: '🔧', hermes: '⚡', agy: '🧠' }; + const highlight = (text) => { + if (!q) return escapeHtml(text); + const escaped = escapeHtml(text); + const ql = escapeHtml(q); + return escaped.split(new RegExp(`(${ql.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'i')).map((part, i) => + part.toLowerCase() === ql.toLowerCase() ? `${part}` : part + ).join(''); + }; + + container.innerHTML = Object.entries(groups).map(([day, msgs]) => ` +
+
📅 ${escapeHtml(day)}${msgs.length} msg
+
+ ${msgs.map(m => { + const icon = agentIcons[m.agent] || '🤖'; + return `
+
${m.role === 'user' ? '👤' : icon}
+
+
+ ${escapeHtml(m.role === 'user' ? 'You' : (m.agent || 'agent'))} + ${escapeHtml(m.agent || '')} + ${timeAgo(m.timestamp)} +
+
${highlight(m.content || '')}
+
+
`; + }).join('')} +
+
+ `).join(''); +} + +async function refreshHistory() { + await loadHistory(); +} + +function loadHistoryIntoChat(agent, content) { + navigate('chat'); + setTimeout(() => { + selectAgent(agent); + const input = document.getElementById('chatInput'); + if (input) { + input.value = content; + input.focus(); + autoResizeTextarea(input); + } + }, 300); +} diff --git a/dashboard/pages/memory.js b/dashboard/pages/memory.js index 5d2525e..ef4558b 100644 --- a/dashboard/pages/memory.js +++ b/dashboard/pages/memory.js @@ -7,35 +7,172 @@ async function renderMemory() {

Shared brain context across all agents

+
+ + +
`; + window._memoryView = 'files'; + await loadMemoryFiles(); +} + +function switchMemoryView(view) { + window._memoryView = view; + document.querySelectorAll('#memoryTabs .tab').forEach(t => t.classList.toggle('active', t.dataset.view === view)); + if (view === 'graph') loadMemoryGraph(); + else loadMemoryFiles(); +} + +async function loadMemoryFiles() { + const container = document.getElementById('memoryList'); + if (!container) return; + try { const brain = await api.getBrain(); const files = Object.entries(brain); - const container = document.getElementById('memoryList'); if (files.length === 0) { container.innerHTML = '
🧠
No memory files
'; return; } - container.innerHTML = `
${files.map(([name, content]) => { + container.innerHTML = `
${files.map(([name, content]) => { const preview = content ? content.slice(0, 200) : ''; const safeName = escapeHtml(name.replace('.md', '').replace(/-/g, ' ')); - return `
+ return `
${safeName}
${content ? content.split('\n').length : 0} lines
-
${escapeHtml(preview)}${preview.length >= 200 ? '...' : ''}
+
${escapeHtml(preview)}${preview.length >= 200 ? '...' : ''}
`; }).join('')}
`; } catch (err) { - document.getElementById('memoryList').innerHTML = `
${escapeHtml(err.message)}
`; + container.innerHTML = `
${escapeHtml(err.message)}
`; } } +async function loadMemoryGraph() { + const container = document.getElementById('memoryList'); + if (!container) return; + container.innerHTML = `
Building graph...
`; + + try { + const graph = await api.getMemoryGraph(); + const nodes = graph.nodes || []; + const edges = graph.edges || []; + + if (nodes.length === 0) { + container.innerHTML = '
🕸
No graph data
Run a memory reindex or chat with agents to build connections.
'; + return; + } + + const stats = graph.stats || {}; + container.innerHTML = ` +
+
+ 📄 ${stats.nodes || 0} nodes + 🔗 ${stats.edges || 0} edges + ${nodes.filter(n => (n.type || '').startsWith('entity')).length} entities +
+
+
+ +
+
Click a node to open the associated file. Drag to pan, scroll to zoom.
+ `; + drawMemoryGraph(graph); + } catch (err) { + container.innerHTML = `
${escapeHtml(err.message)}
`; + } +} + +function drawMemoryGraph(graph) { + const canvas = document.getElementById('memoryGraphCanvas'); + if (!canvas) return; + const ctx = canvas.getContext('2d'); + const dpr = window.devicePixelRatio || 1; + const width = canvas.clientWidth || 800; + const height = canvas.clientHeight || 480; + canvas.width = width * dpr; + canvas.height = height * dpr; + ctx.scale(dpr, dpr); + + const nodes = graph.nodes || []; + const edges = graph.edges || []; + const typeColors = { + brain: '#6c5ce7', skill: '#00b894', journal: '#fdcb6e', general: '#74b9ff', + }; + const colorFor = (t) => { + if (t.startsWith('entity:')) return '#fd79a8'; + return typeColors[t] || '#74b9ff'; + }; + + // Simple layout: entities on left, docs spread on right (force-ish radial fallback) + const entityNodes = nodes.filter(n => (n.type || '').startsWith('entity:')); + const docNodes = nodes.filter(n => !(n.type || '').startsWith('entity:')); + const positions = {}; + const cx = width / 2, cy = height / 2; + docNodes.forEach((n, i) => { + const angle = (i / Math.max(docNodes.length, 1)) * Math.PI * 2 - Math.PI / 2; + positions[n.id] = { x: cx + Math.cos(angle) * Math.min(width * 0.3, 200), y: cy + Math.sin(angle) * Math.min(height * 0.35, 180) }; + }); + entityNodes.forEach((n, i) => { + const angle = (i / Math.max(entityNodes.length, 1)) * Math.PI * 2 - Math.PI / 2; + positions[n.id] = { x: cx + Math.cos(angle) * Math.min(width * 0.38, 260), y: cy + Math.sin(angle) * Math.min(height * 0.42, 220) }; + }); + + ctx.clearRect(0, 0, width, height); + ctx.lineWidth = 1; + ctx.strokeStyle = 'rgba(148,163,184,0.4)'; + edges.forEach(e => { + const a = positions[e.source], b = positions[e.target]; + if (!a || !b) return; + ctx.beginPath(); + ctx.moveTo(a.x, a.y); + ctx.lineTo(b.x, b.y); + ctx.stroke(); + }); + + nodes.forEach(n => { + const p = positions[n.id]; + if (!p) return; + const color = colorFor(n.type); + const isEntity = (n.type || '').startsWith('entity:'); + const radius = isEntity ? 6 : 10; + ctx.beginPath(); + ctx.arc(p.x, p.y, radius, 0, Math.PI * 2); + ctx.fillStyle = color; + ctx.fill(); + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 1.5; + ctx.stroke(); + const label = (n.label || '').slice(0, 18); + ctx.fillStyle = 'var(--text-secondary, #cbd5e1)'; + ctx.font = '10px Inter, sans-serif'; + ctx.fillText(label, p.x + radius + 4, p.y + 4); + }); + + // Click-to-open: store layout for hit testing + window._graphLayout = { positions, nodes, docById: {} }; + nodes.forEach(n => { window._graphLayout.docById[n.id] = n; }); + canvas.onclick = (ev) => { + const rect = canvas.getBoundingClientRect(); + const mx = ev.clientX - rect.left, my = ev.clientY - rect.top; + for (const [id, p] of Object.entries(positions)) { + if (Math.hypot(mx - p.x, my - p.y) < 14) { + const n = window._graphLayout.docById[id]; + if (n && n.path && n.path.endsWith('.md') && !(n.type || '').startsWith('entity:')) { + editMemory(encodeURIComponent(n.path.split('/').pop())); + } + return; + } + } + }; +} + async function editMemory(encodedName) { const name = decodeURIComponent(encodedName); const display = escapeHtml(name.replace('.md', '').replace(/-/g, ' ')); diff --git a/dashboard/pages/settings.js b/dashboard/pages/settings.js index 54fbec7..7703da6 100644 --- a/dashboard/pages/settings.js +++ b/dashboard/pages/settings.js @@ -22,7 +22,7 @@ async function renderSettings() {
🤖 Agent Preferences
- ${['opencode', 'hermes', 'gemini'].map(a => ` + ${['opencode', 'hermes', 'agy'].map(a => `
@@ -124,7 +124,7 @@ async function saveAllSettings() { agent_preferences: { opencode: { enabled: document.getElementById('agent_opencode').checked, binary: document.getElementById('bin_opencode').value }, hermes: { enabled: document.getElementById('agent_hermes').checked, binary: document.getElementById('bin_hermes').value }, - gemini: { enabled: document.getElementById('agent_gemini').checked, binary: document.getElementById('bin_gemini').value }, + agy: { enabled: document.getElementById('agent_agy').checked, binary: document.getElementById('bin_agy').value }, }, dashboard: { port: parseInt(document.getElementById('setPort').value) || 8080, @@ -167,7 +167,7 @@ async function resetSettings() { async function confirmReset() { const defaults = { theme: 'dark', - agent_preferences: { opencode: { enabled: true, binary: 'opencode' }, hermes: { enabled: true, binary: 'hermes' }, gemini: { enabled: true, binary: 'gemini', model: 'gemini-2.5-flash' } }, + agent_preferences: { opencode: { enabled: true, binary: 'opencode' }, hermes: { enabled: true, binary: 'hermes' }, agy: { enabled: true, binary: 'agy' } }, dashboard: { port: 8080, host: '127.0.0.1', dark_mode: true }, api_keys: { gemini: '', openrouter: '' }, free_tier_limits: { gemini_flash: { requests_per_day: 1500, tokens_per_day: 1000000 }, openrouter_free: { requests_per_day: 100, tokens_per_day: 200000 } }, diff --git a/dashboard/pages/setup-wizard.js b/dashboard/pages/setup-wizard.js index a227992..5955222 100644 --- a/dashboard/pages/setup-wizard.js +++ b/dashboard/pages/setup-wizard.js @@ -51,7 +51,7 @@ async function renderWizardStep() { wc.innerHTML = `
-

Agentic OS coordinates opencode, Hermes Agent, and Gemini CLI into a unified multi-agent orchestration platform. This wizard will help you get everything configured.

+

Agentic OS coordinates opencode, Hermes Agent, and agy into a unified multi-agent orchestration platform. This wizard will help you get everything configured.

`; break; @@ -89,7 +89,7 @@ async function renderWizardStep() {
diff --git a/dashboard/pages/skills.js b/dashboard/pages/skills.js index 9258513..d60b3e6 100644 --- a/dashboard/pages/skills.js +++ b/dashboard/pages/skills.js @@ -102,6 +102,7 @@ async function showSkillDetail(encodedName) {
+
@@ -159,7 +160,7 @@ async function quickRunSkill(encodedName) { - +
@@ -202,3 +203,37 @@ async function executeSkillRun(encodedName) { if (runBtn) { runBtn.textContent = '▶ Run'; runBtn.disabled = false; } } } + +async function showSkillDiff(encodedName) { + const name = decodeURIComponent(encodedName); + showModal(`Diff: ${escapeHtml(name)}`, ` +
+ +
+ + +
+
+
Enter a file path to see its git diff.
+ `, ` + + `); +} + +async function loadDiff() { + const input = document.getElementById('diffFile'); + const result = document.getElementById('diffResult'); + const file = input ? input.value.trim() : ''; + if (!file) { showToast('Enter a file path', 'warning'); return; } + result.innerHTML = '
'; + try { + const data = await api.getDiff(file); + if (!data.changed) { + result.innerHTML = `
No changes
${escapeHtml(file)} matches HEAD (or no uncommitted diff).
`; + return; + } + result.innerHTML = `
${escapeHtml(data.diff)}
`; + } catch (err) { + result.innerHTML = `
Error
${escapeHtml(err.message)}
`; + } +} diff --git a/dashboard/pages/smart-router.js b/dashboard/pages/smart-router.js index ba8e319..286d253 100644 --- a/dashboard/pages/smart-router.js +++ b/dashboard/pages/smart-router.js @@ -22,7 +22,7 @@ async function renderSmartRouter() { - +
@@ -36,7 +36,7 @@ async function renderSmartRouter() { AgentBest ForKeywords 🔧 opencodeCode, DevOps, infra, git, file operationscode, deploy, git, terraform, docker, test, build, script ⚡ HermesMemory, scheduling, messaging, skillsmemory, schedule, cron, reminder, brain, plugin, backup - 🧠 Gemini CLIResearch, analysis, study, document, reviewresearch, analyze, search, explain, study, learn, report + 🧠 agyResearch, analysis, study, document, reviewresearch, analyze, search, explain, study, learn, report
`; @@ -50,7 +50,7 @@ async function suggestRouter() { try { const data = await api.suggestRouter(task); const result = document.getElementById('routerResult'); - const agentIcons = { opencode: '🔧', hermes: '⚡', gemini: '🧠' }; + const agentIcons = { opencode: '🔧', hermes: '⚡', agy: '🧠' }; const confidenceColors = { high: 'var(--green)', medium: 'var(--yellow)', low: 'var(--text-muted)' }; result.innerHTML = `
diff --git a/dashboard/styles.css b/dashboard/styles.css index 265b310..12e9adc 100644 --- a/dashboard/styles.css +++ b/dashboard/styles.css @@ -214,6 +214,7 @@ body { padding: 12px 28px; border-bottom: 1px solid var(--border); min-height: 56px; background: var(--bg-secondary); flex-shrink: 0; + width: 100%; max-width: 1600px; margin: 0 auto; } .topbar-left { display: flex; align-items: center; gap: 12px; } .topbar-title { font-size: 16px; font-weight: 600; } @@ -237,6 +238,7 @@ body { flex: 1; display: flex; flex-direction: column; overflow-y: auto; padding: 24px 28px; min-height: 0; + width: 100%; max-width: 1600px; margin: 0 auto; } /* ─── Page Header ─── */ @@ -543,7 +545,7 @@ pre { /* ─── Tabs ─── */ .tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); - margin-bottom: 16px; overflow-x: auto; + margin-bottom: 16px; overflow-x: auto; flex-shrink: 0; } .tab { padding: 10px 16px; font-size: 13px; font-weight: 500; diff --git a/dashboard/utils.js b/dashboard/utils.js index 717eee5..f2c87ba 100644 --- a/dashboard/utils.js +++ b/dashboard/utils.js @@ -123,6 +123,7 @@ const PAGE_TITLES = { settings: { title: 'Settings', breadcrumb: 'Configuration' }, 'setup-wizard': { title: 'Setup Wizard', breadcrumb: 'Guided configuration' }, chat: { title: 'AI Chat', breadcrumb: 'Multi-agent terminal' }, + history: { title: 'Chat History', breadcrumb: 'Browse & replay conversations' }, errors: { title: 'Error Dashboard', breadcrumb: 'System errors & circuit breaker' }, kanban: { title: 'Kanban Board', breadcrumb: 'Multi-agent task management' }, goals: { title: 'Goals', breadcrumb: 'Project targets and progress' }, diff --git a/data/agent-routes.json b/data/agent-routes.json index 86210b0..66de209 100644 --- a/data/agent-routes.json +++ b/data/agent-routes.json @@ -12,7 +12,7 @@ }, { "pattern": "research|analyze|search|summarize|compare|investigate|learn", - "target": "gemini", + "target": "agy", "priority": 10 }, { @@ -25,7 +25,7 @@ "agent_capabilities": { "opencode": ["code_generation", "file_operations", "git_management", "terminal_execution", "infrastructure_as_code", "testing", "debugging"], "hermes": ["persistent_memory", "scheduled_tasks", "messaging_channels", "skill_hub", "voice", "browser_automation", "subagent_delegation"], - "gemini": ["web_search", "multi_modal_analysis", "document_understanding", "data_analysis", "research_synthesis", "reasoning"] + "agy": ["web_search", "multi_modal_analysis", "document_understanding", "data_analysis", "research_synthesis", "reasoning"] }, "handoff_protocol": { "enabled": true, diff --git a/docs/agentic-os-architecture.svg b/docs/agentic-os-architecture.svg index c70ca24..ea4af83 100644 --- a/docs/agentic-os-architecture.svg +++ b/docs/agentic-os-architecture.svg @@ -199,12 +199,12 @@ Cron scheduling & Telegram/Discord - + 🔍 - Gemini CLI + agy CLI Research & Analysis Agent @@ -217,7 +217,7 @@ 138 files · 16 skills · 7 brain files · 13 dashboard pages · MIT - 100% Free Tier — OpenRouter · Gemini Flash · Local opencode + 100% Free Tier — OpenRouter · Antigravity (agy) · Local opencode github.com/modimihir07/agentic-os diff --git a/docs/index.html b/docs/index.html index 391e010..747ad39 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,22 +5,22 @@ -Agentic OS (agentic-os) — Multi-Agent Dashboard & GitHub Repository | opencode + Hermes + Gemini CLI - - +Agentic OS (agentic-os) — Multi-Agent Dashboard & GitHub Repository | opencode + Hermes + agy CLI + + - + - +