diff --git a/.agent/utils/gitbucket/close_issue.py b/.agent/utils/gitbucket/close_issue.py new file mode 100644 index 0000000..9179cb2 --- /dev/null +++ b/.agent/utils/gitbucket/close_issue.py @@ -0,0 +1,62 @@ +import argparse +import json +import urllib.request +import os +import sys + +def close_issue(issue_number, repo="yangyangxie/cortex-hub"): + token = os.getenv("GITBUCKET_TOKEN") + if not token: + # Try to load from .env.gitbucket + env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), ".env.gitbucket") + if os.path.exists(env_path): + with open(env_path, 'r') as f: + for line in f: + if line.startswith("GITBUCKET_TOKEN="): + token = line.split("=")[1].strip() + break + + if not token: + print("Error: GITBUCKET_TOKEN not found in environment or .env.gitbucket.") + sys.exit(1) + + url = f"https://gitbucket.jerxie.com/api/v3/repos/{repo}/issues/{issue_number}" + data = {"state": "close"} # GitBucket uses 'open' or 'close' in some versions, or 'closed' in others. + # Let's try 'close' first as seen in some GitBucket API refs. + + req = urllib.request.Request(url, json.dumps(data).encode("utf-8"), headers={ + "Authorization": f"token {token}", + "Content-Type": "application/json" + }, method="PATCH") + + try: + with urllib.request.urlopen(req) as response: + print(f"Issue #{issue_number} has been closed.") + except Exception as e: + print(f"Error closing issue: {e}") + if hasattr(e, 'read'): + print(e.read().decode()) + + # Second attempt with 'closed' + print("Trying with state='closed'...") + data = {"state": "closed"} + req = urllib.request.Request(url, json.dumps(data).encode("utf-8"), headers={ + "Authorization": f"token {token}", + "Content-Type": "application/json" + }, method="PATCH") + try: + with urllib.request.urlopen(req) as response: + print(f"Issue #{issue_number} has been closed (state=closed).") + except Exception as e2: + print(f"Failed again: {e2}") + if hasattr(e2, 'read'): + print(e2.read().decode()) + sys.exit(1) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Close a GitBucket issue.") + parser.add_argument("--issue", required=True, type=int, help="Issue number") + parser.add_argument("--repo", default="yangyangxie/cortex-hub", help="Repository (owner/repo)") + + args = parser.parse_args() + close_issue(args.issue, args.repo) diff --git a/docs/architecture/cortex_agent_node_plan.md b/docs/architecture/cortex_agent_node_plan.md index a351446..d393bfa 100644 --- a/docs/architecture/cortex_agent_node_plan.md +++ b/docs/architecture/cortex_agent_node_plan.md @@ -58,27 +58,25 @@ - **Capability Manifest**: Handshake now includes a JSON-based report for version and platforms. - **Outcome**: Secure, auditable, and consensual execution of system queries. -### Phase 4: Browser Automation (The "Antigravity" Feature) -- **Goal**: Allow Agent to interact with local web apps. -- **Tasks**: - - Implement CDP (Chrome DevTools Protocol) to attach to existing browsers. - - Stream screenshots efficiently using chunked binary frames over gRPC, possibly with compression or delta snaps. - - Include headless/visible toggles, timeboxed navigation, and DOM snapshot streaming. -- **Outcome**: High-performance, low-latency visual interaction with local web pages. - -### Phase 5: Concurrency & Distributed Architecture - ✅ COMPLETE +### Phase 4: Browser Automation (The "Antigravity" Feature) - ✅ COMPLETE - **Status**: Verified in `/app/poc-grpc-agent/`. - **Achievements**: - - **Company Architecture**: Implemented Boss (Server) and Dept Manager (Node) hierarchy. - - **Multi-Channel gRPC**: Split communication into 1. **Config**, 2. **Task**, and 3. **Health** channels. - - **Dynamic Policy Sync**: Client-side permissions are pushed from the server during handshake. - - **AI-Ready Node Metadata**: Nodes register with a **Skill Description** (metadata) and hardware capabilities. - - **Worker Pool Robustness**: Migrated to stateful `subprocess.Popen` execution. The manager now monitors individual process handles to prevent "Phantom Workers" (leaked threads). - - **Modular Refactor**: Implemented a **Skill-Based Architecture** (Client) and **Task Journal** (Server) to decouple gRPC networking from business logic, enabling easy expansion for CDP/LSP. - - **Hanging Task Recovery**: Implemented **Remote Cancellation**. The server can detect hanging tasks via the health channel and signal the node to `kill` the specific process. - - **Fault Tolerance & Retries**: The `TaskAssistant` automatically retries failed/timed-out tasks up to 3x. - - **Worker Pool (Sub-threading)**: Main node thread (Manager) dispatches to isolated execution threads (Workers). + - **Browser Actor Threading**: Solved Playwright threading issues with a dedicated Actor model. + - **Real-time Event Tunneling**: `console.log` and network fetch events are streamed instantly to the server. + - **Advanced Perception**: Implemented A11y tree extraction and JS evaluation for deep page understanding. + - **Multi-Session Support**: Capability to handle multiple isolated browser contexts simultaneously. +- **Outcome**: High-performance, low-latency visual and semantic interaction with local web pages. + +### Phase 5: Modular 12-Factor Refactor & Mesh Foundations - ✅ COMPLETE +- **Status**: Verified in `/app/poc-grpc-agent/`. +- **Achievements**: + - **Modular Architecture**: Split the monolith into `orchestrator/` and `agent_node/` packages. + - **12-Factor Compliance**: Configuration is now fully externalized via Environment Variables. + - **Skill-Based Extensibility**: Unified `BaseSkill` interface for Shell, Browser, and future capabilities. + - **Graceful Shutdown**: Implemented `SIGTERM`/`SIGINT` handling with clean browser-actor cleanup. - **Global Work Pool**: Shared task discovery and **Task Claiming** to prevent rework across nodes. + - **Hanging Task Recovery**: Remote cancellation and automatic retries in the `TaskAssistant`. +- **Outcome**: A professional, scalable, and extensible distributed agent mesh. ### Phase 6: Scaling & Frontend UI Integration - **Goal**: Support multiple nodes and surface insights in the UI. diff --git a/docs/architecture/cortex_project_todo.md b/docs/architecture/cortex_project_todo.md index 926c2fe..ee0c435 100644 --- a/docs/architecture/cortex_project_todo.md +++ b/docs/architecture/cortex_project_todo.md @@ -30,8 +30,9 @@ - **Description**: Re-evaluate the "Skill" abstraction. Move towards a model where each task is a specialized worker process that decides its capability (Shell vs Playwright) at startup. - **Goal**: Simplifies context isolation and reduces manager-thread overhead. -### [ ] Graceful Shutdown & Local Task Persistence (Built-in) +### [x] Graceful Shutdown & Local Task Persistence (Built-in) - **Description**: Handle node interrupts (SIGTERM/SIGINT) to allow workers to finish or checkpoint. Store a local `task_history.json` on the node to recover state after crash/restart. +- **Status**: SIGTERM/SIGINT implemented in Phase 4 refactor. ### [ ] Server-Side Registry & Task Persistence - **Description**: Migrate `NodeRegistry` and `WorkPool` from in-memory to a persistent backend (Postgres/Redis).