From 6dbbca8e55b02db8da4fa7c5b182aaa37a24c604 Mon Sep 17 00:00:00 2001 From: fujie Date: Mon, 16 Mar 2026 04:09:29 +0800 Subject: [PATCH] Remove deprecated agent coordination files and scripts; update documentation and streamline agent protocols. --- .agent/agent_hub.db | Bin 122880 -> 0 bytes .agent/rules/agent_protocol.md | 29 - .github/agents/plugin-planner.agent.md | 1 - CLAUDE.md | 37 +- COOPERATION.md | 33 - scripts/agent_sync_v2.py | 847 ------------------------- scripts/macp | 110 ---- zed-ai-tabs.sh | 139 ---- 8 files changed, 28 insertions(+), 1168 deletions(-) delete mode 100644 .agent/agent_hub.db delete mode 100644 .agent/rules/agent_protocol.md delete mode 100644 COOPERATION.md delete mode 100755 scripts/agent_sync_v2.py delete mode 100755 scripts/macp delete mode 100755 zed-ai-tabs.sh diff --git a/.agent/agent_hub.db b/.agent/agent_hub.db deleted file mode 100644 index d93646390e8e5e54a04d09cfea7224b5c0d27133..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122880 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 diff --git a/.agent/rules/agent_protocol.md b/.agent/rules/agent_protocol.md deleted file mode 100644 index 6b0e983..0000000 --- a/.agent/rules/agent_protocol.md +++ /dev/null @@ -1,29 +0,0 @@ -# Agent Coordination Protocol (FOR AGENTS ONLY) - -## 🛡️ The Golden Rule -**NEVER modify code without verifying the lock status in the Agent Hub.** - -## 🔑 Identity Management -- `claude-code`: Official Claude CLI -- `copilot-agent`: GitHub Copilot -- `gemini-cursor`: Cursor IDE or Gemini extension -- `iflow-agent`: iFlow SDK agent - -## 🛠️ The Synchronization Tool -Script: `scripts/agent_sync.py` (SQLite-backed) - -### 🏎️ Workflow Lifecycle -1. **Initialize Session**: - - `python3 scripts/agent_sync.py status` - - `python3 scripts/agent_sync.py register ""` -2. **Resource Acquisition**: - - `python3 scripts/agent_sync.py lock ` - - If blocked, identify the owner from `status` and do not attempt to bypass. -3. **Collaboration (Research Mode)**: - - If the project mode is `RESEARCH`, prioritize the `note` command. - - Summarize findings: `python3 scripts/agent_sync.py note "" ""` -4. **Cleanup**: - - `python3 scripts/agent_sync.py unlock ` - -## 📜 Shared Memory -Read `.agent/learnings/` to avoid reinventing the wheel. diff --git a/.github/agents/plugin-planner.agent.md b/.github/agents/plugin-planner.agent.md index 69e9c8f..8d712a8 100644 --- a/.github/agents/plugin-planner.agent.md +++ b/.github/agents/plugin-planner.agent.md @@ -3,7 +3,6 @@ name: Plugin Planner description: Analyze requirements and produce a safe implementation plan for OpenWebUI plugins argument-hint: Describe the plugin goal, constraints, and target files tools: ['read/readFile', 'search', 'web', 'web/githubRepo', 'read/terminalLastCommand', 'read/terminalSelection', 'agent'] -infer: true handoffs: - label: Start Implementation agent: Plugin Implementer diff --git a/CLAUDE.md b/CLAUDE.md index b5b2924..cf28b43 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,13 +1,32 @@ -# 🤖 Claude Multi-Agent Protocol (MACP) - -## 🚀 Mandatory Startup -1. **Check Hub**: `python3 scripts/agent_sync.py status` -2. **Register**: `python3 scripts/agent_sync.py register claude-code "Claude" "Handling user request"` -3. **Lock**: `python3 scripts/agent_sync.py lock claude-code ` -4. **Handoff**: Use `python3 scripts/agent_sync.py note` for collaborative findings. +# 🤖 OpenWebUI Extensions ## 🤝 Project Standards Read these BEFORE writing any code: - `.agent/rules/plugin_standards.md` -- `.agent/rules/agent_protocol.md` -- `COOPERATION.md` + +## 📖 Development Guidelines + +### Writing Documentation +- All plugins MUST have both English (`README.md`) and Chinese (`README_CN.md`) documentation +- Follow the template at `docs/PLUGIN_README_TEMPLATE.md` +- Keep versions in sync across all files + +### Code Standards +- Use logging instead of print +- Implement Valves for configuration +- Use Lucide icons +- Include i18n support + +### Release Process +- Update version numbers in ALL relevant files (code, READMEs, docs) +- Use Conventional Commits format (`feat`, `fix`, `docs`, etc.) +- Create PRs using GitHub CLI (`gh pr create`) + +## Author + +Fu-Jie +GitHub: [Fu-Jie/openwebui-extensions](https://github.com/Fu-Jie/openwebui-extensions) + +## License + +MIT License diff --git a/COOPERATION.md b/COOPERATION.md deleted file mode 100644 index 240a75b..0000000 --- a/COOPERATION.md +++ /dev/null @@ -1,33 +0,0 @@ -# 🤖 Multi-Agent Cooperation Protocol (MACP) v2.1 - -本项目采用 **SQLite 协作中控 (Agent Hub)** 来管理多个 AI Agent 的并发任务。 - -## 🚀 核心指令 (Quick Commands) -使用 `./scripts/macp` 即可快速调用,无需记忆复杂的 Python 参数。 - -| 指令 | 描述 | -| :--- | :--- | -| **`/status`** | 查看全场状态(活跃 Agent、文件锁、任务、研究主题) | -| **`/study `** | **一键发起联合研究**。广播主题并通知所有 Agent 进入研究状态。 | -| **`/summon `** | **定向召唤**。给特定 Agent 派发高优先级任务。 | -| **`/handover `** | **任务接力**。释放当前进度并交棒给下一个 Agent。 | -| **`/broadcast `** | **全场广播**。发送紧急通知或状态同步。 | -| **`/check`** | **收件箱检查**。查看是否有分配给你的待办任务。 | -| **`/resolve `** | **归档结论**。结束研究专题并记录最终共识。 | -| **`/ping`** | **生存检查**。快速查看哪些 Agent 在线。 | - ---- - -## 🛡️ 协作准则 -1. **先查后动**:开始工作前先运行 `./scripts/macp /status`。 -2. **锁即所有权**:修改文件前必须获取锁。 -3. **意图先行**:大型重构建议先通过 `/study` 发起方案讨论。 -4. **及时解锁**:Commit 并 Push 后,请务必 `/handover` 或手动解锁。 - -## 📁 基础设施 -- **数据库**: `.agent/agent_hub.db` (不要手动编辑) -- **内核**: `scripts/agent_sync.py` -- **快捷工具**: `scripts/macp` - ---- -*Generated by Claude (Coordinator) in collaboration with Sisyphus & Copilot.* diff --git a/scripts/agent_sync_v2.py b/scripts/agent_sync_v2.py deleted file mode 100755 index a1f82c5..0000000 --- a/scripts/agent_sync_v2.py +++ /dev/null @@ -1,847 +0,0 @@ -#!/usr/bin/env python3 -""" -🤖 AGENT SYNC TOOL v2.0 - MULTI-AGENT COOPERATION PROTOCOL (MACP) ---------------------------------------------------------- -Enhanced collaboration commands for seamless multi-agent synergy. - -QUICK COMMANDS: - @research - Start a joint research topic - @join - Join an active research topic - @find - Post a finding to research topic - @consensus - Generate consensus document - @assign - Assign task to specific agent - @notify - Broadcast to all agents - @handover - Handover current task - @poll - Start a quick poll - @switch - Request switch to specific agent - -WORKFLOW: @research -> @find (xN) -> @consensus -> @assign -""" -import sqlite3 -import os -import sys -import argparse -import json -from datetime import datetime, timedelta -from typing import List, Dict, Optional - -DB_PATH = os.path.join(os.getcwd(), ".agent/agent_hub.db") - -def get_connection(): - os.makedirs(os.path.dirname(DB_PATH), exist_ok=True) - return sqlite3.connect(DB_PATH) - -def init_db(): - conn = get_connection() - cursor = conn.cursor() - cursor.executescript(''' - CREATE TABLE IF NOT EXISTS agents ( - id TEXT PRIMARY KEY, - name TEXT, - task TEXT, - status TEXT DEFAULT 'idle', - current_research TEXT, - last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - CREATE TABLE IF NOT EXISTS file_locks ( - file_path TEXT PRIMARY KEY, - agent_id TEXT, - lock_type TEXT, - timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY(agent_id) REFERENCES agents(id) - ); - CREATE TABLE IF NOT EXISTS research_log ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - agent_id TEXT, - topic TEXT, - content TEXT, - finding_type TEXT DEFAULT 'note', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - FOREIGN KEY(agent_id) REFERENCES agents(id) - ); - CREATE TABLE IF NOT EXISTS research_topics ( - topic TEXT PRIMARY KEY, - status TEXT DEFAULT 'active', - initiated_by TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - completed_at TIMESTAMP - ); - CREATE TABLE IF NOT EXISTS agent_research_participation ( - agent_id TEXT, - topic TEXT, - joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (agent_id, topic) - ); - CREATE TABLE IF NOT EXISTS task_assignments ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - agent_id TEXT, - task TEXT, - assigned_by TEXT, - status TEXT DEFAULT 'pending', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - completed_at TIMESTAMP - ); - CREATE TABLE IF NOT EXISTS notifications ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - agent_id TEXT, - message TEXT, - is_broadcast BOOLEAN DEFAULT 0, - is_read BOOLEAN DEFAULT 0, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - CREATE TABLE IF NOT EXISTS polls ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - question TEXT, - created_by TEXT, - status TEXT DEFAULT 'active', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ); - CREATE TABLE IF NOT EXISTS poll_votes ( - poll_id INTEGER, - agent_id TEXT, - vote TEXT, - voted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (poll_id, agent_id) - ); - CREATE TABLE IF NOT EXISTS global_settings ( - key TEXT PRIMARY KEY, - value TEXT - ); - ''') - cursor.execute("INSERT OR IGNORE INTO global_settings (key, value) VALUES ('mode', 'isolation')") - conn.commit() - conn.close() - print(f"✅ Agent Hub v2.0 initialized at {DB_PATH}") - -# ============ AGENT MANAGEMENT ============ - -def register_agent(agent_id, name, task, status="idle"): - conn = get_connection() - cursor = conn.cursor() - cursor.execute(''' - INSERT OR REPLACE INTO agents (id, name, task, status, last_seen) - VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP) - ''', (agent_id, name, task, status)) - conn.commit() - conn.close() - print(f"🤖 Agent '{name}' ({agent_id}) registered.") - -def update_agent_status(agent_id, status, research_topic=None): - conn = get_connection() - cursor = conn.cursor() - if research_topic: - cursor.execute(''' - UPDATE agents SET status = ?, current_research = ?, last_seen = CURRENT_TIMESTAMP - WHERE id = ? - ''', (status, research_topic, agent_id)) - else: - cursor.execute(''' - UPDATE agents SET status = ?, last_seen = CURRENT_TIMESTAMP - WHERE id = ? - ''', (status, agent_id)) - conn.commit() - conn.close() - -# ============ RESEARCH COLLABORATION ============ - -def start_research(agent_id, topic): - """@research - Start a new research topic and notify all agents""" - conn = get_connection() - cursor = conn.cursor() - - # Create research topic - try: - cursor.execute(''' - INSERT INTO research_topics (topic, status, initiated_by) - VALUES (?, 'active', ?) - ''', (topic, agent_id)) - except sqlite3.IntegrityError: - print(f"⚠️ Research topic '{topic}' already exists") - conn.close() - return - - # Add initiator as participant - cursor.execute(''' - INSERT OR IGNORE INTO agent_research_participation (agent_id, topic) - VALUES (?, ?) - ''', (agent_id, topic)) - - # Update agent status - cursor.execute(''' - UPDATE agents SET status = 'researching', current_research = ? - WHERE id = ? - ''', (topic, agent_id)) - - # Notify all other agents - cursor.execute("SELECT id FROM agents WHERE id != ?", (agent_id,)) - other_agents = cursor.fetchall() - for (other_id,) in other_agents: - cursor.execute(''' - INSERT INTO notifications (agent_id, message, is_broadcast) - VALUES (?, ?, 0) - ''', (other_id, f"🔬 New research started: '{topic}' by {agent_id}. Use '@join {topic}' to participate.")) - - conn.commit() - conn.close() - - print(f"🔬 Research topic '{topic}' started by {agent_id}") - print(f"📢 Notified {len(other_agents)} other agents") - -def join_research(agent_id, topic): - """@join - Join an active research topic""" - conn = get_connection() - cursor = conn.cursor() - - # Check if topic exists and is active - cursor.execute("SELECT status FROM research_topics WHERE topic = ?", (topic,)) - result = cursor.fetchone() - if not result: - print(f"❌ Research topic '{topic}' not found") - conn.close() - return - if result[0] != 'active': - print(f"⚠️ Research topic '{topic}' is {result[0]}") - conn.close() - return - - # Add participant - cursor.execute(''' - INSERT OR IGNORE INTO agent_research_participation (agent_id, topic) - VALUES (?, ?) - ''', (agent_id, topic)) - - # Update agent status - cursor.execute(''' - UPDATE agents SET status = 'researching', current_research = ? - WHERE id = ? - ''', (topic, agent_id)) - - conn.commit() - conn.close() - print(f"✅ {agent_id} joined research: '{topic}'") - -def post_finding(agent_id, topic, content, finding_type="note"): - """@find - Post a finding to research topic""" - conn = get_connection() - cursor = conn.cursor() - - # Check if topic exists - cursor.execute("SELECT status FROM research_topics WHERE topic = ?", (topic,)) - result = cursor.fetchone() - if not result: - print(f"❌ Research topic '{topic}' not found") - conn.close() - return - if result[0] != 'active': - print(f"⚠️ Research topic '{topic}' is {result[0]}") - - # Add finding - cursor.execute(''' - INSERT INTO research_log (agent_id, topic, content, finding_type) - VALUES (?, ?, ?, ?) - ''', (agent_id, topic, content, finding_type)) - - # Update agent status - cursor.execute(''' - UPDATE agents SET last_seen = CURRENT_TIMESTAMP WHERE id = ? - ''', (agent_id,)) - - conn.commit() - conn.close() - print(f"📝 Finding added to '{topic}' by {agent_id}") - -def generate_consensus(topic): - """@consensus - Generate consensus document from research findings""" - conn = get_connection() - cursor = conn.cursor() - - # Get all findings - cursor.execute(''' - SELECT agent_id, content, finding_type, created_at - FROM research_log - WHERE topic = ? - ORDER BY created_at - ''', (topic,)) - findings = cursor.fetchall() - - if not findings: - print(f"⚠️ No findings found for topic '{topic}'") - conn.close() - return - - # Get participants - cursor.execute(''' - SELECT agent_id FROM agent_research_participation WHERE topic = ? - ''', (topic,)) - participants = [row[0] for row in cursor.fetchall()] - - # Mark topic as completed - cursor.execute(''' - UPDATE research_topics - SET status = 'completed', completed_at = CURRENT_TIMESTAMP - WHERE topic = ? - ''', (topic,)) - - conn.commit() - conn.close() - - # Generate consensus document - consensus_dir = os.path.join(os.getcwd(), ".agent/consensus") - os.makedirs(consensus_dir, exist_ok=True) - - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - filename = f"{topic.replace(' ', '_').replace('/', '_')}_{timestamp}.md" - filepath = os.path.join(consensus_dir, filename) - - with open(filepath, 'w', encoding='utf-8') as f: - f.write(f"# 🎯 Consensus: {topic}\n\n") - f.write(f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n") - f.write(f"**Participants**: {', '.join(participants)}\n\n") - f.write("---\n\n") - - for agent_id, content, finding_type, created_at in findings: - f.write(f"## [{finding_type.upper()}] {agent_id}\n\n") - f.write(f"*{created_at}*\n\n") - f.write(f"{content}\n\n") - - print(f"✅ Consensus generated: {filepath}") - print(f"📊 Total findings: {len(findings)}") - print(f"👥 Participants: {len(participants)}") - - return filepath - -# ============ TASK MANAGEMENT ============ - -def assign_task(assigned_by, agent_id, task): - """@assign - Assign task to specific agent""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute(''' - INSERT INTO task_assignments (agent_id, task, assigned_by) - VALUES (?, ?, ?) - ''', (agent_id, task, assigned_by)) - - # Notify the agent - cursor.execute(''' - INSERT INTO notifications (agent_id, message, is_broadcast) - VALUES (?, ?, 0) - ''', (agent_id, f"📋 New task assigned by {assigned_by}: {task}")) - - conn.commit() - conn.close() - print(f"📋 Task assigned to {agent_id} by {assigned_by}") - -def list_tasks(agent_id=None): - """List tasks for an agent or all agents""" - conn = get_connection() - cursor = conn.cursor() - - if agent_id: - cursor.execute(''' - SELECT id, task, assigned_by, status, created_at - FROM task_assignments - WHERE agent_id = ? AND status != 'completed' - ORDER BY created_at DESC - ''', (agent_id,)) - tasks = cursor.fetchall() - - print(f"\n📋 Tasks for {agent_id}:") - for task_id, task, assigned_by, status, created_at in tasks: - print(f" [{status.upper()}] #{task_id}: {task} (from {assigned_by})") - else: - cursor.execute(''' - SELECT agent_id, id, task, assigned_by, status - FROM task_assignments - WHERE status != 'completed' - ORDER BY agent_id - ''') - tasks = cursor.fetchall() - - print(f"\n📋 All pending tasks:") - current_agent = None - for agent, task_id, task, assigned_by, status in tasks: - if agent != current_agent: - print(f"\n {agent}:") - current_agent = agent - print(f" [{status.upper()}] #{task_id}: {task}") - - conn.close() - -def complete_task(task_id): - """Mark a task as completed""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute(''' - UPDATE task_assignments - SET status = 'completed', completed_at = CURRENT_TIMESTAMP - WHERE id = ? - ''', (task_id,)) - - if cursor.rowcount > 0: - print(f"✅ Task #{task_id} marked as completed") - else: - print(f"❌ Task #{task_id} not found") - - conn.commit() - conn.close() - -# ============ NOTIFICATIONS ============ - -def broadcast_message(from_agent, message): - """@notify - Broadcast message to all agents""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute("SELECT id FROM agents WHERE id != ?", (from_agent,)) - other_agents = cursor.fetchall() - - for (agent_id,) in other_agents: - cursor.execute(''' - INSERT INTO notifications (agent_id, message, is_broadcast) - VALUES (?, ?, 1) - ''', (agent_id, f"📢 Broadcast from {from_agent}: {message}")) - - conn.commit() - conn.close() - print(f"📢 Broadcast sent to {len(other_agents)} agents") - -def get_notifications(agent_id, unread_only=False): - """Get notifications for an agent""" - conn = get_connection() - cursor = conn.cursor() - - if unread_only: - cursor.execute(''' - SELECT id, message, is_broadcast, created_at - FROM notifications - WHERE agent_id = ? AND is_read = 0 - ORDER BY created_at DESC - ''', (agent_id,)) - else: - cursor.execute(''' - SELECT id, message, is_broadcast, created_at - FROM notifications - WHERE agent_id = ? - ORDER BY created_at DESC - LIMIT 10 - ''', (agent_id,)) - - notifications = cursor.fetchall() - - print(f"\n🔔 Notifications for {agent_id}:") - for notif_id, message, is_broadcast, created_at in notifications: - prefix = "📢" if is_broadcast else "🔔" - print(f" {prefix} {message}") - print(f" {created_at}") - - # Mark as read - cursor.execute(''' - UPDATE notifications SET is_read = 1 - WHERE agent_id = ? AND is_read = 0 - ''', (agent_id,)) - - conn.commit() - conn.close() - -# ============ POLLS ============ - -def start_poll(agent_id, question): - """@poll - Start a quick poll""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute(''' - INSERT INTO polls (question, created_by, status) - VALUES (?, ?, 'active') - ''', (question, agent_id)) - poll_id = cursor.lastrowid - - # Notify all agents - cursor.execute("SELECT id FROM agents WHERE id != ?", (agent_id,)) - other_agents = cursor.fetchall() - for (other_id,) in other_agents: - cursor.execute(''' - INSERT INTO notifications (agent_id, message, is_broadcast) - VALUES (?, ?, 0) - ''', (other_id, f"🗳️ New poll from {agent_id}: '{question}' (Poll #{poll_id}). Vote with: @vote {poll_id} ")) - - conn.commit() - conn.close() - print(f"🗳️ Poll #{poll_id} started: {question}") - return poll_id - -def vote_poll(agent_id, poll_id, vote): - """@vote - Vote on a poll""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute(''' - INSERT OR REPLACE INTO poll_votes (poll_id, agent_id, vote) - VALUES (?, ?, ?) - ''', (poll_id, agent_id, vote)) - - conn.commit() - conn.close() - print(f"✅ Vote recorded for poll #{poll_id}: {vote}") - -def show_poll_results(poll_id): - """Show poll results""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute("SELECT question FROM polls WHERE id = ?", (poll_id,)) - result = cursor.fetchone() - if not result: - print(f"❌ Poll #{poll_id} not found") - conn.close() - return - - question = result[0] - - cursor.execute(''' - SELECT vote, COUNT(*) FROM poll_votes - WHERE poll_id = ? - GROUP BY vote - ''', (poll_id,)) - votes = dict(cursor.fetchall()) - - cursor.execute(''' - SELECT agent_id, vote FROM poll_votes - WHERE poll_id = ? - ''', (poll_id,)) - details = cursor.fetchall() - - conn.close() - - print(f"\n🗳️ Poll #{poll_id}: {question}") - print("Results:") - for vote, count in votes.items(): - print(f" {vote}: {count}") - print("\nVotes:") - for agent, vote in details: - print(f" {agent}: {vote}") - -# ============ HANDOVER ============ - -def request_handover(from_agent, to_agent, context=""): - """@handover - Request task handover to another agent""" - conn = get_connection() - cursor = conn.cursor() - - # Get current task of from_agent - cursor.execute("SELECT task FROM agents WHERE id = ?", (from_agent,)) - result = cursor.fetchone() - current_task = result[0] if result else "current task" - - # Create handover notification - message = f"🔄 Handover request from {from_agent}: '{current_task}'" - if context: - message += f" | Context: {context}" - - cursor.execute(''' - INSERT INTO notifications (agent_id, message, is_broadcast) - VALUES (?, ?, 0) - ''', (to_agent, message)) - - # Update from_agent status - cursor.execute(''' - UPDATE agents SET status = 'idle', task = NULL - WHERE id = ? - ''', (from_agent,)) - - conn.commit() - conn.close() - print(f"🔄 Handover requested: {from_agent} -> {to_agent}") - -def switch_to(agent_id, to_agent): - """@switch - Request to switch to specific agent""" - conn = get_connection() - cursor = conn.cursor() - - message = f"🔄 {agent_id} requests to switch to you for continuation" - - cursor.execute(''' - INSERT INTO notifications (agent_id, message, is_broadcast) - VALUES (?, ?, 0) - ''', (to_agent, message)) - - conn.commit() - conn.close() - print(f"🔄 Switch request sent: {agent_id} -> {to_agent}") - -# ============ STATUS & MONITORING ============ - -def get_status(): - """Enhanced status view""" - conn = get_connection() - cursor = conn.cursor() - - print("\n" + "="*60) - print("🛰️ ACTIVE AGENTS") - print("="*60) - - for row in cursor.execute(''' - SELECT name, task, status, current_research, last_seen - FROM agents - ORDER BY last_seen DESC - '''): - status_emoji = { - 'active': '🟢', - 'idle': '⚪', - 'researching': '🔬', - 'busy': '🔴' - }.get(row[2], '⚪') - - research_info = f" | Research: {row[3]}" if row[3] else "" - print(f"{status_emoji} [{row[2].upper()}] {row[0]}: {row[1]}{research_info}") - print(f" Last seen: {row[4]}") - - print("\n" + "="*60) - print("🔬 ACTIVE RESEARCH TOPICS") - print("="*60) - - for row in cursor.execute(''' - SELECT t.topic, t.initiated_by, t.created_at, - (SELECT COUNT(*) FROM agent_research_participation WHERE topic = t.topic) as participants, - (SELECT COUNT(*) FROM research_log WHERE topic = t.topic) as findings - FROM research_topics t - WHERE t.status = 'active' - ORDER BY t.created_at DESC - '''): - print(f"🔬 {row[0]}") - print(f" Initiated by: {row[1]} | Participants: {row[3]} | Findings: {row[4]}") - print(f" Started: {row[2]}") - - print("\n" + "="*60) - print("🔒 FILE LOCKS") - print("="*60) - - locks = list(cursor.execute(''' - SELECT file_path, agent_id, lock_type - FROM file_locks - ORDER BY timestamp DESC - ''')) - - if locks: - for file_path, agent_id, lock_type in locks: - lock_emoji = '🔒' if lock_type == 'write' else '🔍' - print(f"{lock_emoji} {file_path} -> {agent_id} ({lock_type})") - else: - print(" No active locks") - - print("\n" + "="*60) - print("📋 PENDING TASKS") - print("="*60) - - for row in cursor.execute(''' - SELECT agent_id, COUNT(*) - FROM task_assignments - WHERE status = 'pending' - GROUP BY agent_id - '''): - print(f" {row[0]}: {row[1]} pending tasks") - - cursor.execute("SELECT value FROM global_settings WHERE key = 'mode'") - mode = cursor.fetchone()[0] - print(f"\n🌍 Global Mode: {mode.upper()}") - print("="*60) - - conn.close() - -def show_research_topic(topic): - """Show detailed view of a research topic""" - conn = get_connection() - cursor = conn.cursor() - - cursor.execute("SELECT status, initiated_by, created_at FROM research_topics WHERE topic = ?", (topic,)) - result = cursor.fetchone() - if not result: - print(f"❌ Topic '{topic}' not found") - conn.close() - return - - status, initiated_by, created_at = result - - print(f"\n🔬 Research: {topic}") - print(f"Status: {status} | Initiated by: {initiated_by} | Started: {created_at}") - - cursor.execute(''' - SELECT agent_id FROM agent_research_participation WHERE topic = ? - ''', (topic,)) - participants = [row[0] for row in cursor.fetchall()] - print(f"Participants: {', '.join(participants)}") - - print("\n--- Findings ---") - cursor.execute(''' - SELECT agent_id, content, finding_type, created_at - FROM research_log - WHERE topic = ? - ORDER BY created_at - ''', (topic,)) - - for agent_id, content, finding_type, created_at in cursor.fetchall(): - emoji = {'note': '📝', 'finding': '🔍', 'concern': '⚠️', 'solution': '✅'}.get(finding_type, '📝') - print(f"\n{emoji} [{finding_type.upper()}] {agent_id} ({created_at})") - print(f" {content}") - - conn.close() - -# ============ MAIN CLI ============ - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="🤖 Agent Sync v2.0 - Multi-Agent Cooperation Protocol", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=""" -QUICK COMMANDS: - @research Start joint research - @join Join active research - @find Post finding to research - @consensus Generate consensus document - @assign Assign task to agent - @notify Broadcast to all agents - @handover [context] Handover task - @switch Request switch to agent - @poll Start a poll - @vote Vote on poll - @tasks [agent] List tasks - @complete Complete task - @notifications [agent] Check notifications - @topic View research topic details - -EXAMPLES: - python3 agent_sync_v2.py research claude-code "API Design" - python3 agent_sync_v2.py find copilot "API Design" "Use REST instead of GraphQL" - python3 agent_sync_v2.py assign claude-code copilot "Implement REST endpoints" - python3 agent_sync_v2.py consensus "API Design" - """ - ) - subparsers = parser.add_subparsers(dest="command", help="Command to execute") - - # Legacy commands - subparsers.add_parser("init", help="Initialize the database") - - reg = subparsers.add_parser("register", help="Register an agent") - reg.add_argument("id", help="Agent ID") - reg.add_argument("name", help="Agent name") - reg.add_argument("task", help="Current task") - reg.add_argument("--status", default="idle", help="Agent status") - - lock = subparsers.add_parser("lock", help="Lock a file") - lock.add_argument("id", help="Agent ID") - lock.add_argument("path", help="File path") - lock.add_argument("--type", default="write", choices=["write", "research"], help="Lock type") - - unlock = subparsers.add_parser("unlock", help="Unlock a file") - unlock.add_argument("id", help="Agent ID") - unlock.add_argument("path", help="File path") - - subparsers.add_parser("status", help="Show status dashboard") - - # New v2.0 commands - research = subparsers.add_parser("research", help="@research - Start joint research topic") - research.add_argument("agent_id", help="Agent initiating research") - research.add_argument("topic", help="Research topic") - - join = subparsers.add_parser("join", help="@join - Join active research") - join.add_argument("agent_id", help="Agent joining") - join.add_argument("topic", help="Topic to join") - - find = subparsers.add_parser("find", help="@find - Post finding to research") - find.add_argument("agent_id", help="Agent posting finding") - find.add_argument("topic", help="Research topic") - find.add_argument("content", help="Finding content") - find.add_argument("--type", default="note", choices=["note", "finding", "concern", "solution"], help="Type of finding") - - consensus = subparsers.add_parser("consensus", help="@consensus - Generate consensus document") - consensus.add_argument("topic", help="Topic to generate consensus for") - - assign = subparsers.add_parser("assign", help="@assign - Assign task to agent") - assign.add_argument("from_agent", help="Agent assigning the task") - assign.add_argument("to_agent", help="Agent to assign task to") - assign.add_argument("task", help="Task description") - - tasks = subparsers.add_parser("tasks", help="@tasks - List pending tasks") - tasks.add_argument("--agent", help="Filter by agent ID") - - complete = subparsers.add_parser("complete", help="@complete - Mark task as completed") - complete.add_argument("task_id", type=int, help="Task ID to complete") - - notify = subparsers.add_parser("notify", help="@notify - Broadcast message to all agents") - notify.add_argument("from_agent", help="Agent sending notification") - notify.add_argument("message", help="Message to broadcast") - - handover = subparsers.add_parser("handover", help="@handover - Handover task to another agent") - handover.add_argument("from_agent", help="Current agent") - handover.add_argument("to_agent", help="Agent to handover to") - handover.add_argument("--context", default="", help="Handover context") - - switch = subparsers.add_parser("switch", help="@switch - Request switch to specific agent") - switch.add_argument("from_agent", help="Current agent") - switch.add_argument("to_agent", help="Agent to switch to") - - poll = subparsers.add_parser("poll", help="@poll - Start a quick poll") - poll.add_argument("agent_id", help="Agent starting poll") - poll.add_argument("question", help="Poll question") - - vote = subparsers.add_parser("vote", help="@vote - Vote on a poll") - vote.add_argument("agent_id", help="Agent voting") - vote.add_argument("poll_id", type=int, help="Poll ID") - vote.add_argument("vote_choice", choices=["yes", "no", "maybe"], help="Your vote") - - poll_results = subparsers.add_parser("poll-results", help="Show poll results") - poll_results.add_argument("poll_id", type=int, help="Poll ID") - - notifications = subparsers.add_parser("notifications", help="@notifications - Check notifications") - notifications.add_argument("agent_id", help="Agent to check notifications for") - notifications.add_argument("--unread", action="store_true", help="Show only unread") - - topic = subparsers.add_parser("topic", help="@topic - View research topic details") - topic.add_argument("topic_name", help="Topic name") - - args = parser.parse_args() - - if args.command == "init": - init_db() - elif args.command == "register": - register_agent(args.id, args.name, args.task, args.status) - elif args.command == "lock": - lock_file(args.id, args.path, args.type) - elif args.command == "unlock": - unlock_file(args.id, args.path) - elif args.command == "status": - get_status() - elif args.command == "research": - start_research(args.agent_id, args.topic) - elif args.command == "join": - join_research(args.agent_id, args.topic) - elif args.command == "find": - post_finding(args.agent_id, args.topic, args.content, args.type) - elif args.command == "consensus": - generate_consensus(args.topic) - elif args.command == "assign": - assign_task(args.from_agent, args.to_agent, args.task) - elif args.command == "tasks": - list_tasks(args.agent) - elif args.command == "complete": - complete_task(args.task_id) - elif args.command == "notify": - broadcast_message(args.from_agent, args.message) - elif args.command == "handover": - request_handover(args.from_agent, args.to_agent, args.context) - elif args.command == "switch": - switch_to(args.from_agent, args.to_agent) - elif args.command == "poll": - start_poll(args.agent_id, args.question) - elif args.command == "vote": - vote_poll(args.agent_id, args.poll_id, args.vote_choice) - elif args.command == "poll-results": - show_poll_results(args.poll_id) - elif args.command == "notifications": - get_notifications(args.agent_id, args.unread) - elif args.command == "topic": - show_research_topic(args.topic_name) - else: - parser.print_help() diff --git a/scripts/macp b/scripts/macp deleted file mode 100755 index 92e7fe7..0000000 --- a/scripts/macp +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash -# 🤖 MACP Quick Command v2.1 (Unified Edition) - -set -euo pipefail - -AGENT_ID_FILE=".agent/current_agent" - -resolve_agent_id() { - if [ -n "${MACP_AGENT_ID:-}" ]; then - echo "$MACP_AGENT_ID" - return - fi - - if [ -f "$AGENT_ID_FILE" ]; then - cat "$AGENT_ID_FILE" - return - fi - - echo "Error: MACP agent identity is not set. Export MACP_AGENT_ID or create .agent/current_agent." >&2 - exit 1 -} - -resolve_agent_name() { - python3 - <<'PY2' -import os -import sqlite3 -import sys - -agent_id = os.environ.get("MACP_AGENT_ID", "").strip() -if not agent_id: - path = os.path.join(os.getcwd(), ".agent", "current_agent") - if os.path.exists(path): - with open(path, "r", encoding="utf-8") as handle: - agent_id = handle.read().strip() - -db_path = os.path.join(os.getcwd(), ".agent", "agent_hub.db") -name = agent_id or "Agent" - -if agent_id and os.path.exists(db_path): - conn = sqlite3.connect(db_path) - cur = conn.cursor() - cur.execute("SELECT name FROM agents WHERE id = ?", (agent_id,)) - row = cur.fetchone() - conn.close() - if row and row[0]: - name = row[0] - -sys.stdout.write(name) -PY2 -} - -AGENT_ID="$(resolve_agent_id)" -export MACP_AGENT_ID="$AGENT_ID" -AGENT_NAME="$(resolve_agent_name)" - -CMD="${1:-}" -if [ -z "$CMD" ]; then - echo "Usage: ./scripts/macp [/status|/ping|/study|/broadcast|/summon|/handover|/note|/check|/resolve]" >&2 - exit 1 -fi -shift - -case "$CMD" in - /study) - TOPIC="$1" - shift - DESC="$*" - if [ -n "$DESC" ]; then - python3 scripts/agent_sync.py study "$AGENT_ID" "$TOPIC" --desc "$DESC" - else - python3 scripts/agent_sync.py study "$AGENT_ID" "$TOPIC" - fi - ;; - /broadcast) - python3 scripts/agent_sync.py broadcast "$AGENT_ID" manual "$*" - ;; - /summon) - TO_AGENT="$1" - shift - python3 scripts/agent_sync.py assign "$AGENT_ID" "$TO_AGENT" "$*" --role worker --priority high - ;; - /handover) - TO_AGENT="$1" - shift - python3 scripts/agent_sync.py assign "$AGENT_ID" "$TO_AGENT" "$*" --role worker - python3 scripts/agent_sync.py register "$AGENT_ID" "$AGENT_NAME" "Idle" - ;; - /note) - TOPIC="$1" - shift - python3 scripts/agent_sync.py note "$AGENT_ID" "$TOPIC" "$*" --type note - ;; - /check) - python3 scripts/agent_sync.py check - ;; - /resolve) - TOPIC="$1" - shift - python3 scripts/agent_sync.py resolve "$AGENT_ID" "$TOPIC" "$*" - ;; - /ping) - python3 scripts/agent_sync.py status | grep "\[" - ;; - /status) - python3 scripts/agent_sync.py status - ;; - *) - echo "Usage: ./scripts/macp [/status|/ping|/study|/broadcast|/summon|/handover|/note|/check|/resolve]" - ;; -esac diff --git a/zed-ai-tabs.sh b/zed-ai-tabs.sh deleted file mode 100755 index 1319338..0000000 --- a/zed-ai-tabs.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash -# ============================================================================== -# ai-tabs - Ultra Orchestrator -# Version: v1.0.0 -# License: MIT -# Author: Fu-Jie -# Description: Batch-launches and orchestrates multiple AI CLI tools as Tabs. -# ============================================================================== - -# 1. Single-Instance Lock -LOCK_FILE="/tmp/ai_terminal_launch.lock" -# If lock is less than 10 seconds old, another instance is running. Exit. -if [ -f "$LOCK_FILE" ]; then - LOCK_TIME=$(stat -f %m "$LOCK_FILE") - NOW=$(date +%s) - if (( NOW - LOCK_TIME < 10 )); then - echo "⚠️ Another launch in progress. Skipping to prevent duplicates." - exit 0 - fi -fi -touch "$LOCK_FILE" -trap 'rm -f "$LOCK_FILE"' EXIT - -# 2. Configuration & Constants -INIT_DELAY=4.5 -PASTE_DELAY=0.3 -CMD_CREATION_DELAY=0.3 -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PARENT_DIR="$(dirname "$SCRIPT_DIR")" - -# Search for .env -if [ -f "${SCRIPT_DIR}/.env" ]; then - ENV_FILE="${SCRIPT_DIR}/.env" -elif [ -f "${PARENT_DIR}/.env" ]; then - ENV_FILE="${PARENT_DIR}/.env" -fi - -# Supported Tools -SUPPORTED_TOOLS=( - "claude:--continue" - "opencode:--continue" - "gemini:--resume latest" - "copilot:--continue" - "iflow:--continue" - "kilo:--continue" -) - -FOUND_TOOLS_NAMES=() -FOUND_CMDS=() - -# 3. Part A: Load Manual Configuration -if [ -f "$ENV_FILE" ]; then - set -a; source "$ENV_FILE"; set +a - for var in $(compgen -v | grep '^TOOL_[0-9]' | sort -V); do - TPATH="${!var}" - if [ -x "$TPATH" ]; then - NAME=$(basename "$TPATH") - FLAG="--continue" - for item in "${SUPPORTED_TOOLS[@]}"; do - [[ "${item%%:*}" == "$NAME" ]] && FLAG="${item#*:}" && break - done - FOUND_TOOLS_NAMES+=("$NAME") - FOUND_CMDS+=("'$TPATH' $FLAG || '$TPATH' || exec \$SHELL") - fi - done -fi - -# 4. Part B: Automatic Tool Discovery -for item in "${SUPPORTED_TOOLS[@]}"; do - NAME="${item%%:*}" - FLAG="${item#*:}" - ALREADY_CONFIGURED=false - for configured in "${FOUND_TOOLS_NAMES[@]}"; do - [[ "$configured" == "$NAME" ]] && ALREADY_CONFIGURED=true && break - done - [[ "$ALREADY_CONFIGURED" == true ]] && continue - TPATH=$(which "$NAME" 2>/dev/null) - if [ -z "$TPATH" ]; then - SEARCH_PATHS=( - "/opt/homebrew/bin/$NAME" - "/usr/local/bin/$NAME" - "$HOME/.local/bin/$NAME" - "$HOME/bin/$NAME" - "$HOME/.$NAME/bin/$NAME" - "$HOME/.nvm/versions/node/*/bin/$NAME" - "$HOME/.npm-global/bin/$NAME" - "$HOME/.cargo/bin/$NAME" - ) - for p in "${SEARCH_PATHS[@]}"; do - for found_p in $p; do [[ -x "$found_p" ]] && TPATH="$found_p" && break 2; done - done - fi - if [ -n "$TPATH" ]; then - FOUND_TOOLS_NAMES+=("$NAME") - FOUND_CMDS+=("'$TPATH' $FLAG || '$TPATH' || exec \$SHELL") - fi -done - -NUM_FOUND=${#FOUND_CMDS[@]} -[[ "$NUM_FOUND" -eq 0 ]] && exit 1 - -# 5. Core Orchestration (Reset + Launch) -# Using Command Palette automation to avoid the need for manual shortcut binding. -AS_SCRIPT="tell application \"System Events\"\n" - -# Phase A: Creation (Using Command Palette to ensure it opens in Editor Area) -for ((i=1; i<=NUM_FOUND; i++)); do - AS_SCRIPT+=" keystroke \"p\" using {command down, shift down}\n" - AS_SCRIPT+=" delay 0.1\n" - # Ensure we are searching for the command. Using clipboard for speed and universal language support. - AS_SCRIPT+=" set the clipboard to \"workspace: new center terminal\"\n" - AS_SCRIPT+=" keystroke \"v\" using {command down}\n" - AS_SCRIPT+=" delay 0.1\n" - AS_SCRIPT+=" keystroke return\n" - AS_SCRIPT+=" delay $CMD_CREATION_DELAY\n" -done - -# Phase B: Warmup -AS_SCRIPT+=" delay $INIT_DELAY\n" - -# Phase C: Command Injection (Reverse) -for ((i=NUM_FOUND-1; i>=0; i--)); do - FULL_CMD="${FOUND_CMDS[$i]}" - CLEAN_CMD=$(echo "$FULL_CMD" | sed 's/"/\\"/g') - AS_SCRIPT+=" set the clipboard to \"$CLEAN_CMD\"\n" - AS_SCRIPT+=" delay 0.1\n" - AS_SCRIPT+=" keystroke \"v\" using {command down}\n" - AS_SCRIPT+=" delay $PASTE_DELAY\n" - AS_SCRIPT+=" keystroke return\n" - if [ $i -gt 0 ]; then - AS_SCRIPT+=" delay 0.5\n" - AS_SCRIPT+=" keystroke \"[\" using {command down, shift down}\n" - fi -done -AS_SCRIPT+="end tell" - -# Execute -echo -e "$AS_SCRIPT" | osascript -echo "✨ Ai tabs initialized successfully ($NUM_FOUND tools found)."