diff --git a/.gitattributes b/.gitattributes index c3482579..75d81ed5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,2 @@ -libs/openagent/sandbox/vm/setup/*.sh text eol=lf -libs/openagent/sandbox/vm/setup/steps/*.sh text eol=lf -libs/hexagent/sandbox/vm/setup/*.sh text eol=lf -libs/hexagent/sandbox/vm/setup/steps/*.sh text eol=lf -libs/openagent/sandbox/vm/wsl/prebuilt/openagent-prebuilt.tar filter=lfs diff=lfs merge=lfs -text +libs/uniharness/sandbox/vm/setup/*.sh text eol=lf +libs/uniharness/sandbox/vm/setup/steps/*.sh text eol=lf diff --git a/.github/images/logo.svg b/.github/images/logo.svg index d8267d54..83197e16 100644 --- a/.github/images/logo.svg +++ b/.github/images/logo.svg @@ -1,4 +1,4 @@ - + @@ -39,5 +39,5 @@ -HexAgent +UniHarness diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce3b8f12..b91e5ade 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,10 +22,10 @@ jobs: matrix: include: # Core package - - working-directory: "libs/hexagent" + - working-directory: "libs/uniharness" python-version: "3.11" # Other packages in monorepo - # - working-directory: "libs/hexagent-cli" + # - working-directory: "libs/uniharness-cli" # python-version: "3.11" fail-fast: false uses: ./.github/workflows/_lint.yml @@ -38,16 +38,16 @@ jobs: matrix: include: # Core package - - working-directory: "libs/hexagent" + - working-directory: "libs/uniharness" python-version: "3.11" - - working-directory: "libs/hexagent" + - working-directory: "libs/uniharness" python-version: "3.12" - - working-directory: "libs/hexagent" + - working-directory: "libs/uniharness" python-version: "3.13" # Other packages - # - working-directory: "libs/hexagent-cli" + # - working-directory: "libs/uniharness-cli" # python-version: "3.11" - # - working-directory: "libs/hexagent-cli" + # - working-directory: "libs/uniharness-cli" # python-version: "3.13" fail-fast: false uses: ./.github/workflows/_test.yml @@ -59,7 +59,7 @@ jobs: strategy: matrix: include: - - working-directory: "libs/hexagent" + - working-directory: "libs/uniharness" python-version: "3.11" fail-fast: false uses: ./.github/workflows/_integration_test.yml diff --git a/.gitignore b/.gitignore index 6c9f2a64..cbdd0579 100644 --- a/.gitignore +++ b/.gitignore @@ -215,14 +215,14 @@ __marimo__/ /tmp/ */tmp/ -# HexAgent Sandbox +# UniHarness Sandbox mounts/ # Git worktrees .trees/ # Electron build artifact -libs/hexagent_demo/electron/dist.zip +libs/uniharness_demo/electron/dist.zip # Vite dev-server cache **/.vite/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d4128900..71f27873 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,9 +17,9 @@ repos: - repo: local hooks: - - id: hexagent - name: format and lint hexagent + - id: uniharness + name: format and lint uniharness language: system - entry: make -C libs/hexagent format lint - files: ^libs/hexagent/ + entry: make -C libs/uniharness format lint + files: ^libs/uniharness/ pass_filenames: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd33cab7..a4037843 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing to HexAgent +# Contributing to UniHarness -Thank you for your interest in contributing to HexAgent! We believe agent infrastructure should be open, vendor-neutral, and community-driven — and every contribution moves that forward. +Thank you for your interest in contributing to UniHarness! We believe agent infrastructure should be open, vendor-neutral, and community-driven — and every contribution moves that forward. Whether you're fixing a typo, adding a new tool, implementing a computer backend, or improving documentation, you're helping build the agent harness the community needs. @@ -16,11 +16,11 @@ Whether you're fixing a typo, adding a new tool, implementing a computer backend ```bash # Clone the repository -git clone https://github.com/an7tang/hexagent.git -cd hexagent +git clone https://github.com/UnicomAI/UniHarness.git +cd uniharness # Set up the core library -cd libs/hexagent +cd libs/uniharness uv sync --group test # Verify everything works @@ -31,15 +31,15 @@ make test ### Project Structure ``` -hexagent/ +uniharness/ ├── libs/ -│ ├── hexagent/ # Core agent harness library -│ │ ├── hexagent/ # Package source +│ ├── uniharness/ # Core agent harness library +│ │ ├── uniharness/ # Package source │ │ ├── tests/ # Unit + integration tests │ │ ├── sandbox/ # Docker/VM sandbox configs │ │ ├── Makefile # Build targets │ │ └── pyproject.toml # Package config -│ └── hexagent_demo/ # Demo desktop application +│ └── uniharness_demo/ # Demo desktop application │ ├── backend/ # FastAPI backend │ ├── frontend/ # React frontend │ └── electron/ # Electron shell @@ -52,7 +52,7 @@ hexagent/ ### Running Tests ```bash -cd libs/hexagent +cd libs/uniharness make test # Unit tests with coverage make integration_test # Integration tests (requires API keys) @@ -94,14 +94,14 @@ pre-commit install - Test behavior, not implementation details - Prefer testing public APIs over internal functions - Descriptive test names: `test___` -- Unit tests in `tests/unit_tests/` — mirror the `hexagent/` directory structure +- Unit tests in `tests/unit_tests/` — mirror the `uniharness/` directory structure - Integration tests in `tests/integration_tests/` ## Making Changes ### Before You Start -1. Check existing [issues](https://github.com/an7tang/hexagent/issues) to see if someone is already working on it +1. Check existing [issues](https://github.com/UnicomAI/UniHarness/issues) to see if someone is already working on it 2. For significant changes, open an issue first to discuss the approach 3. Fork the repository and create a feature branch @@ -116,7 +116,7 @@ pre-commit install 3. Ensure all checks pass: ```bash - cd libs/hexagent + cd libs/uniharness make format make lint make test @@ -151,31 +151,31 @@ When contributing, keep these principles in mind: ### Framework-Agnostic Core -The core library (`hexagent/`) is framework-agnostic — LangChain integration lives in `hexagent/langchain/`. Don't introduce LangChain imports outside of that directory. +The core library (`uniharness/`) is framework-agnostic — LangChain integration lives in `uniharness/langchain/`. Don't introduce LangChain imports outside of that directory. ### Where to Contribute | Area | Good for | Location | |------|----------|----------| -| New tools | Adding capabilities to agents | `hexagent/tools/` | -| Computer implementations | New execution environments | `hexagent/computer/` | -| Web providers | New search/fetch backends | `hexagent/tools/web/providers/` | -| MCP improvements | Protocol support | `hexagent/mcp/` | -| Prompt fragments | Better agent instructions | `hexagent/prompts/fragments/` | -| Demo features | UI/UX improvements | `libs/hexagent_demo/` | +| New tools | Adding capabilities to agents | `uniharness/tools/` | +| Computer implementations | New execution environments | `uniharness/computer/` | +| Web providers | New search/fetch backends | `uniharness/tools/web/providers/` | +| MCP improvements | Protocol support | `uniharness/mcp/` | +| Prompt fragments | Better agent instructions | `uniharness/prompts/fragments/` | +| Demo features | UI/UX improvements | `libs/uniharness_demo/` | | Tests | Improving coverage | `tests/` | | Documentation | Clarity and examples | `README.md`, `libs/*/README.md` | ## Good First Issues -New to the project? Look for issues tagged [`good first issue`](https://github.com/an7tang/hexagent/labels/good%20first%20issue). These are scoped to be approachable without deep knowledge of the codebase. +New to the project? Look for issues tagged [`good first issue`](https://github.com/UnicomAI/UniHarness/labels/good%20first%20issue). These are scoped to be approachable without deep knowledge of the codebase. ## Reporting Issues -- Use [GitHub Issues](https://github.com/an7tang/hexagent/issues) +- Use [GitHub Issues](https://github.com/UnicomAI/UniHarness/issues) - Include steps to reproduce, expected behavior, and actual behavior - For bugs, include your Python version, OS, and relevant dependency versions ## Questions? -Open a [Discussion](https://github.com/an7tang/hexagent/discussions) for questions, ideas, or feedback that don't fit neatly into an issue. +Open a [Discussion](https://github.com/UnicomAI/UniHarness/discussions) for questions, ideas, or feedback that don't fit neatly into an issue. diff --git a/README.md b/README.md index f355a053..b9bdca0c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- HexAgent + UniHarness

@@ -7,35 +7,35 @@

- CI + CI Python 3.11+ License: MIT

--- -**HexAgent** is an open-source **agent harness**: the production runtime that gives any LLM a fully-equipped computer — terminal, filesystem, and shell — to complete tasks autonomously. +**UniHarness** is an open-source **agent harness**: the production runtime that gives any LLM a fully-equipped computer — terminal, filesystem, and shell — to complete tasks autonomously. -Unlike every other agent framework, HexAgent **separates the agent runtime from the computer it operates on**. Your agent gets a sandboxed machine; your runtime keeps its API keys, config, and source code private. +Unlike every other agent framework, UniHarness **separates the agent runtime from the computer it operates on**. Your agent gets a sandboxed machine; your runtime keeps its API keys, config, and source code private. > **Why "harness" and not "framework"?** A framework gives you building blocks and says "assemble your own agent." A harness gives the agent a fully equipped runtime — tools, context management, safety, execution environments — so you focus on *what* the agent does, not *how* it executes. ([Read more](#agent-harness-vs-agent-framework)) ## The Computer Layer -In Claude Code, Codex, and every LangChain agent, the agent runtime and the computer it controls are the same process. The agent can read its own source code, config files, and API keys. HexAgent's `Computer` protocol makes this separation explicit and pluggable — swap execution environments without changing a line of agent code. +In Claude Code, Codex, and every LangChain agent, the agent runtime and the computer it controls are the same process. The agent can read its own source code, config files, and API keys. UniHarness's `Computer` protocol makes this separation explicit and pluggable — swap execution environments without changing a line of agent code. ```python -from hexagent import create_agent -from hexagent.computer import LocalNativeComputer, LocalVM, RemoteE2BComputer +from uniharness import create_agent +from uniharness.computer import LocalNativeComputer, LocalVM, RemoteE2BComputer # Development — run on your machine -agent = await create_agent(model="anthropic/claude-sonnet-4-20250514", computer=LocalNativeComputer()) +agent = await create_agent(model="openai:gpt-5.5", computer=LocalNativeComputer()) # Security-sensitive — sandboxed VM (Lima on macOS, WSL on Windows) -agent = await create_agent(model="anthropic/claude-sonnet-4-20250514", computer=LocalVM()) +agent = await create_agent(model="openai:gpt-5.5", computer=LocalVM()) # Production / multi-tenant — isolated cloud sandbox -agent = await create_agent(model="anthropic/claude-sonnet-4-20250514", computer=RemoteE2BComputer(api_key="...")) +agent = await create_agent(model="openai:gpt-5.5", computer=RemoteE2BComputer(api_key="...")) ``` ``` @@ -64,19 +64,19 @@ Implement the `Computer` protocol to add your own — Docker, Kubernetes pods, o ## Quick Start ```bash -pip install hexagent +pip install uniharness ``` ### Minimal example ```python import asyncio -from hexagent import create_agent -from hexagent.computer import LocalNativeComputer +from uniharness import create_agent +from uniharness.computer import LocalNativeComputer async def main(): async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", # or any LLM + model="openai:gpt-5.5", # or any LLM computer=LocalNativeComputer(), ) as agent: result = await agent.ainvoke({ @@ -90,12 +90,12 @@ asyncio.run(main()) ### Use any model ```python -from hexagent import create_agent, ModelProfile -from hexagent.computer import LocalNativeComputer +from uniharness import create_agent, ModelProfile +from uniharness.computer import LocalNativeComputer # DeepSeek, Qwen, Llama, Mistral — anything OpenAI-compatible model = ModelProfile( - model="deepseek/deepseek-chat", + model="deepseek:deepseek-v4-flash", base_url="https://api.deepseek.com/v1", api_key="your-key", context_window=64000, @@ -107,11 +107,11 @@ agent = await create_agent(model=model, computer=LocalNativeComputer()) ### Add subagents, MCP servers, web tools ```python -from hexagent import create_agent, AgentDefinition -from hexagent.computer import LocalNativeComputer +from uniharness import create_agent, AgentDefinition +from uniharness.computer import LocalNativeComputer agent = await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), # Subagents for parallel specialized work agents={ @@ -134,17 +134,17 @@ agent = await create_agent( ### Run in a cloud sandbox ```python -from hexagent import create_agent -from hexagent.computer import RemoteE2BComputer +from uniharness import create_agent +from uniharness.computer import RemoteE2BComputer # Fully isolated cloud execution — no local risk agent = await create_agent( - model="openai/gpt-4o", + model="openai:gpt-4o", computer=RemoteE2BComputer(api_key="your-e2b-key"), ) ``` -See [`libs/hexagent/README.md`](libs/hexagent/README.md) for the full API reference. +See [`libs/uniharness/README.md`](libs/uniharness/README.md) for the full API reference. ## What Can You Build? @@ -157,7 +157,7 @@ One harness powers four product types — no other agent SDK does this: | **Cowork** | Desktop agent that works on your local files, folders, and apps — completing knowledge work tasks autonomously while you steer | [Claude Cowork](https://www.anthropic.com/product/claude-cowork) | | **Autonomous Agent** | Headless agent that runs tasks end-to-end without supervision | [OpenClaw](https://github.com/openclaw/openclaw), [Devin](https://devin.ai/) | -The [`hexagent_demo`](libs/hexagent_demo/) app ships with ready-to-use **Chat** and **Cowork** modes as concrete examples. +The [`uniharness_demo`](libs/uniharness_demo/) app ships with ready-to-use **Chat** and **Cowork** modes as concrete examples. ## Features @@ -178,9 +178,9 @@ The [`hexagent_demo`](libs/hexagent_demo/) app ships with ready-to-use **Chat** - **Web providers** — Pluggable search (Tavily/Brave) and fetch (Jina/Firecrawl) backends - **Composable, not magical** — Small modules with explicit I/O. No hidden state. Every piece is testable and replaceable. -### How HexAgent Compares +### How UniHarness Compares -| | HexAgent | Claude Agent SDK | LangChain Deep Agents | +| | UniHarness | Claude Agent SDK | LangChain Deep Agents | |---|---|---|---| | **Open source** | MIT | MIT | MIT | | **Model-agnostic** | Any LLM | Claude only | Any LLM | @@ -243,23 +243,23 @@ The AI agent ecosystem has converged on a [clear taxonomy](https://blog.langchai | **What it is** | Building blocks (tools, prompts, memory) | Durable execution engine | Complete agent operating system | | **Analogy** | A toolkit | A job scheduler | An OS for the agent | | **You build** | Everything from scratch | Orchestration logic | Your agent's purpose | -| **Examples** | LangChain, CrewAI, Semantic Kernel | LangGraph, Temporal | HexAgent, Claude Code, OpenHands | +| **Examples** | LangChain, CrewAI, Semantic Kernel | LangGraph, Temporal | UniHarness, Claude Code, OpenHands | A framework says: *"Here are components. Assemble your agent."* A harness says: *"Here is a fully equipped computer. Tell the agent what to do."* -HexAgent is a harness you can embed as a library — giving you the batteries-included runtime of products like Claude Code, with the flexibility to build any agent product you want. +UniHarness is a harness you can embed as a library — giving you the batteries-included runtime of products like Claude Code, with the flexibility to build any agent product you want. ## Project Structure | Package | Description | |---------|-------------| -| [`libs/hexagent`](libs/hexagent/) | **Core framework** — the agent harness library ([API docs](libs/hexagent/README.md)) | -| [`libs/hexagent_demo`](libs/hexagent_demo/) | **Demo app** — desktop Chat + Cowork built on the framework ([setup guide](libs/hexagent_demo/README.md)) | +| [`libs/uniharness`](libs/uniharness/) | **Core framework** — the agent harness library ([API docs](libs/uniharness/README.md)) | +| [`libs/uniharness_demo`](libs/uniharness_demo/) | **Demo app** — desktop Chat + Cowork built on the framework ([setup guide](libs/uniharness_demo/README.md)) | ``` -libs/hexagent/hexagent/ +libs/uniharness/uniharness/ ├── computer/ # Computer protocol — local, VM, or cloud (E2B) execution ├── harness/ # Runtime augmentation: environment, permissions, skills, reminders ├── tools/ # Built-in tools: CLI, web, subagents, skills, todos diff --git a/SECURITY.md b/SECURITY.md index 0769f86b..a3e7fc69 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,10 +1,10 @@ # Security Policy -HexAgent agents execute shell commands and access filesystems — security is a core architectural concern, not an afterthought. +UniHarness agents execute shell commands and access filesystems — security is a core architectural concern, not an afterthought. ## Reporting a Vulnerability -If you discover a security vulnerability in HexAgent, please report it responsibly. +If you discover a security vulnerability in UniHarness, please report it responsibly. **Do not open a public GitHub issue for security vulnerabilities.** @@ -24,24 +24,24 @@ Include: ## Scope -This policy applies to the HexAgent codebase hosted at [github.com/an7tang/hexagent](https://github.com/an7tang/hexagent). +This policy applies to the UniHarness codebase hosted at [github.com/UnicomAI/UniHarness](https://github.com/UnicomAI/UniHarness). ### In Scope -- Vulnerabilities in the `hexagent` library code -- Security issues in the `hexagent_demo` application +- Vulnerabilities in the `uniharness` library code +- Security issues in the `uniharness_demo` application - Sandbox escape vulnerabilities in Computer implementations - Injection vulnerabilities in tool execution (command injection, path traversal, etc.) ### Out of Scope - Vulnerabilities in third-party dependencies (report these to the respective maintainers) -- Issues that require physical access to the machine running HexAgent +- Issues that require physical access to the machine running UniHarness - Social engineering attacks ## Security Considerations -HexAgent agents execute shell commands and file operations. When deploying HexAgent: +UniHarness agents execute shell commands and file operations. When deploying UniHarness: - **Use sandboxed execution environments** (E2B cloud sandbox or Lima VMs) for untrusted workloads - **Never expose the agent API to the public internet** without authentication diff --git a/libs/hexagent/hexagent/__init__.py b/libs/hexagent/hexagent/__init__.py deleted file mode 100644 index e9eb59fe..00000000 --- a/libs/hexagent/hexagent/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -"""HexAgent package. - -HexAgent is an Agent SDK (supporting OpenAI-compatible LLMs) similar to -Anthropic's Claude Agent SDK. - -Core Philosophy: Give agents a CLI-based computer, allowing them to work -like humans do. -""" - -from hexagent.harness.definition import AgentDefinition -from hexagent.harness.model import ModelProfile -from hexagent.langchain import Agent, create_agent - -__all__ = [ - "Agent", - "AgentDefinition", - "ModelProfile", - "create_agent", -] diff --git a/libs/hexagent/hexagent/computer/__init__.py b/libs/hexagent/hexagent/computer/__init__.py deleted file mode 100644 index 288f9615..00000000 --- a/libs/hexagent/hexagent/computer/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Computer abstractions for HexAgent.""" - -from hexagent.computer.base import Computer, ExecutionMetadata, Mount -from hexagent.computer.local import LocalNativeComputer, LocalVM -from hexagent.computer.remote.e2b import RemoteE2BComputer - -__all__ = [ - "Computer", - "ExecutionMetadata", - "LocalNativeComputer", - "LocalVM", - "Mount", - "RemoteE2BComputer", -] diff --git a/libs/hexagent/hexagent/computer/local/__init__.py b/libs/hexagent/hexagent/computer/local/__init__.py deleted file mode 100644 index b33cfe23..00000000 --- a/libs/hexagent/hexagent/computer/local/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Local computer implementations.""" - -import sys - -from hexagent.computer.local.native import LocalNativeComputer - -if sys.platform == "win32": - from hexagent.computer.local.vm_win import LocalVM -else: - from hexagent.computer.local.vm import LocalVM - -__all__ = ["LocalNativeComputer", "LocalVM"] diff --git a/libs/hexagent/hexagent/langchain/__init__.py b/libs/hexagent/hexagent/langchain/__init__.py deleted file mode 100644 index 0ee5d98e..00000000 --- a/libs/hexagent/hexagent/langchain/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -"""LangChain integration for HexAgent. - -This module provides adapters and utilities for integrating HexAgent's -framework-agnostic tools and computer abstractions with LangChain. - -If you delete this directory, all core HexAgent functionality -(tools, computer, types, prompts) should still work independently. - -Main exports: -- Agent: HexAgent agent with managed resources -- create_agent: Create an HexAgent agent using LangChain -- to_langchain_tool: Convert BaseAgentTool to LangChain StructuredTool -- LangChainSubagentRunner: Executes subagents with isolated context -""" - -from hexagent.langchain.adapter import to_langchain_tool -from hexagent.langchain.agent import Agent, create_agent -from hexagent.langchain.subagent import LangChainSubagentRunner - -__all__ = [ - "Agent", - "LangChainSubagentRunner", - "create_agent", - "to_langchain_tool", -] diff --git a/libs/hexagent/hexagent/prompts/fragments/__init__.py b/libs/hexagent/hexagent/prompts/fragments/__init__.py deleted file mode 100644 index 106fc89c..00000000 --- a/libs/hexagent/hexagent/prompts/fragments/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Markdown prompt fragments loaded by :mod:`hexagent.prompts.content`.""" diff --git a/libs/hexagent/hexagent/tools/task/__init__.py b/libs/hexagent/hexagent/tools/task/__init__.py deleted file mode 100644 index 4f3a70b7..00000000 --- a/libs/hexagent/hexagent/tools/task/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Framework-agnostic task tools. - -These tools operate against a :class:`~hexagent.tasks.TaskRegistry` -and are assembled by the agent factory. -""" - -from hexagent.tools.task.agent import AgentTool -from hexagent.tools.task.output import TaskOutputTool -from hexagent.tools.task.stop import TaskStopTool - -__all__ = [ - "AgentTool", - "TaskOutputTool", - "TaskStopTool", -] diff --git a/libs/hexagent/tests/unit_tests/mcp/__init__.py b/libs/hexagent/tests/unit_tests/mcp/__init__.py deleted file mode 100644 index b34fd4c1..00000000 --- a/libs/hexagent/tests/unit_tests/mcp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Unit tests for hexagent.mcp module.""" diff --git a/libs/hexagent_demo/backend/hexagent_api/__init__.py b/libs/hexagent_demo/backend/hexagent_api/__init__.py deleted file mode 100644 index 0ee54483..00000000 --- a/libs/hexagent_demo/backend/hexagent_api/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""HexAgent API backend package.""" diff --git a/libs/hexagent_demo/electron/resources/installer.nsh b/libs/hexagent_demo/electron/resources/installer.nsh deleted file mode 100644 index 7609d096..00000000 --- a/libs/hexagent_demo/electron/resources/installer.nsh +++ /dev/null @@ -1,3 +0,0 @@ -!macro customUnInstall - RMDir /r "$PROFILE\.hexagent" -!macroend diff --git a/libs/hexagent/AGENTS.md b/libs/uniharness/AGENTS.md similarity index 85% rename from libs/hexagent/AGENTS.md rename to libs/uniharness/AGENTS.md index 1da93f88..d9aaa839 100644 --- a/libs/hexagent/AGENTS.md +++ b/libs/uniharness/AGENTS.md @@ -1,6 +1,6 @@ ## Project Overview -**HexAgent** is a general-purpose agent harness that **gives LLM agents access to a computer via the terminal** to complete tasks the way humans do. +**UniHarness** is a general-purpose agent harness that **gives LLM agents access to a computer via the terminal** to complete tasks the way humans do. ### Architecture Principles @@ -20,7 +20,7 @@ Backward compatibility is not a concern. Clean architecture and code quality alw ## Instructions on Helping Human - When asked for architecture or design work, prioritize deep conceptual analysis and design philosophy BEFORE jumping to concrete code or file structures. Ask clarifying questions about constraints, trade-offs, and design principles first. Only move to implementation details when explicitly asked. -- When discussing architecture for HexAgent, maintain awareness that the project values: framework-agnostic design, clean patterns, and separation of concerns. Avoid coupling to specific LLM providers or frameworks (except integration dir, e.g. langchain/). +- When discussing architecture for UniHarness, maintain awareness that the project values: framework-agnostic design, clean patterns, and separation of concerns. Avoid coupling to specific LLM providers or frameworks (except integration dir, e.g. langchain/). ## Commands @@ -53,7 +53,7 @@ uv run pytest tests/unit_tests/path/to/test_file.py::test_name -v # Single test ``` **Test Organization**: -- Unit tests: `tests/unit_tests/` — mirrors `hexagent/` structure +- Unit tests: `tests/unit_tests/` — mirrors `uniharness/` structure - Integration tests: `tests/integration_tests/` **Writing Tests**: diff --git a/libs/hexagent/CLAUDE.md b/libs/uniharness/CLAUDE.md similarity index 100% rename from libs/hexagent/CLAUDE.md rename to libs/uniharness/CLAUDE.md diff --git a/libs/hexagent/Makefile b/libs/uniharness/Makefile similarity index 77% rename from libs/hexagent/Makefile rename to libs/uniharness/Makefile index b8a8aa3b..18146956 100644 --- a/libs/hexagent/Makefile +++ b/libs/uniharness/Makefile @@ -1,7 +1,7 @@ PYTHON_FILES=. MYPY_CACHE=.mypy_cache lint format: PYTHON_FILES=. -lint_diff format_diff: PYTHON_FILES=$(shell git diff --relative=libs/hexagent --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') +lint_diff format_diff: PYTHON_FILES=$(shell git diff --relative=libs/uniharness --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$') lint_package: PYTHON_FILES=. lint_tests: PYTHON_FILES=tests @@ -19,7 +19,7 @@ format format_diff: [ "$(PYTHON_FILES)" = "" ] || uv run --all-groups ruff check --fix $(PYTHON_FILES) test: - uv run pytest tests/unit_tests --cov=hexagent --cov-report=term-missing + uv run pytest tests/unit_tests --cov=uniharness --cov-report=term-missing integration_test: - uv run pytest tests/integration_tests --cov=hexagent --cov-report=term-missing + uv run pytest tests/integration_tests --cov=uniharness --cov-report=term-missing diff --git a/libs/hexagent/README.md b/libs/uniharness/README.md similarity index 88% rename from libs/hexagent/README.md rename to libs/uniharness/README.md index 7a2e9dd6..69b9710f 100644 --- a/libs/hexagent/README.md +++ b/libs/uniharness/README.md @@ -1,6 +1,6 @@ -# HexAgent +# UniHarness -The core Python library for building computer-using AI agents. HexAgent is an **agent harness** — the complete runtime layer that gives any LLM **access to a computer via the terminal**, completing tasks the way developers do. +The core Python library for building computer-using AI agents. UniHarness is an **agent harness** — the complete runtime layer that gives any LLM **access to a computer via the terminal**, completing tasks the way developers do. **Vendor-agnostic.** Works with Anthropic, OpenAI, DeepSeek, open-weight models via OpenRouter, or any OpenAI-compatible endpoint. The model is a parameter — swap it without changing your agent. @@ -9,7 +9,7 @@ The core Python library for building computer-using AI agents. HexAgent is an ** ## Installation ```bash -pip install hexagent +pip install uniharness ``` **Requirements:** Python 3.11+ @@ -17,9 +17,9 @@ pip install hexagent ### Optional dependencies ```bash -pip install hexagent[langsmith] # LangSmith tracing -pip install hexagent[braintrust] # Braintrust observability -pip install hexagent[observe] # Both +pip install uniharness[langsmith] # LangSmith tracing +pip install uniharness[braintrust] # Braintrust observability +pip install uniharness[observe] # Both ``` ## Quick Start @@ -28,12 +28,12 @@ pip install hexagent[observe] # Both ```python import asyncio -from hexagent import create_agent -from hexagent.computer import LocalNativeComputer +from uniharness import create_agent +from uniharness.computer import LocalNativeComputer async def main(): async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), ) as agent: result = await agent.ainvoke({ @@ -47,11 +47,11 @@ asyncio.run(main()) ### Using any OpenAI-compatible model ```python -from hexagent import create_agent, ModelProfile -from hexagent.computer import LocalNativeComputer +from uniharness import create_agent, ModelProfile +from uniharness.computer import LocalNativeComputer model = ModelProfile( - model="deepseek/deepseek-chat", + model="deepseek:deepseek-v4-flash", base_url="https://api.deepseek.com/v1", api_key="your-key", context_window=64000, @@ -68,7 +68,7 @@ async with await create_agent( ```python async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), ) as agent: async for event in agent.astream_events( @@ -82,19 +82,19 @@ async with await create_agent( ### Custom computer environment ```python -from hexagent import create_agent -from hexagent.computer import LocalNativeComputer, RemoteE2BComputer +from uniharness import create_agent +from uniharness.computer import LocalNativeComputer, RemoteE2BComputer # Local execution async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), ) as agent: ... # Cloud sandbox via E2B async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=RemoteE2BComputer(api_key="your-e2b-key"), ) as agent: ... @@ -103,8 +103,8 @@ async with await create_agent( ### Defining subagents ```python -from hexagent import create_agent, AgentDefinition -from hexagent.computer import LocalNativeComputer +from uniharness import create_agent, AgentDefinition +from uniharness.computer import LocalNativeComputer agents = { "researcher": AgentDefinition( @@ -116,7 +116,7 @@ agents = { } async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), agents=agents, ) as agent: @@ -127,7 +127,7 @@ async with await create_agent( ```python async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), mcp_servers={ "github": {"type": "http", "url": "https://mcp.github.com/mcp"}, @@ -145,7 +145,7 @@ async with await create_agent( ```python async with await create_agent( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", computer=LocalNativeComputer(), search_provider=("tavily", "your-tavily-key"), fetch_provider=("jina", "your-jina-key"), @@ -181,14 +181,14 @@ async def create_agent( | Parameter | Type | Description | |-----------|------|-------------| -| `model` | `str \| BaseChatModel \| ModelProfile` | LLM specifier string (e.g. `"anthropic/claude-sonnet-4-20250514"`), a pre-configured LangChain model, or a `ModelProfile` with context window config. | +| `model` | `str \| BaseChatModel \| ModelProfile` | LLM specifier string (e.g. `"openai:gpt-5.5"`), a pre-configured LangChain model, or a `ModelProfile` with context window config. | | `computer` | `Computer` | Execution environment for CLI tools. Use `LocalNativeComputer()` for local or `RemoteE2BComputer()` for cloud sandbox. | | `fast_model` | same as `model` | Optional lightweight model for subagents marked with `model="fast"`. | | `mcp_servers` | `Mapping[str, McpServerConfig]` | Dict mapping server names to MCP server configs. Supports `"stdio"`, `"sse"`, and `"http"` transports. | | `agents` | `Mapping[str, AgentDefinition]` | Dict mapping subagent type names to their definitions. Parent agent spawns these via the `Agent` tool. | | `search_provider` | `SearchProvider` | Web search backend. Pass `("tavily", api_key)` or `("brave", api_key)` for convenience. | | `fetch_provider` | `FetchProvider` | Web fetch backend. Pass `("jina", api_key)` or `("firecrawl", api_key)` for convenience. | -| `skill_paths` | `Sequence[str]` | Directories to scan for SKILL.md-based skills. Defaults to `/mnt/skills`, `~/.hexagent/skills`, `.hexagent/skills`. | +| `skill_paths` | `Sequence[str]` | Directories to scan for SKILL.md-based skills. Defaults to `/mnt/skills`, `~/.uniharness/skills`, `.uniharness/skills`. | | `system_prompt` | `str` | Override the auto-composed system prompt entirely. | | `reminders` | `Sequence[Reminder]` | Dynamic message annotation rules evaluated on every turn. | | `extra_tools` | `Sequence[BaseAgentTool]` | Additional tool instances appended to the built-in set. | @@ -216,7 +216,7 @@ Configuration for an LLM with context window management. ```python ModelProfile( - model="anthropic/claude-sonnet-4-20250514", + model="openai:gpt-5.5", context_window=200000, # Max tokens compaction_threshold=160000, # When to trigger context compaction (default: 75% of context_window) api_key="...", # Optional: provider API key @@ -259,8 +259,8 @@ AgentDefinition( Extend `BaseAgentTool` to create your own: ```python -from hexagent.tools import BaseAgentTool -from hexagent.types import ToolResult +from uniharness.tools import BaseAgentTool +from uniharness.types import ToolResult from pydantic import BaseModel, Field class MyToolInput(BaseModel): @@ -287,7 +287,7 @@ agent = await create_agent( ### Computer Protocol -The foundational abstraction. Every agent gets a computer — a pluggable execution environment that abstracts *where* CLI tools run. This is what makes HexAgent agents general-purpose: the same tools work whether the agent is on your laptop, in a VM, or in the cloud. +The foundational abstraction. Every agent gets a computer — a pluggable execution environment that abstracts *where* CLI tools run. This is what makes UniHarness agents general-purpose: the same tools work whether the agent is on your laptop, in a VM, or in the cloud. Implementations must provide: @@ -332,12 +332,12 @@ description: Extract and process PDF documents ... ``` -Default discovery paths: `/mnt/skills`, `~/.hexagent/skills`, `.hexagent/skills`. +Default discovery paths: `/mnt/skills`, `~/.uniharness/skills`, `.uniharness/skills`. ## Architecture ``` -hexagent/ +uniharness/ ├── __init__.py # Public API: Agent, AgentDefinition, ModelProfile, create_agent ├── types.py # Framework-agnostic core types (ToolResult, AgentContext, etc.) ├── tasks.py # Background task lifecycle (TaskRegistry) @@ -380,7 +380,7 @@ hexagent/ ## Development ```bash -cd libs/hexagent +cd libs/uniharness # Install dependencies uv sync --group test diff --git a/libs/hexagent/pyproject.toml b/libs/uniharness/pyproject.toml similarity index 85% rename from libs/hexagent/pyproject.toml rename to libs/uniharness/pyproject.toml index a1a4b9bc..79a157d6 100644 --- a/libs/hexagent/pyproject.toml +++ b/libs/uniharness/pyproject.toml @@ -3,9 +3,10 @@ requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" [project] -name = "hexagent" +name = "uniharness" dynamic = ["version"] description = "A general-purpose agent harness that gives LLM agents a CLI-based computer to complete tasks the way humans do" +readme = "README.md" requires-python = ">=3.11,<4.0" authors = [ { name = "Anqi (Anthony) Tang", email = "anqi.tang.ai@gmail.com" } @@ -36,8 +37,8 @@ observe = [ ] [project.urls] -Repository = "https://github.com/an7tang/hexagent" -Issues = "https://github.com/an7tang/hexagent/issues" +Repository = "https://github.com/UnicomAI/UniHarness" +Issues = "https://github.com/UnicomAI/UniHarness/issues" [dependency-groups] test = [ @@ -53,17 +54,17 @@ test = [ [tool.hatch.version] source = "vcs" -tag-pattern = "hexagent==(?P.*)" +tag-pattern = "uniharness==(?P.*)" raw-options = { root = "../.." } fallback-version = "0.0.0" [tool.hatch.build.targets.sdist] include = [ - "/hexagent", + "/uniharness", ] [tool.hatch.build.targets.wheel] -packages = ["hexagent"] +packages = ["uniharness"] [tool.ruff] line-length = 150 @@ -112,11 +113,11 @@ ignore-var-parameters = true ] # Production files -"hexagent/tools/web/providers/_retry.py" = ["PLR2004"] -"hexagent/tools/web/providers/fetch/jina.py" = ["EM101", "EM102", "TRY003"] -"hexagent/tools/web/providers/fetch/firecrawl.py" = ["EM101", "EM102", "TRY003"] -"hexagent/tools/web/providers/search/tavily.py" = ["EM101", "EM102", "TRY003"] -"hexagent/tools/web/providers/search/brave.py" = ["EM101", "EM102", "TRY003"] +"uniharness/tools/web/providers/_retry.py" = ["PLR2004"] +"uniharness/tools/web/providers/fetch/jina.py" = ["EM101", "EM102", "TRY003"] +"uniharness/tools/web/providers/fetch/firecrawl.py" = ["EM101", "EM102", "TRY003"] +"uniharness/tools/web/providers/search/tavily.py" = ["EM101", "EM102", "TRY003"] +"uniharness/tools/web/providers/search/brave.py" = ["EM101", "EM102", "TRY003"] # Test files "tests/integration_tests/test_end_to_end.py" = ["ARG002", "PLR2004"] diff --git a/libs/hexagent/sandbox/docker/Dockerfile b/libs/uniharness/sandbox/docker/Dockerfile similarity index 98% rename from libs/hexagent/sandbox/docker/Dockerfile rename to libs/uniharness/sandbox/docker/Dockerfile index 751237f5..61ed77e3 100644 --- a/libs/hexagent/sandbox/docker/Dockerfile +++ b/libs/uniharness/sandbox/docker/Dockerfile @@ -8,10 +8,10 @@ # Base: Ubuntu 24.04 LTS (Noble Numbat) # # Build: -# docker build -t hexagent-sandbox . +# docker build -t uniharness-sandbox . # # Run: -# docker run -it --rm hexagent-sandbox +# docker run -it --rm uniharness-sandbox # ============================================================================= FROM ubuntu:24.04 @@ -293,7 +293,7 @@ RUN ln -sf /usr/bin/python3 /usr/bin/python RUN mkdir -p /mnt/uploads /mnt/outputs /mnt/skills -WORKDIR /home/hexagent +WORKDIR /home/uniharness USER root CMD ["/bin/sh"] diff --git a/libs/hexagent/sandbox/docker/docker-compose.yml b/libs/uniharness/sandbox/docker/docker-compose.yml similarity index 85% rename from libs/hexagent/sandbox/docker/docker-compose.yml rename to libs/uniharness/sandbox/docker/docker-compose.yml index 7acf2b15..e54a9e78 100644 --- a/libs/hexagent/sandbox/docker/docker-compose.yml +++ b/libs/uniharness/sandbox/docker/docker-compose.yml @@ -1,12 +1,12 @@ -# Docker Compose for HexAgent Computer Environment +# Docker Compose for UniHarness Computer Environment # Usage: docker-compose up -d services: - hexagent-sandbox: + uniharness-sandbox: build: context: . dockerfile: Dockerfile - container_name: hexagent-sandbox + container_name: uniharness-sandbox # Mount points (customize paths as needed) volumes: @@ -45,6 +45,6 @@ services: # Optional: Add gVisor runtime for extra sandboxing # Requires gVisor to be installed on host - # hexagent-sandboxed: - # extends: hexagent-sandbox + # uniharness-sandboxed: + # extends: uniharness-sandbox # runtime: runsc diff --git a/libs/hexagent/sandbox/vm/lima/entitlements.plist b/libs/uniharness/sandbox/vm/lima/entitlements.plist similarity index 100% rename from libs/hexagent/sandbox/vm/lima/entitlements.plist rename to libs/uniharness/sandbox/vm/lima/entitlements.plist diff --git a/libs/hexagent/sandbox/vm/lima/hexagent.yaml b/libs/uniharness/sandbox/vm/lima/uniharness.yaml similarity index 83% rename from libs/hexagent/sandbox/vm/lima/hexagent.yaml rename to libs/uniharness/sandbox/vm/lima/uniharness.yaml index 6252a101..e09abcec 100644 --- a/libs/hexagent/sandbox/vm/lima/hexagent.yaml +++ b/libs/uniharness/sandbox/vm/lima/uniharness.yaml @@ -7,14 +7,14 @@ # ../setup/setup.sh, which is copied into the VM and run after first boot. # # Usage: -# limactl start --name=hexagent hexagent.yaml # Create & boot VM -# limactl shell hexagent # Open shell -# limactl stop hexagent # Stop VM -# limactl delete hexagent # Delete VM +# limactl start --name=uniharness uniharness.yaml # Create & boot VM +# limactl shell uniharness # Open shell +# limactl stop uniharness # Stop VM +# limactl delete uniharness # Delete VM # # After creating the VM, run provisioning: -# limactl copy setup/ hexagent:/tmp/setup/ -# limactl shell hexagent -- sudo bash /tmp/setup/setup.sh +# limactl copy setup/ uniharness:/tmp/setup/ +# limactl shell uniharness -- sudo bash /tmp/setup/setup.sh # ============================================================================= # --- VM Engine --- @@ -35,7 +35,7 @@ disk: "50GiB" # --- User --- user: - name: "hexagent" + name: "uniharness" # --- Mounts --- mounts: [] diff --git a/libs/hexagent/sandbox/vm/setup/setup.sh b/libs/uniharness/sandbox/vm/setup/setup.sh similarity index 98% rename from libs/hexagent/sandbox/vm/setup/setup.sh rename to libs/uniharness/sandbox/vm/setup/setup.sh index ce3187e3..80e156e9 100755 --- a/libs/hexagent/sandbox/vm/setup/setup.sh +++ b/libs/uniharness/sandbox/vm/setup/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # ============================================================================= -# HexAgent VM Setup — Orchestrator +# UniHarness VM Setup — Orchestrator # ============================================================================= # Discovers and runs step scripts in order with progress reporting, # resumability (marker files), concurrency protection (flock), and @@ -24,9 +24,9 @@ set -uo pipefail # ── Constants ──────────────────────────────────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" STEPS_DIR="${SCRIPT_DIR}/steps" -MARKER_DIR="/var/lib/hexagent/setup" -LOG_DIR="/var/log/hexagent/setup" -LOCK_FILE="/var/run/hexagent-setup.lock" +MARKER_DIR="/var/lib/uniharness/setup" +LOG_DIR="/var/log/uniharness/setup" +LOCK_FILE="/var/run/uniharness-setup.lock" LOCK_FD=9 # ── Environment (inherited by steps) ──────────────────────────────────────── diff --git a/libs/hexagent/sandbox/vm/setup/steps/01_base.sh b/libs/uniharness/sandbox/vm/setup/steps/01_base.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/01_base.sh rename to libs/uniharness/sandbox/vm/setup/steps/01_base.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/02_nodejs.sh b/libs/uniharness/sandbox/vm/setup/steps/02_nodejs.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/02_nodejs.sh rename to libs/uniharness/sandbox/vm/setup/steps/02_nodejs.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/03_apt.sh b/libs/uniharness/sandbox/vm/setup/steps/03_apt.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/03_apt.sh rename to libs/uniharness/sandbox/vm/setup/steps/03_apt.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/04_npm.sh b/libs/uniharness/sandbox/vm/setup/steps/04_npm.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/04_npm.sh rename to libs/uniharness/sandbox/vm/setup/steps/04_npm.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/05_pip.sh b/libs/uniharness/sandbox/vm/setup/steps/05_pip.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/05_pip.sh rename to libs/uniharness/sandbox/vm/setup/steps/05_pip.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/06_playwright.sh b/libs/uniharness/sandbox/vm/setup/steps/06_playwright.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/06_playwright.sh rename to libs/uniharness/sandbox/vm/setup/steps/06_playwright.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/07_finalize.sh b/libs/uniharness/sandbox/vm/setup/steps/07_finalize.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/07_finalize.sh rename to libs/uniharness/sandbox/vm/setup/steps/07_finalize.sh diff --git a/libs/hexagent/sandbox/vm/setup/steps/08_cleanup.sh b/libs/uniharness/sandbox/vm/setup/steps/08_cleanup.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup/steps/08_cleanup.sh rename to libs/uniharness/sandbox/vm/setup/steps/08_cleanup.sh diff --git a/libs/hexagent/sandbox/vm/setup_lite/setup.sh b/libs/uniharness/sandbox/vm/setup_lite/setup.sh similarity index 90% rename from libs/hexagent/sandbox/vm/setup_lite/setup.sh rename to libs/uniharness/sandbox/vm/setup_lite/setup.sh index 071ecc58..e17df6cb 100755 --- a/libs/hexagent/sandbox/vm/setup_lite/setup.sh +++ b/libs/uniharness/sandbox/vm/setup_lite/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # ============================================================================= -# HexAgent VM Setup (Lite) — Orchestrator +# UniHarness VM Setup (Lite) — Orchestrator # ============================================================================= # Lite variant: minimal baseline packages for demo/Electron deployments. # Discovers and runs step scripts in order with progress reporting, @@ -25,9 +25,9 @@ set -uo pipefail # ── Constants ──────────────────────────────────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" STEPS_DIR="${SCRIPT_DIR}/steps" -MARKER_DIR="/var/lib/hexagent/setup" -LOG_DIR="/var/log/hexagent/setup" -LOCK_FILE="/var/run/hexagent-setup.lock" +MARKER_DIR="/var/lib/uniharness/setup" +LOG_DIR="/var/log/uniharness/setup" +LOCK_FILE="/var/run/uniharness-setup.lock" LOCK_FD=9 # ── Environment (inherited by steps) ──────────────────────────────────────── @@ -35,18 +35,18 @@ export DEBIAN_FRONTEND=noninteractive export PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers export MARKER_DIR LOG_DIR if grep -qi microsoft /proc/version 2>/dev/null; then - _OPENAGENT_DEFAULT_CN_MIRRORS=1 + _UNIHARNESS_DEFAULT_CN_MIRRORS=1 else - _OPENAGENT_DEFAULT_CN_MIRRORS=0 + _UNIHARNESS_DEFAULT_CN_MIRRORS=0 fi -OPENAGENT_USE_CN_MIRRORS="${OPENAGENT_USE_CN_MIRRORS:-${_OPENAGENT_DEFAULT_CN_MIRRORS}}" -OPENAGENT_APT_MIRROR="${OPENAGENT_APT_MIRROR:-https://mirrors.ustc.edu.cn/ubuntu}" -OPENAGENT_APT_PORTS_MIRROR="${OPENAGENT_APT_PORTS_MIRROR:-https://mirrors.ustc.edu.cn/ubuntu-ports}" -OPENAGENT_PIP_INDEX_URL="${OPENAGENT_PIP_INDEX_URL:-https://pypi.tuna.tsinghua.edu.cn/simple}" -OPENAGENT_NPM_REGISTRY="${OPENAGENT_NPM_REGISTRY:-https://registry.npmmirror.com}" -OPENAGENT_PLAYWRIGHT_DOWNLOAD_HOST="${OPENAGENT_PLAYWRIGHT_DOWNLOAD_HOST:-https://npmmirror.com/mirrors/playwright}" -export OPENAGENT_USE_CN_MIRRORS OPENAGENT_APT_MIRROR OPENAGENT_APT_PORTS_MIRROR -export OPENAGENT_PIP_INDEX_URL OPENAGENT_NPM_REGISTRY OPENAGENT_PLAYWRIGHT_DOWNLOAD_HOST +UNIHARNESS_USE_CN_MIRRORS="${UNIHARNESS_USE_CN_MIRRORS:-${_UNIHARNESS_DEFAULT_CN_MIRRORS}}" +UNIHARNESS_APT_MIRROR="${UNIHARNESS_APT_MIRROR:-https://mirrors.ustc.edu.cn/ubuntu}" +UNIHARNESS_APT_PORTS_MIRROR="${UNIHARNESS_APT_PORTS_MIRROR:-https://mirrors.ustc.edu.cn/ubuntu-ports}" +UNIHARNESS_PIP_INDEX_URL="${UNIHARNESS_PIP_INDEX_URL:-https://pypi.tuna.tsinghua.edu.cn/simple}" +UNIHARNESS_NPM_REGISTRY="${UNIHARNESS_NPM_REGISTRY:-https://registry.npmmirror.com}" +UNIHARNESS_PLAYWRIGHT_DOWNLOAD_HOST="${UNIHARNESS_PLAYWRIGHT_DOWNLOAD_HOST:-https://npmmirror.com/mirrors/playwright}" +export UNIHARNESS_USE_CN_MIRRORS UNIHARNESS_APT_MIRROR UNIHARNESS_APT_PORTS_MIRROR +export UNIHARNESS_PIP_INDEX_URL UNIHARNESS_NPM_REGISTRY UNIHARNESS_PLAYWRIGHT_DOWNLOAD_HOST # ── CLI defaults ───────────────────────────────────────────────────────────── FORCE=false @@ -150,7 +150,7 @@ pip_install() { local max_attempts=5 local delay=5 local attempt=1 - local use_cn_mirrors="${OPENAGENT_USE_CN_MIRRORS:-0}" + local use_cn_mirrors="${UNIHARNESS_USE_CN_MIRRORS:-0}" local pip_opts=( --timeout 120 --retries 3 @@ -217,7 +217,7 @@ pip_install() { export -f pip_install configure_cn_mirrors() { - if [[ "${OPENAGENT_USE_CN_MIRRORS}" != "1" ]]; then + if [[ "${UNIHARNESS_USE_CN_MIRRORS}" != "1" ]]; then return 0 fi @@ -225,15 +225,15 @@ configure_cn_mirrors() { # sed replacement escapes for arbitrary mirror strings (e.g. containing '&' or '|') local apt_mirror_esc apt_ports_mirror_esc - apt_mirror_esc="${OPENAGENT_APT_MIRROR//\\/\\\\}" + apt_mirror_esc="${UNIHARNESS_APT_MIRROR//\\/\\\\}" apt_mirror_esc="${apt_mirror_esc//&/\\&}" apt_mirror_esc="${apt_mirror_esc//|/\\|}" - apt_ports_mirror_esc="${OPENAGENT_APT_PORTS_MIRROR//\\/\\\\}" + apt_ports_mirror_esc="${UNIHARNESS_APT_PORTS_MIRROR//\\/\\\\}" apt_ports_mirror_esc="${apt_ports_mirror_esc//&/\\&}" apt_ports_mirror_esc="${apt_ports_mirror_esc//|/\\|}" if [[ -f /etc/apt/sources.list ]]; then - cp -n /etc/apt/sources.list /etc/apt/sources.list.openagent.bak 2>/dev/null || true + cp -n /etc/apt/sources.list /etc/apt/sources.list.uniharness.bak 2>/dev/null || true sed -Ei \ -e "s|https?://(archive|security)\.ubuntu\.com/ubuntu|${apt_mirror_esc}|g" \ -e "s|https?://ports\.ubuntu\.com/ubuntu-ports|${apt_ports_mirror_esc}|g" \ @@ -241,7 +241,7 @@ configure_cn_mirrors() { fi if [[ -f /etc/apt/sources.list.d/ubuntu.sources ]]; then - cp -n /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.openagent.bak 2>/dev/null || true + cp -n /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.uniharness.bak 2>/dev/null || true sed -Ei \ -e "s|^URIs:[[:space:]]*https?://(archive|security)\.ubuntu\.com/ubuntu/?$|URIs: ${apt_mirror_esc}|g" \ -e "s|^URIs:[[:space:]]*https?://ports\.ubuntu\.com/ubuntu-ports/?$|URIs: ${apt_ports_mirror_esc}|g" \ @@ -250,18 +250,18 @@ configure_cn_mirrors() { cat >/etc/pip.conf </etc/profile.d/openagent-mirrors.sh </etc/profile.d/uniharness-mirrors.sh </dev/null 2>&1 || true + npm config set registry "${UNIHARNESS_NPM_REGISTRY}" >/dev/null 2>&1 || true fi emit 04_npm progress "Installing npm global packages" diff --git a/libs/hexagent/sandbox/vm/setup_lite/steps/05_pip.sh b/libs/uniharness/sandbox/vm/setup_lite/steps/05_pip.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup_lite/steps/05_pip.sh rename to libs/uniharness/sandbox/vm/setup_lite/steps/05_pip.sh diff --git a/libs/hexagent/sandbox/vm/setup_lite/steps/06_playwright.sh b/libs/uniharness/sandbox/vm/setup_lite/steps/06_playwright.sh similarity index 94% rename from libs/hexagent/sandbox/vm/setup_lite/steps/06_playwright.sh rename to libs/uniharness/sandbox/vm/setup_lite/steps/06_playwright.sh index c1b344b8..cde51233 100755 --- a/libs/hexagent/sandbox/vm/setup_lite/steps/06_playwright.sh +++ b/libs/uniharness/sandbox/vm/setup_lite/steps/06_playwright.sh @@ -29,7 +29,7 @@ fi # Download Chromium binary emit 06_playwright progress "Downloading Chromium binary" -mirror_host="${OPENAGENT_PLAYWRIGHT_DOWNLOAD_HOST:-}" +mirror_host="${UNIHARNESS_PLAYWRIGHT_DOWNLOAD_HOST:-}" browser_ok=0 # If bundled browsers are already present in the VM image, skip network download. @@ -43,7 +43,7 @@ for ((attempt = 1; attempt <= max_attempts; attempt++)); do break fi - if [[ "${OPENAGENT_USE_CN_MIRRORS:-0}" == "1" && -n "$mirror_host" ]]; then + if [[ "${UNIHARNESS_USE_CN_MIRRORS:-0}" == "1" && -n "$mirror_host" ]]; then emit 06_playwright progress "browser install attempt $attempt/$max_attempts (mirror)" if PLAYWRIGHT_DOWNLOAD_HOST="$mirror_host" \ PLAYWRIGHT_BROWSERS_PATH=/opt/pw-browsers \ diff --git a/libs/hexagent/sandbox/vm/setup_lite/steps/07_finalize.sh b/libs/uniharness/sandbox/vm/setup_lite/steps/07_finalize.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup_lite/steps/07_finalize.sh rename to libs/uniharness/sandbox/vm/setup_lite/steps/07_finalize.sh diff --git a/libs/hexagent/sandbox/vm/setup_lite/steps/08_cleanup.sh b/libs/uniharness/sandbox/vm/setup_lite/steps/08_cleanup.sh similarity index 100% rename from libs/hexagent/sandbox/vm/setup_lite/steps/08_cleanup.sh rename to libs/uniharness/sandbox/vm/setup_lite/steps/08_cleanup.sh diff --git a/libs/hexagent/tests/__init__.py b/libs/uniharness/tests/__init__.py similarity index 100% rename from libs/hexagent/tests/__init__.py rename to libs/uniharness/tests/__init__.py diff --git a/libs/hexagent/tests/integration_tests/__init__.py b/libs/uniharness/tests/integration_tests/__init__.py similarity index 100% rename from libs/hexagent/tests/integration_tests/__init__.py rename to libs/uniharness/tests/integration_tests/__init__.py diff --git a/libs/hexagent/tests/integration_tests/computer/__init__.py b/libs/uniharness/tests/integration_tests/computer/__init__.py similarity index 100% rename from libs/hexagent/tests/integration_tests/computer/__init__.py rename to libs/uniharness/tests/integration_tests/computer/__init__.py diff --git a/libs/hexagent/tests/integration_tests/computer/test_e2b_reconnect.py b/libs/uniharness/tests/integration_tests/computer/test_e2b_reconnect.py similarity index 97% rename from libs/hexagent/tests/integration_tests/computer/test_e2b_reconnect.py rename to libs/uniharness/tests/integration_tests/computer/test_e2b_reconnect.py index 3c56994c..79bea681 100644 --- a/libs/hexagent/tests/integration_tests/computer/test_e2b_reconnect.py +++ b/libs/uniharness/tests/integration_tests/computer/test_e2b_reconnect.py @@ -14,7 +14,7 @@ import pytest -from hexagent.computer.remote.e2b import RemoteE2BComputer +from uniharness.computer.remote.e2b import RemoteE2BComputer pytestmark = pytest.mark.skipif( "E2B_API_KEY" not in os.environ, diff --git a/libs/hexagent/tests/integration_tests/test_end_to_end.py b/libs/uniharness/tests/integration_tests/test_end_to_end.py similarity index 96% rename from libs/hexagent/tests/integration_tests/test_end_to_end.py rename to libs/uniharness/tests/integration_tests/test_end_to_end.py index 2b97c33b..8dc88e1b 100644 --- a/libs/hexagent/tests/integration_tests/test_end_to_end.py +++ b/libs/uniharness/tests/integration_tests/test_end_to_end.py @@ -1,4 +1,4 @@ -"""End-to-end unit tests for hexagent with fake LLM models.""" +"""End-to-end unit tests for uniharness with fake LLM models.""" from collections.abc import Callable, Sequence from typing import Any @@ -11,10 +11,10 @@ from langchain_core.tools import BaseTool from pydantic import BaseModel, Field -from hexagent.computer import LocalNativeComputer -from hexagent.langchain import create_agent -from hexagent.tools.base import BaseAgentTool -from hexagent.types import ToolResult +from uniharness.computer import LocalNativeComputer +from uniharness.langchain import create_agent +from uniharness.tools.base import BaseAgentTool +from uniharness.types import ToolResult def _content_contains(content: str | list[dict[str, Any]], needle: str) -> bool: @@ -262,7 +262,7 @@ async def test_deep_agent_with_string_model_name(self) -> None: ) ) - with patch("hexagent.langchain.agent.init_chat_model", return_value=fake_model): + with patch("uniharness.langchain.agent.init_chat_model", return_value=fake_model): # This should not raise AttributeError: 'str' object has no attribute 'profile' computer = LocalNativeComputer() async with await create_agent("claude-sonnet-4-5-20250929", computer, extra_tools=[sample_tool]) as agent: diff --git a/libs/hexagent/tests/unit_tests/__init__.py b/libs/uniharness/tests/unit_tests/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/__init__.py rename to libs/uniharness/tests/unit_tests/__init__.py diff --git a/libs/hexagent/tests/unit_tests/chat_model.py b/libs/uniharness/tests/unit_tests/chat_model.py similarity index 100% rename from libs/hexagent/tests/unit_tests/chat_model.py rename to libs/uniharness/tests/unit_tests/chat_model.py diff --git a/libs/hexagent/tests/unit_tests/computer/__init__.py b/libs/uniharness/tests/unit_tests/computer/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/computer/__init__.py rename to libs/uniharness/tests/unit_tests/computer/__init__.py diff --git a/libs/hexagent/tests/unit_tests/computer/test_e2b.py b/libs/uniharness/tests/unit_tests/computer/test_e2b.py similarity index 99% rename from libs/hexagent/tests/unit_tests/computer/test_e2b.py rename to libs/uniharness/tests/unit_tests/computer/test_e2b.py index 39d58c0e..8445e545 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_e2b.py +++ b/libs/uniharness/tests/unit_tests/computer/test_e2b.py @@ -11,12 +11,12 @@ import pytest -from hexagent.computer.remote.e2b import ( +from uniharness.computer.remote.e2b import ( _E2B_MAX_LIFETIME_S, SANDBOX_DEFAULT_LIFETIME_S, RemoteE2BComputer, ) -from hexagent.exceptions import CLIError, ConfigurationError, MissingDependencyError +from uniharness.exceptions import CLIError, ConfigurationError, MissingDependencyError if TYPE_CHECKING: from collections.abc import Generator @@ -877,7 +877,7 @@ class TestProtocolCompliance: @pytest.mark.usefixtures("mock_env") def test_satisfies_computer_protocol(self) -> None: """Test RemoteE2BComputer satisfies Computer protocol.""" - from hexagent.computer import Computer + from uniharness.computer import Computer computer = RemoteE2BComputer() assert isinstance(computer, Computer) diff --git a/libs/hexagent/tests/unit_tests/computer/test_local_vm.py b/libs/uniharness/tests/unit_tests/computer/test_local_vm.py similarity index 97% rename from libs/hexagent/tests/unit_tests/computer/test_local_vm.py rename to libs/uniharness/tests/unit_tests/computer/test_local_vm.py index 8a9e16cc..1a83d83e 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_local_vm.py +++ b/libs/uniharness/tests/unit_tests/computer/test_local_vm.py @@ -12,11 +12,11 @@ import pytest -from hexagent.computer.base import SESSION_DIRS, Mount -from hexagent.computer.local._types import ResolvedMount -from hexagent.computer.local.vm import LocalVM, _VMSessionComputer -from hexagent.exceptions import VMError, VMMountConflictError -from hexagent.types import CLIResult +from uniharness.computer.base import SESSION_DIRS, Mount +from uniharness.computer.local._types import ResolvedMount +from uniharness.computer.local.vm import LocalVM, _VMSessionComputer +from uniharness.exceptions import VMError, VMMountConflictError +from uniharness.types import CLIResult # --------------------------------------------------------------------------- # Helpers @@ -48,9 +48,9 @@ def _mock_vm(*, status: str = "Running") -> AsyncMock: def _make_manager(vm: AsyncMock) -> Any: """Create a LocalVM with a mocked VM backend.""" - with patch("hexagent.computer.local.vm.sys") as mock_sys: + with patch("uniharness.computer.local.vm.sys") as mock_sys: mock_sys.platform = "darwin" - with patch("hexagent.computer.local.vm.LocalVM.__init__", return_value=None): + with patch("uniharness.computer.local.vm.LocalVM.__init__", return_value=None): mgr = LocalVM.__new__(LocalVM) mgr._vm = vm @@ -673,45 +673,45 @@ class TestMountResolution: """Tests for _resolve_mount() and _target_to_guest().""" def test_relative_target_system(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM m = Mount(source="/host/skills", target=".skills/coding") resolved = LocalVM._resolve_mount(m, scope="system") assert resolved.guest_path == "/mnt/.skills/coding" def test_relative_target_session(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM m = Mount(source="/host/project", target="project") resolved = LocalVM._resolve_mount(m, scope="session", session_name="alice") assert resolved.guest_path == "/sessions/alice/mnt/project" def test_absolute_target(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM m = Mount(source="/host/tools", target="/opt/tools") resolved = LocalVM._resolve_mount(m, scope="system") assert resolved.guest_path == "/opt/tools" def test_writable_preserved(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM m = Mount(source="/host/x", target="x", writable=True) resolved = LocalVM._resolve_mount(m, scope="system") assert resolved.writable is True def test_target_to_guest_system(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM assert LocalVM._target_to_guest("code", "system") == "/mnt/code" def test_target_to_guest_session(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM assert LocalVM._target_to_guest("proj", "session", "alice") == "/sessions/alice/mnt/proj" def test_target_to_guest_absolute(self) -> None: - from hexagent.computer.local.vm import LocalVM + from uniharness.computer.local.vm import LocalVM assert LocalVM._target_to_guest("/opt/tools", "system") == "/opt/tools" diff --git a/libs/hexagent/tests/unit_tests/computer/test_local_vm_win.py b/libs/uniharness/tests/unit_tests/computer/test_local_vm_win.py similarity index 97% rename from libs/hexagent/tests/unit_tests/computer/test_local_vm_win.py rename to libs/uniharness/tests/unit_tests/computer/test_local_vm_win.py index 6bccba0f..9100f444 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_local_vm_win.py +++ b/libs/uniharness/tests/unit_tests/computer/test_local_vm_win.py @@ -12,11 +12,11 @@ import pytest -from hexagent.computer.base import SESSION_DIRS, Mount -from hexagent.computer.local._types import ResolvedMount -from hexagent.computer.local.vm_win import LocalVM, _VMSessionComputer -from hexagent.exceptions import VMError, VMMountConflictError -from hexagent.types import CLIResult +from uniharness.computer.base import SESSION_DIRS, Mount +from uniharness.computer.local._types import ResolvedMount +from uniharness.computer.local.vm_win import LocalVM, _VMSessionComputer +from uniharness.exceptions import VMError, VMMountConflictError +from uniharness.types import CLIResult # --------------------------------------------------------------------------- # Helpers @@ -48,7 +48,7 @@ def _mock_vm(*, status: str = "Running") -> AsyncMock: def _make_manager(vm: AsyncMock) -> Any: """Create a LocalVM (Windows) with a mocked VM backend.""" - with patch("hexagent.computer.local.vm_win.LocalVM.__init__", return_value=None): + with patch("uniharness.computer.local.vm_win.LocalVM.__init__", return_value=None): mgr = LocalVM.__new__(LocalVM) mgr._vm = vm @@ -191,7 +191,7 @@ async def test_mount_idempotent_self_heals_missing_live_mount(self, tmp_path: An ] ) - with patch("hexagent.computer.local._wsl._win_path_to_wsl", return_value="/mnt/c/code"): + with patch("uniharness.computer.local._wsl._win_path_to_wsl", return_value="/mnt/c/code"): await mgr.mount(Mount(source=str(d), target="code")) vm.apply_mounts.assert_not_awaited() diff --git a/libs/hexagent/tests/unit_tests/computer/test_native.py b/libs/uniharness/tests/unit_tests/computer/test_native.py similarity index 98% rename from libs/hexagent/tests/unit_tests/computer/test_native.py rename to libs/uniharness/tests/unit_tests/computer/test_native.py index bc0bf8e7..2f77d1cf 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_native.py +++ b/libs/uniharness/tests/unit_tests/computer/test_native.py @@ -12,9 +12,9 @@ import pytest -from hexagent.computer import Computer, LocalNativeComputer -from hexagent.computer.base import BASH_MAX_TIMEOUT_MS -from hexagent.exceptions import CLIError, UnsupportedPlatformError +from uniharness.computer import Computer, LocalNativeComputer +from uniharness.computer.base import BASH_MAX_TIMEOUT_MS +from uniharness.exceptions import CLIError, UnsupportedPlatformError # Test constants _NONZERO_EXIT_CODE = 42 diff --git a/libs/hexagent/tests/unit_tests/computer/test_protocol.py b/libs/uniharness/tests/unit_tests/computer/test_protocol.py similarity index 96% rename from libs/hexagent/tests/unit_tests/computer/test_protocol.py rename to libs/uniharness/tests/unit_tests/computer/test_protocol.py index db827dd5..38d166f9 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_protocol.py +++ b/libs/uniharness/tests/unit_tests/computer/test_protocol.py @@ -2,9 +2,9 @@ import pytest -from hexagent.computer import Computer -from hexagent.computer.base import Mount -from hexagent.types import CLIResult +from uniharness.computer import Computer +from uniharness.computer.base import Mount +from uniharness.types import CLIResult def test_mock_satisfies_protocol() -> None: diff --git a/libs/hexagent/tests/unit_tests/computer/test_vm.py b/libs/uniharness/tests/unit_tests/computer/test_vm.py similarity index 98% rename from libs/hexagent/tests/unit_tests/computer/test_vm.py rename to libs/uniharness/tests/unit_tests/computer/test_vm.py index 90e0a7eb..a766f524 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_vm.py +++ b/libs/uniharness/tests/unit_tests/computer/test_vm.py @@ -17,12 +17,12 @@ import pytest -from hexagent.computer.base import BASH_MAX_TIMEOUT_MS, Computer -from hexagent.computer.local._lima import LimaVM -from hexagent.computer.local._types import ResolvedMount -from hexagent.computer.local.vm import _VMSessionComputer -from hexagent.exceptions import CLIError, LimaError, MissingDependencyError, UnsupportedPlatformError, VMError -from hexagent.types import CLIResult +from uniharness.computer.base import BASH_MAX_TIMEOUT_MS, Computer +from uniharness.computer.local._lima import LimaVM +from uniharness.computer.local._types import ResolvedMount +from uniharness.computer.local.vm import _VMSessionComputer +from uniharness.exceptions import CLIError, LimaError, MissingDependencyError, UnsupportedPlatformError, VMError +from uniharness.types import CLIResult # --------------------------------------------------------------------------- # Helpers diff --git a/libs/hexagent/tests/unit_tests/computer/test_wsl.py b/libs/uniharness/tests/unit_tests/computer/test_wsl.py similarity index 93% rename from libs/hexagent/tests/unit_tests/computer/test_wsl.py rename to libs/uniharness/tests/unit_tests/computer/test_wsl.py index f2ed9766..794cb402 100644 --- a/libs/hexagent/tests/unit_tests/computer/test_wsl.py +++ b/libs/uniharness/tests/unit_tests/computer/test_wsl.py @@ -15,17 +15,17 @@ import pytest -from hexagent.computer.base import BASH_MAX_TIMEOUT_MS, Computer -from hexagent.computer.local._types import ResolvedMount -from hexagent.computer.local._wsl import ( +from uniharness.computer.base import BASH_MAX_TIMEOUT_MS, Computer +from uniharness.computer.local._types import ResolvedMount +from uniharness.computer.local._wsl import ( WslVM, _parse_status_output, _session_user_from_guest_mount_path, _win_path_to_wsl, ) -from hexagent.computer.local.vm_win import LocalVM, _VMSessionComputer -from hexagent.exceptions import CLIError, MissingDependencyError, UnsupportedPlatformError, VMError, WslError -from hexagent.types import CLIResult +from uniharness.computer.local.vm_win import LocalVM, _VMSessionComputer +from uniharness.exceptions import CLIError, MissingDependencyError, UnsupportedPlatformError, VMError, WslError +from uniharness.types import CLIResult # --------------------------------------------------------------------------- # Helpers @@ -212,7 +212,7 @@ async def test_new_session_defaults_to_session_home(self) -> None: backend = _mock_vm() vm = object.__new__(LocalVM) vm._vm = backend - vm._instance = "openagent" + vm._instance = "uniharness" vm._lock = asyncio.Lock() vm._generate_unique_name = AsyncMock(return_value="alice") # type: ignore[method-assign] vm._create_user = AsyncMock() # type: ignore[method-assign] @@ -349,14 +349,14 @@ class TestWslVMInit: def test_rejects_non_win32(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "darwin"), + patch("uniharness.computer.local._wsl._PLATFORM", "darwin"), pytest.raises(UnsupportedPlatformError, match="Windows"), ): WslVM(instance="test") def test_rejects_missing_wsl(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value=None), patch("pathlib.Path.is_file", return_value=False), pytest.raises(MissingDependencyError, match="wsl.exe"), @@ -365,7 +365,7 @@ def test_rejects_missing_wsl(self) -> None: def test_accepts_win32_with_wsl(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="myvm") @@ -382,7 +382,7 @@ class TestWslVMStart: def _make_vm(self) -> WslVM: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): return WslVM(instance="test") @@ -428,31 +428,31 @@ class TestStatusParsing: """Tests for _parse_status_output.""" def test_utf8_output(self) -> None: - output = (" NAME STATE VERSION\n* Ubuntu Running 2\n hexagent Stopped 2\n").encode("utf-8") + output = (" NAME STATE VERSION\n* Ubuntu Running 2\n uniharness Stopped 2\n").encode("utf-8") entries = _parse_status_output(output) assert len(entries) == 2 assert entries[0] == {"name": "Ubuntu", "state": "Running", "version": "2"} - assert entries[1] == {"name": "hexagent", "state": "Stopped", "version": "2"} + assert entries[1] == {"name": "uniharness", "state": "Stopped", "version": "2"} def test_utf16le_with_bom(self) -> None: - text = " NAME STATE VERSION\n hexagent Running 2\n" + text = " NAME STATE VERSION\n uniharness Running 2\n" output = b"\xff\xfe" + text.encode("utf-16-le") entries = _parse_status_output(output) assert len(entries) == 1 - assert entries[0]["name"] == "hexagent" + assert entries[0]["name"] == "uniharness" assert entries[0]["state"] == "Running" def test_default_distro_star_prefix(self) -> None: - output = (" NAME STATE VERSION\n* hexagent Running 2\n").encode("utf-8") + output = (" NAME STATE VERSION\n* uniharness Running 2\n").encode("utf-8") entries = _parse_status_output(output) assert len(entries) == 1 - assert entries[0]["name"] == "hexagent" + assert entries[0]["name"] == "uniharness" def test_empty_output(self) -> None: entries = _parse_status_output(b"") @@ -468,14 +468,14 @@ def test_multiple_distros(self) -> None: " NAME STATE VERSION\n" "* Ubuntu Running 2\n" " Debian Stopped 2\n" - " hexagent Running 2\n" + " uniharness Running 2\n" ).encode("utf-8") entries = _parse_status_output(output) assert len(entries) == 3 names = [e["name"] for e in entries] - assert names == ["Ubuntu", "Debian", "hexagent"] + assert names == ["Ubuntu", "Debian", "uniharness"] # =========================================================================== @@ -542,7 +542,7 @@ class TestReadWriteMounts: def _make_vm(self) -> WslVM: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): return WslVM(instance="test") @@ -600,7 +600,7 @@ class TestShellCommandBuilding: async def _capture_exec_args(self, **shell_kwargs: Any) -> list[str]: """Call shell() and return the args passed to create_subprocess_exec.""" with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -651,7 +651,7 @@ async def test_cwd_without_user(self) -> None: async def test_timeout_raises_wsl_error(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -678,7 +678,7 @@ class TestApplyMounts: async def test_apply_stops_running_distro(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -696,7 +696,7 @@ async def test_apply_stops_running_distro(self) -> None: async def test_apply_raises_if_instance_missing(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -718,7 +718,7 @@ class TestApplyBindMounts: async def test_applies_bind_mounts(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -758,7 +758,7 @@ async def test_applies_bind_mounts(self) -> None: async def test_chown_after_writable_session_bind(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -788,7 +788,7 @@ async def test_chown_after_writable_session_bind(self) -> None: async def test_skips_already_mounted(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") @@ -810,7 +810,7 @@ async def test_skips_already_mounted(self) -> None: async def test_empty_mounts_is_noop(self) -> None: with ( - patch("hexagent.computer.local._wsl._PLATFORM", "win32"), + patch("uniharness.computer.local._wsl._PLATFORM", "win32"), patch("shutil.which", return_value="C:\\Windows\\System32\\wsl.exe"), ): vm = WslVM(instance="test") diff --git a/libs/hexagent/tests/unit_tests/conftest.py b/libs/uniharness/tests/unit_tests/conftest.py similarity index 89% rename from libs/hexagent/tests/unit_tests/conftest.py rename to libs/uniharness/tests/unit_tests/conftest.py index 6e3e98f4..14f7f000 100644 --- a/libs/hexagent/tests/unit_tests/conftest.py +++ b/libs/uniharness/tests/unit_tests/conftest.py @@ -8,10 +8,10 @@ import pytest from pydantic import BaseModel -from hexagent.harness.model import ModelProfile -from hexagent.tasks import TaskRegistry -from hexagent.tools.base import BaseAgentTool -from hexagent.types import ToolResult +from uniharness.harness.model import ModelProfile +from uniharness.tasks import TaskRegistry +from uniharness.tools.base import BaseAgentTool +from uniharness.types import ToolResult if TYPE_CHECKING: from collections.abc import AsyncIterator diff --git a/libs/hexagent/tests/unit_tests/harness/__init__.py b/libs/uniharness/tests/unit_tests/harness/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/harness/__init__.py rename to libs/uniharness/tests/unit_tests/harness/__init__.py diff --git a/libs/hexagent/tests/unit_tests/harness/test_environment.py b/libs/uniharness/tests/unit_tests/harness/test_environment.py similarity index 97% rename from libs/hexagent/tests/unit_tests/harness/test_environment.py rename to libs/uniharness/tests/unit_tests/harness/test_environment.py index 9681f0a6..0af3ab46 100644 --- a/libs/hexagent/tests/unit_tests/harness/test_environment.py +++ b/libs/uniharness/tests/unit_tests/harness/test_environment.py @@ -8,8 +8,8 @@ import pytest -from hexagent.harness.environment import EnvironmentResolver -from hexagent.types import CLIResult +from uniharness.harness.environment import EnvironmentResolver +from uniharness.types import CLIResult # --------------------------------------------------------------------------- # Helpers diff --git a/libs/hexagent/tests/unit_tests/harness/test_model.py b/libs/uniharness/tests/unit_tests/harness/test_model.py similarity index 98% rename from libs/hexagent/tests/unit_tests/harness/test_model.py rename to libs/uniharness/tests/unit_tests/harness/test_model.py index 81157d23..643ced2a 100644 --- a/libs/hexagent/tests/unit_tests/harness/test_model.py +++ b/libs/uniharness/tests/unit_tests/harness/test_model.py @@ -9,7 +9,7 @@ import pytest from langchain_core.language_models import BaseChatModel -from hexagent.harness.model import ( +from uniharness.harness.model import ( _DEFAULT_COMPACTION_RATIO, ModelProfile, ) diff --git a/libs/hexagent/tests/unit_tests/harness/test_permission.py b/libs/uniharness/tests/unit_tests/harness/test_permission.py similarity index 99% rename from libs/hexagent/tests/unit_tests/harness/test_permission.py rename to libs/uniharness/tests/unit_tests/harness/test_permission.py index 73ebb96d..ff562c83 100644 --- a/libs/hexagent/tests/unit_tests/harness/test_permission.py +++ b/libs/uniharness/tests/unit_tests/harness/test_permission.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING -from hexagent.harness.permission import ( +from uniharness.harness.permission import ( PermissionDecision, PermissionGate, PermissionResult, diff --git a/libs/hexagent/tests/unit_tests/harness/test_reminders.py b/libs/uniharness/tests/unit_tests/harness/test_reminders.py similarity index 97% rename from libs/hexagent/tests/unit_tests/harness/test_reminders.py rename to libs/uniharness/tests/unit_tests/harness/test_reminders.py index bf4d9562..7ecdfe02 100644 --- a/libs/hexagent/tests/unit_tests/harness/test_reminders.py +++ b/libs/uniharness/tests/unit_tests/harness/test_reminders.py @@ -4,15 +4,15 @@ from typing import TYPE_CHECKING -from hexagent.harness.reminders import ( +from uniharness.harness.reminders import ( BUILTIN_REMINDERS, Message, Reminder, available_skills_reminder, evaluate_reminders, ) -from hexagent.prompts.tags import SYSTEM_REMINDER_TAG, Tag -from hexagent.types import AgentContext, Skill +from uniharness.prompts.tags import SYSTEM_REMINDER_TAG, Tag +from uniharness.types import AgentContext, Skill if TYPE_CHECKING: from collections.abc import Sequence diff --git a/libs/hexagent/tests/unit_tests/harness/test_skill_spec.py b/libs/uniharness/tests/unit_tests/harness/test_skill_spec.py similarity index 99% rename from libs/hexagent/tests/unit_tests/harness/test_skill_spec.py rename to libs/uniharness/tests/unit_tests/harness/test_skill_spec.py index e4c32489..ceda605c 100644 --- a/libs/hexagent/tests/unit_tests/harness/test_skill_spec.py +++ b/libs/uniharness/tests/unit_tests/harness/test_skill_spec.py @@ -4,8 +4,8 @@ import pytest -from hexagent.exceptions import SkillError, SkillParseError, SkillValidationError -from hexagent.harness.skill_spec import ( +from uniharness.exceptions import SkillError, SkillParseError, SkillValidationError +from uniharness.harness.skill_spec import ( SkillFrontmatter, SkillSpec, parse_skill_md, diff --git a/libs/hexagent/tests/unit_tests/harness/test_skills.py b/libs/uniharness/tests/unit_tests/harness/test_skills.py similarity index 98% rename from libs/hexagent/tests/unit_tests/harness/test_skills.py rename to libs/uniharness/tests/unit_tests/harness/test_skills.py index f0ba5dce..6f425343 100644 --- a/libs/hexagent/tests/unit_tests/harness/test_skills.py +++ b/libs/uniharness/tests/unit_tests/harness/test_skills.py @@ -6,8 +6,8 @@ import pytest -from hexagent.harness.skills import SkillResolver -from hexagent.types import CLIResult +from uniharness.harness.skills import SkillResolver +from uniharness.types import CLIResult # --------------------------------------------------------------------------- # Mock Computer diff --git a/libs/hexagent/tests/unit_tests/langchain/__init__.py b/libs/uniharness/tests/unit_tests/langchain/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/langchain/__init__.py rename to libs/uniharness/tests/unit_tests/langchain/__init__.py diff --git a/libs/hexagent/tests/unit_tests/langchain/test_adapter.py b/libs/uniharness/tests/unit_tests/langchain/test_adapter.py similarity index 98% rename from libs/hexagent/tests/unit_tests/langchain/test_adapter.py rename to libs/uniharness/tests/unit_tests/langchain/test_adapter.py index 29d1718a..1c51ee03 100644 --- a/libs/hexagent/tests/unit_tests/langchain/test_adapter.py +++ b/libs/uniharness/tests/unit_tests/langchain/test_adapter.py @@ -6,7 +6,7 @@ import pytest -from hexagent.types import Base64Source, ToolResult, UrlSource +from uniharness.types import Base64Source, ToolResult, UrlSource class TestAnthropicContentBlocks: diff --git a/libs/hexagent/tests/unit_tests/langchain/test_agent.py b/libs/uniharness/tests/unit_tests/langchain/test_agent.py similarity index 94% rename from libs/hexagent/tests/unit_tests/langchain/test_agent.py rename to libs/uniharness/tests/unit_tests/langchain/test_agent.py index 4dade8cb..3582a498 100644 --- a/libs/hexagent/tests/unit_tests/langchain/test_agent.py +++ b/libs/uniharness/tests/unit_tests/langchain/test_agent.py @@ -8,11 +8,11 @@ import pytest -from hexagent.harness.definition import AgentDefinition -from hexagent.harness.model import _FALLBACK_COMPACTION_THRESHOLD, ModelProfile -from hexagent.langchain.agent import Agent, _resolve_to_profile, _validate_agent_tools -from hexagent.tasks import TaskRegistry from tests.unit_tests.conftest import make_tool +from uniharness.harness.definition import AgentDefinition +from uniharness.harness.model import _FALLBACK_COMPACTION_THRESHOLD, ModelProfile +from uniharness.langchain.agent import Agent, _resolve_to_profile, _validate_agent_tools +from uniharness.tasks import TaskRegistry # --------------------------------------------------------------------------- # _validate_agent_tools @@ -112,7 +112,7 @@ def test_base_chat_model_wrapped(self) -> None: def test_string_model_resolved(self) -> None: """String input calls init_chat_model.""" mock_model = _stub_model("resolved-model") - with patch("hexagent.langchain.agent.init_chat_model", return_value=mock_model) as mock_init: + with patch("uniharness.langchain.agent.init_chat_model", return_value=mock_model) as mock_init: result = _resolve_to_profile("some-model-name") mock_init.assert_called_once_with("some-model-name") diff --git a/libs/hexagent/tests/unit_tests/langchain/test_middleware.py b/libs/uniharness/tests/unit_tests/langchain/test_middleware.py similarity index 98% rename from libs/hexagent/tests/unit_tests/langchain/test_middleware.py rename to libs/uniharness/tests/unit_tests/langchain/test_middleware.py index a4d8835a..a342b1c8 100644 --- a/libs/hexagent/tests/unit_tests/langchain/test_middleware.py +++ b/libs/uniharness/tests/unit_tests/langchain/test_middleware.py @@ -20,20 +20,20 @@ ToolMessage, ) -from hexagent.harness.model import ModelProfile -from hexagent.harness.permission import PermissionDecision, PermissionGate, PermissionResult, SafetyRule -from hexagent.harness.reminders import Reminder -from hexagent.langchain.middleware import ( +from uniharness.harness.model import ModelProfile +from uniharness.harness.permission import PermissionDecision, PermissionGate, PermissionResult, SafetyRule +from uniharness.harness.reminders import Reminder +from uniharness.langchain.middleware import ( _IMAGE_EXTRACTED, AgentMiddleware, - HexAgentState, + UniHarnessState, _create_denied_response, _detect_skill_call, _extract_text_content, _extract_tool_images, ) -from hexagent.prompts.content import load -from hexagent.types import AgentContext, CompactionPhase, Skill +from uniharness.prompts.content import load +from uniharness.types import AgentContext, CompactionPhase, Skill if TYPE_CHECKING: from collections.abc import Sequence @@ -73,7 +73,7 @@ def _make_middleware( def _state( messages: list[SystemMessage | HumanMessage | AIMessage | ToolMessage], phase: CompactionPhase = CompactionPhase.NONE, -) -> HexAgentState: +) -> UniHarnessState: return {"messages": messages, "compaction_phase": phase} # type: ignore[typeddict-item] @@ -108,7 +108,7 @@ class TestDetectSkillCall: """Tests for _detect_skill_call (operates on OpenAI-format messages).""" def _skill_tool_name(self) -> str: - from hexagent.tools.skill import SkillTool + from uniharness.tools.skill import SkillTool return SkillTool.name diff --git a/libs/hexagent/tests/unit_tests/langchain/test_subagent.py b/libs/uniharness/tests/unit_tests/langchain/test_subagent.py similarity index 96% rename from libs/hexagent/tests/unit_tests/langchain/test_subagent.py rename to libs/uniharness/tests/unit_tests/langchain/test_subagent.py index deba1134..fe076d15 100644 --- a/libs/hexagent/tests/unit_tests/langchain/test_subagent.py +++ b/libs/uniharness/tests/unit_tests/langchain/test_subagent.py @@ -7,9 +7,9 @@ from langchain_core.messages import AIMessage, HumanMessage -from hexagent.harness.definition import AgentDefinition -from hexagent.langchain.subagent import LangChainSubagentRunner, _extract_final_output from tests.unit_tests.conftest import STUB_PROFILE, make_tool +from uniharness.harness.definition import AgentDefinition +from uniharness.langchain.subagent import LangChainSubagentRunner, _extract_final_output # --------------------------------------------------------------------------- # _extract_final_output diff --git a/libs/uniharness/tests/unit_tests/mcp/__init__.py b/libs/uniharness/tests/unit_tests/mcp/__init__.py new file mode 100644 index 00000000..c7fb64ac --- /dev/null +++ b/libs/uniharness/tests/unit_tests/mcp/__init__.py @@ -0,0 +1 @@ +"""Unit tests for uniharness.mcp module.""" diff --git a/libs/hexagent/tests/unit_tests/mcp/test_client.py b/libs/uniharness/tests/unit_tests/mcp/test_client.py similarity index 94% rename from libs/hexagent/tests/unit_tests/mcp/test_client.py rename to libs/uniharness/tests/unit_tests/mcp/test_client.py index 2ca4978a..b2ec4eca 100644 --- a/libs/hexagent/tests/unit_tests/mcp/test_client.py +++ b/libs/uniharness/tests/unit_tests/mcp/test_client.py @@ -1,5 +1,5 @@ # ruff: noqa: PLR2004, TC001, TC003 -"""Tests for hexagent.mcp._client — McpClient lifecycle and transport.""" +"""Tests for uniharness.mcp._client — McpClient lifecycle and transport.""" from __future__ import annotations @@ -12,8 +12,8 @@ import mcp.types as mcp_types import pytest -from hexagent.mcp._client import McpClient, _create_mcp_tool, _list_all_tools -from hexagent.types import McpServerConfig +from uniharness.mcp._client import McpClient, _create_mcp_tool, _list_all_tools +from uniharness.types import McpServerConfig def _make_mcp_tool( @@ -137,13 +137,13 @@ async def test_instructions_populated_from_initialize(self) -> None: client2._exit_stack = AsyncExitStack() await client2._exit_stack.__aenter__() try: - with patch("hexagent.mcp._client.McpClient._open_transport", return_value=(AsyncMock(), AsyncMock())): + with patch("uniharness.mcp._client.McpClient._open_transport", return_value=(AsyncMock(), AsyncMock())): mock_session = AsyncMock() init_result = MagicMock() init_result.instructions = "Server instructions here" mock_session.initialize = AsyncMock(return_value=init_result) - with patch("hexagent.mcp._client.ClientSession", return_value=mock_session): + with patch("uniharness.mcp._client.ClientSession", return_value=mock_session): mock_session.__aenter__ = AsyncMock(return_value=mock_session) mock_session.__aexit__ = AsyncMock(return_value=None) await client2._open_session() @@ -204,7 +204,7 @@ async def test_http_transport(self) -> None: try: with patch( - "hexagent.mcp._client.streamable_http_client", + "uniharness.mcp._client.streamable_http_client", self._mock_streamable_http, ): read, write = await client._open_transport() @@ -219,7 +219,7 @@ async def test_sse_transport(self) -> None: await client._exit_stack.__aenter__() try: - with patch("hexagent.mcp._client.sse_client", self._mock_sse): + with patch("uniharness.mcp._client.sse_client", self._mock_sse): read, write = await client._open_transport() assert read is not None assert write is not None @@ -232,7 +232,7 @@ async def test_stdio_transport(self) -> None: await client._exit_stack.__aenter__() try: - with patch("hexagent.mcp._client.stdio_client", self._mock_stdio): + with patch("uniharness.mcp._client.stdio_client", self._mock_stdio): read, write = await client._open_transport() assert read is not None assert write is not None diff --git a/libs/hexagent/tests/unit_tests/mcp/test_connector.py b/libs/uniharness/tests/unit_tests/mcp/test_connector.py similarity index 93% rename from libs/hexagent/tests/unit_tests/mcp/test_connector.py rename to libs/uniharness/tests/unit_tests/mcp/test_connector.py index 9d39920e..999b25a1 100644 --- a/libs/hexagent/tests/unit_tests/mcp/test_connector.py +++ b/libs/uniharness/tests/unit_tests/mcp/test_connector.py @@ -1,14 +1,14 @@ # ruff: noqa: PLR2004, TC001 -"""Tests for hexagent.mcp._connector — McpConnector orchestrator.""" +"""Tests for uniharness.mcp._connector — McpConnector orchestrator.""" from __future__ import annotations from unittest.mock import AsyncMock, patch -from hexagent.mcp._client import McpClient -from hexagent.mcp._connector import _MAX_CONNECT_ATTEMPTS, McpConnector -from hexagent.mcp._tool import McpTool -from hexagent.types import McpServerConfig +from uniharness.mcp._client import McpClient +from uniharness.mcp._connector import _MAX_CONNECT_ATTEMPTS, McpConnector +from uniharness.mcp._tool import McpTool +from uniharness.types import McpServerConfig def _http_config() -> McpServerConfig: @@ -146,7 +146,7 @@ async def mock_aexit( with ( patch.object(McpClient, "__aenter__", mock_aenter), patch.object(McpClient, "__aexit__", mock_aexit), - patch("hexagent.mcp._connector.asyncio.sleep", new_callable=AsyncMock), + patch("uniharness.mcp._connector.asyncio.sleep", new_callable=AsyncMock), ): async with McpConnector(servers) as connector: assert len(connector.clients) == 1 @@ -182,7 +182,7 @@ async def mock_aexit( with ( patch.object(McpClient, "__aenter__", mock_aenter), patch.object(McpClient, "__aexit__", mock_aexit), - patch("hexagent.mcp._connector.asyncio.sleep", new_callable=AsyncMock), + patch("uniharness.mcp._connector.asyncio.sleep", new_callable=AsyncMock), ): async with McpConnector(servers) as connector: assert len(connector.clients) == 1 diff --git a/libs/hexagent/tests/unit_tests/mcp/test_schema.py b/libs/uniharness/tests/unit_tests/mcp/test_schema.py similarity index 98% rename from libs/hexagent/tests/unit_tests/mcp/test_schema.py rename to libs/uniharness/tests/unit_tests/mcp/test_schema.py index 57c94e1a..c3fb03a3 100644 --- a/libs/hexagent/tests/unit_tests/mcp/test_schema.py +++ b/libs/uniharness/tests/unit_tests/mcp/test_schema.py @@ -1,6 +1,6 @@ # ruff: noqa: PLR2004 # mypy: disable-error-code="attr-defined" -"""Tests for hexagent.mcp._schema — JSON Schema to Pydantic model conversion.""" +"""Tests for uniharness.mcp._schema — JSON Schema to Pydantic model conversion.""" from __future__ import annotations @@ -9,7 +9,7 @@ import pytest from pydantic import BaseModel, ValidationError -from hexagent.mcp._schema import json_schema_to_model +from uniharness.mcp._schema import json_schema_to_model class TestSimpleTypes: diff --git a/libs/hexagent/tests/unit_tests/mcp/test_tool.py b/libs/uniharness/tests/unit_tests/mcp/test_tool.py similarity index 97% rename from libs/hexagent/tests/unit_tests/mcp/test_tool.py rename to libs/uniharness/tests/unit_tests/mcp/test_tool.py index e783c506..5d6b8532 100644 --- a/libs/hexagent/tests/unit_tests/mcp/test_tool.py +++ b/libs/uniharness/tests/unit_tests/mcp/test_tool.py @@ -1,4 +1,4 @@ -"""Tests for hexagent.mcp._tool — McpTool and result conversion.""" +"""Tests for uniharness.mcp._tool — McpTool and result conversion.""" from __future__ import annotations @@ -9,8 +9,8 @@ import mcp.types as mcp_types from pydantic import BaseModel, Field -from hexagent.mcp._tool import McpTool, _convert_result -from hexagent.types import Base64Source +from uniharness.mcp._tool import McpTool, _convert_result +from uniharness.types import Base64Source def _make_text_content(text: str) -> mcp_types.TextContent: diff --git a/libs/hexagent/tests/unit_tests/middleware/__init__.py b/libs/uniharness/tests/unit_tests/middleware/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/middleware/__init__.py rename to libs/uniharness/tests/unit_tests/middleware/__init__.py diff --git a/libs/hexagent/tests/unit_tests/prompts/__init__.py b/libs/uniharness/tests/unit_tests/prompts/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/prompts/__init__.py rename to libs/uniharness/tests/unit_tests/prompts/__init__.py diff --git a/libs/hexagent/tests/unit_tests/prompts/test_content.py b/libs/uniharness/tests/unit_tests/prompts/test_content.py similarity index 97% rename from libs/hexagent/tests/unit_tests/prompts/test_content.py rename to libs/uniharness/tests/unit_tests/prompts/test_content.py index b6e38271..87ee1e59 100644 --- a/libs/hexagent/tests/unit_tests/prompts/test_content.py +++ b/libs/uniharness/tests/unit_tests/prompts/test_content.py @@ -4,8 +4,8 @@ import pytest -from hexagent.prompts import content -from hexagent.prompts.content import substitute +from uniharness.prompts import content +from uniharness.prompts.content import substitute @pytest.fixture(autouse=True) diff --git a/libs/hexagent/tests/unit_tests/prompts/test_sections.py b/libs/uniharness/tests/unit_tests/prompts/test_sections.py similarity index 95% rename from libs/hexagent/tests/unit_tests/prompts/test_sections.py rename to libs/uniharness/tests/unit_tests/prompts/test_sections.py index 2b25cd2b..4a215866 100644 --- a/libs/hexagent/tests/unit_tests/prompts/test_sections.py +++ b/libs/uniharness/tests/unit_tests/prompts/test_sections.py @@ -4,10 +4,10 @@ from datetime import UTC, date, datetime -from hexagent.harness.definition import AgentDefinition -from hexagent.mcp import McpClient -from hexagent.prompts import FRESH_SESSION, RESUMED_SESSION, SUBAGENT_SESSION, compose -from hexagent.prompts.sections import ( +from uniharness.harness.definition import AgentDefinition +from uniharness.mcp import McpClient +from uniharness.prompts import FRESH_SESSION, RESUMED_SESSION, SUBAGENT_SESSION, compose +from uniharness.prompts.sections import ( _mnt_dirs, agency, computer_use, @@ -19,7 +19,7 @@ tool_instructions, using_your_tools, ) -from hexagent.types import AgentContext, EnvironmentContext +from uniharness.types import AgentContext, EnvironmentContext from ..conftest import STUB_PROFILE, core_tools, make_tool @@ -45,7 +45,7 @@ class TestIdentity: def test_includes_agent_name(self) -> None: result = identity(AgentContext(model=STUB_PROFILE)) assert result is not None - assert "HexAgent" in result + assert "UniHarness" in result class TestDoingTasks: @@ -237,7 +237,7 @@ def test_empty_profile_returns_empty_string(self) -> None: def test_filters_none_sections(self) -> None: ctx = AgentContext(model=STUB_PROFILE) # no tools → using_your_tools returns None result = compose([identity, using_your_tools], ctx) - assert "HexAgent" in result + assert "UniHarness" in result assert "Using your tools" not in result def test_joins_sections_with_double_newline(self) -> None: @@ -248,7 +248,7 @@ def test_joins_sections_with_double_newline(self) -> None: def test_fresh_session_includes_tools(self) -> None: result = compose(FRESH_SESSION, AgentContext(model=STUB_PROFILE, tools=core_tools())) - assert "HexAgent" in result + assert "UniHarness" in result assert "# Tools" in result assert "## Bash" in result @@ -259,7 +259,7 @@ def test_section_ordering_matches_profile(self) -> None: mcps=[_make_mcp_client("github", "GitHub API")], ) result = compose(FRESH_SESSION, ctx) - identity_pos = result.index("HexAgent") + identity_pos = result.index("UniHarness") tools_pos = result.index("# Tools") mcps_pos = result.index("# MCP Servers") assert identity_pos < tools_pos < mcps_pos @@ -267,7 +267,7 @@ def test_section_ordering_matches_profile(self) -> None: def test_custom_profile_only_includes_specified_sections(self) -> None: ctx = AgentContext(model=STUB_PROFILE, mcps=[_make_mcp_client("github", "GitHub API")]) result = compose([identity, mcps], ctx) - assert "HexAgent" in result + assert "UniHarness" in result assert "github" in result assert "Doing tasks" not in result @@ -285,8 +285,8 @@ class TestSubagentSession: def test_excludes_root_sections(self) -> None: ctx = AgentContext(model=STUB_PROFILE, tools=core_tools() + [make_tool("Agent"), make_tool("TaskOutput")]) result = compose(SUBAGENT_SESSION, ctx) - # Identity section starts with "You are HexAgent" - assert "You are HexAgent" not in result + # Identity section starts with "You are UniHarness" + assert "You are UniHarness" not in result assert "## Agency" not in result assert "## Doing tasks" not in result assert "## Executing actions with care" not in result diff --git a/libs/hexagent/tests/unit_tests/test_tasks.py b/libs/uniharness/tests/unit_tests/test_tasks.py similarity index 98% rename from libs/hexagent/tests/unit_tests/test_tasks.py rename to libs/uniharness/tests/unit_tests/test_tasks.py index ba20a72a..af94e234 100644 --- a/libs/hexagent/tests/unit_tests/test_tasks.py +++ b/libs/uniharness/tests/unit_tests/test_tasks.py @@ -1,4 +1,4 @@ -"""Tests for hexagent.tasks — TaskRegistry.""" +"""Tests for uniharness.tasks — TaskRegistry.""" # ruff: noqa: PT018 @@ -8,8 +8,8 @@ import pytest -from hexagent.tasks import TaskRegistry -from hexagent.types import ToolResult +from uniharness.tasks import TaskRegistry +from uniharness.types import ToolResult # --------------------------------------------------------------------------- # Helpers diff --git a/libs/hexagent/tests/unit_tests/test_trace.py b/libs/uniharness/tests/unit_tests/test_trace.py similarity index 98% rename from libs/hexagent/tests/unit_tests/test_trace.py rename to libs/uniharness/tests/unit_tests/test_trace.py index 9338a38d..a582c56f 100644 --- a/libs/hexagent/tests/unit_tests/test_trace.py +++ b/libs/uniharness/tests/unit_tests/test_trace.py @@ -1,4 +1,4 @@ -"""Tests for hexagent.trace and LangChain tracing setup.""" +"""Tests for uniharness.trace and LangChain tracing setup.""" from __future__ import annotations @@ -7,7 +7,7 @@ import pytest -import hexagent.trace as trc +import uniharness.trace as trc if TYPE_CHECKING: from collections.abc import Iterator diff --git a/libs/hexagent/tests/unit_tests/test_types.py b/libs/uniharness/tests/unit_tests/test_types.py similarity index 99% rename from libs/hexagent/tests/unit_tests/test_types.py rename to libs/uniharness/tests/unit_tests/test_types.py index 0cc43a44..16b2d4f0 100644 --- a/libs/hexagent/tests/unit_tests/test_types.py +++ b/libs/uniharness/tests/unit_tests/test_types.py @@ -6,8 +6,8 @@ import pytest -from hexagent.mcp import McpClient -from hexagent.types import ( +from uniharness.mcp import McpClient +from uniharness.types import ( AgentContext, Base64Source, CLIResult, diff --git a/libs/hexagent/tests/unit_tests/tools/__init__.py b/libs/uniharness/tests/unit_tests/tools/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/__init__.py rename to libs/uniharness/tests/unit_tests/tools/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/cli/__init__.py b/libs/uniharness/tests/unit_tests/tools/cli/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/cli/__init__.py rename to libs/uniharness/tests/unit_tests/tools/cli/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/cli/test_bash.py b/libs/uniharness/tests/unit_tests/tools/cli/test_bash.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/cli/test_bash.py rename to libs/uniharness/tests/unit_tests/tools/cli/test_bash.py index e80dcb85..eecf681c 100644 --- a/libs/hexagent/tests/unit_tests/tools/cli/test_bash.py +++ b/libs/uniharness/tests/unit_tests/tools/cli/test_bash.py @@ -6,11 +6,11 @@ import pytest -from hexagent.computer import LocalNativeComputer -from hexagent.exceptions import CLIError -from hexagent.tasks import TaskRegistry -from hexagent.tools import BashTool -from hexagent.types import CLIResult +from uniharness.computer import LocalNativeComputer +from uniharness.exceptions import CLIError +from uniharness.tasks import TaskRegistry +from uniharness.tools import BashTool +from uniharness.types import CLIResult # AsyncMock GC can trigger false "coroutine was never awaited" warnings # when mock cleanup encounters coroutine references from background tasks. diff --git a/libs/hexagent/tests/unit_tests/tools/cli/test_edit.py b/libs/uniharness/tests/unit_tests/tools/cli/test_edit.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/cli/test_edit.py rename to libs/uniharness/tests/unit_tests/tools/cli/test_edit.py index 2df53c7f..6991011b 100644 --- a/libs/hexagent/tests/unit_tests/tools/cli/test_edit.py +++ b/libs/uniharness/tests/unit_tests/tools/cli/test_edit.py @@ -5,9 +5,9 @@ from typing import TYPE_CHECKING from unittest.mock import AsyncMock -from hexagent.computer import LocalNativeComputer -from hexagent.exceptions import CLIError -from hexagent.tools import EditTool +from uniharness.computer import LocalNativeComputer +from uniharness.exceptions import CLIError +from uniharness.tools import EditTool if TYPE_CHECKING: from pathlib import Path diff --git a/libs/hexagent/tests/unit_tests/tools/cli/test_glob.py b/libs/uniharness/tests/unit_tests/tools/cli/test_glob.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/cli/test_glob.py rename to libs/uniharness/tests/unit_tests/tools/cli/test_glob.py index bfc32522..2dadc122 100644 --- a/libs/hexagent/tests/unit_tests/tools/cli/test_glob.py +++ b/libs/uniharness/tests/unit_tests/tools/cli/test_glob.py @@ -8,9 +8,9 @@ import pytest -from hexagent.computer import LocalNativeComputer -from hexagent.exceptions import CLIError -from hexagent.tools import GlobTool +from uniharness.computer import LocalNativeComputer +from uniharness.exceptions import CLIError +from uniharness.tools import GlobTool @pytest.fixture diff --git a/libs/hexagent/tests/unit_tests/tools/cli/test_grep.py b/libs/uniharness/tests/unit_tests/tools/cli/test_grep.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/cli/test_grep.py rename to libs/uniharness/tests/unit_tests/tools/cli/test_grep.py index d21e98d6..d0ffad6c 100644 --- a/libs/hexagent/tests/unit_tests/tools/cli/test_grep.py +++ b/libs/uniharness/tests/unit_tests/tools/cli/test_grep.py @@ -4,10 +4,10 @@ from unittest.mock import AsyncMock -from hexagent.exceptions import CLIError -from hexagent.tools import GrepTool -from hexagent.tools.cli.grep import build_rg_command -from hexagent.types import CLIResult, GrepToolParams +from uniharness.exceptions import CLIError +from uniharness.tools import GrepTool +from uniharness.tools.cli.grep import build_rg_command +from uniharness.types import CLIResult, GrepToolParams # --------------------------------------------------------------------------- # build_rg_command diff --git a/libs/hexagent/tests/unit_tests/tools/cli/test_read.py b/libs/uniharness/tests/unit_tests/tools/cli/test_read.py similarity index 97% rename from libs/hexagent/tests/unit_tests/tools/cli/test_read.py rename to libs/uniharness/tests/unit_tests/tools/cli/test_read.py index 3f0d52b0..12508a2f 100644 --- a/libs/hexagent/tests/unit_tests/tools/cli/test_read.py +++ b/libs/uniharness/tests/unit_tests/tools/cli/test_read.py @@ -6,11 +6,11 @@ import pytest -from hexagent.computer import LocalNativeComputer -from hexagent.exceptions import CLIError -from hexagent.tools import ReadTool -from hexagent.tools.cli.read import _LINE_SEPARATOR, _MAX_IMAGE_BYTES, _truncate_long_lines, read_file -from hexagent.types import Base64Source, CLIResult +from uniharness.computer import LocalNativeComputer +from uniharness.exceptions import CLIError +from uniharness.tools import ReadTool +from uniharness.tools.cli.read import _LINE_SEPARATOR, _MAX_IMAGE_BYTES, _truncate_long_lines, read_file +from uniharness.types import Base64Source, CLIResult @pytest.fixture @@ -297,7 +297,7 @@ async def test_long_lines_truncated(self, tool: ReadTool, long_line_file: str) - # Extract content after the separator sep_idx = first_line.find(_LINE_SEPARATOR) body = first_line[sep_idx + len(_LINE_SEPARATOR) :] - from hexagent.tools.cli.read import _MAX_LINE_LENGTH + from uniharness.tools.cli.read import _MAX_LINE_LENGTH assert len(body) == _MAX_LINE_LENGTH diff --git a/libs/hexagent/tests/unit_tests/tools/cli/test_write.py b/libs/uniharness/tests/unit_tests/tools/cli/test_write.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/cli/test_write.py rename to libs/uniharness/tests/unit_tests/tools/cli/test_write.py index 6087eef0..ededc5fa 100644 --- a/libs/hexagent/tests/unit_tests/tools/cli/test_write.py +++ b/libs/uniharness/tests/unit_tests/tools/cli/test_write.py @@ -8,9 +8,9 @@ if TYPE_CHECKING: from pathlib import Path -from hexagent.computer import LocalNativeComputer -from hexagent.exceptions import CLIError -from hexagent.tools import WriteTool +from uniharness.computer import LocalNativeComputer +from uniharness.exceptions import CLIError +from uniharness.tools import WriteTool class TestWriteTool: diff --git a/libs/hexagent/tests/unit_tests/tools/test_agent.py b/libs/uniharness/tests/unit_tests/tools/test_agent.py similarity index 97% rename from libs/hexagent/tests/unit_tests/tools/test_agent.py rename to libs/uniharness/tests/unit_tests/tools/test_agent.py index 123f3540..30a2d2a9 100644 --- a/libs/hexagent/tests/unit_tests/tools/test_agent.py +++ b/libs/uniharness/tests/unit_tests/tools/test_agent.py @@ -8,14 +8,14 @@ from typing import TYPE_CHECKING, Any from unittest.mock import AsyncMock, MagicMock -from hexagent.harness.definition import AgentDefinition -from hexagent.harness.reminders import task_completion_reminder -from hexagent.tasks import TaskRegistry -from hexagent.tools.task.agent import AgentTool -from hexagent.types import AgentContext, AgentToolParams, SubagentResult, ToolResult +from uniharness.harness.definition import AgentDefinition +from uniharness.harness.reminders import task_completion_reminder +from uniharness.tasks import TaskRegistry +from uniharness.tools.task.agent import AgentTool +from uniharness.types import AgentContext, AgentToolParams, SubagentResult, ToolResult if TYPE_CHECKING: - from hexagent.harness.reminders import Message + from uniharness.harness.reminders import Message from ..conftest import STUB_PROFILE diff --git a/libs/hexagent/tests/unit_tests/tools/test_cli.py b/libs/uniharness/tests/unit_tests/tools/test_cli.py similarity index 77% rename from libs/hexagent/tests/unit_tests/tools/test_cli.py rename to libs/uniharness/tests/unit_tests/tools/test_cli.py index 8c75ca73..ceff107d 100644 --- a/libs/hexagent/tests/unit_tests/tools/test_cli.py +++ b/libs/uniharness/tests/unit_tests/tools/test_cli.py @@ -1,8 +1,8 @@ """Tests for CLI tools factory functions.""" -from hexagent.computer import LocalNativeComputer -from hexagent.tasks import TaskRegistry -from hexagent.tools import create_cli_tools +from uniharness.computer import LocalNativeComputer +from uniharness.tasks import TaskRegistry +from uniharness.tools import create_cli_tools class TestCreateCliTools: diff --git a/libs/hexagent/tests/unit_tests/tools/test_skill.py b/libs/uniharness/tests/unit_tests/tools/test_skill.py similarity index 93% rename from libs/hexagent/tests/unit_tests/tools/test_skill.py rename to libs/uniharness/tests/unit_tests/tools/test_skill.py index afb4a0ab..c2bb70da 100644 --- a/libs/hexagent/tests/unit_tests/tools/test_skill.py +++ b/libs/uniharness/tests/unit_tests/tools/test_skill.py @@ -2,8 +2,8 @@ from __future__ import annotations -from hexagent.tools.skill import SkillTool -from hexagent.types import SkillToolParams +from uniharness.tools.skill import SkillTool +from uniharness.types import SkillToolParams class _FakeCatalog: diff --git a/libs/hexagent/tests/unit_tests/tools/test_tasks.py b/libs/uniharness/tests/unit_tests/tools/test_tasks.py similarity index 96% rename from libs/hexagent/tests/unit_tests/tools/test_tasks.py rename to libs/uniharness/tests/unit_tests/tools/test_tasks.py index 4244c152..f97fd57e 100644 --- a/libs/hexagent/tests/unit_tests/tools/test_tasks.py +++ b/libs/uniharness/tests/unit_tests/tools/test_tasks.py @@ -4,9 +4,9 @@ import asyncio -from hexagent.tasks import TaskRegistry -from hexagent.tools.task import TaskOutputTool, TaskStopTool -from hexagent.types import TaskOutputToolParams, TaskStopToolParams, ToolResult +from uniharness.tasks import TaskRegistry +from uniharness.tools.task import TaskOutputTool, TaskStopTool +from uniharness.types import TaskOutputToolParams, TaskStopToolParams, ToolResult # --------------------------------------------------------------------------- # Helpers diff --git a/libs/hexagent/tests/unit_tests/tools/todo/__init__.py b/libs/uniharness/tests/unit_tests/tools/todo/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/todo/__init__.py rename to libs/uniharness/tests/unit_tests/tools/todo/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/todo/test_todowrite.py b/libs/uniharness/tests/unit_tests/tools/todo/test_todowrite.py similarity index 96% rename from libs/hexagent/tests/unit_tests/tools/todo/test_todowrite.py rename to libs/uniharness/tests/unit_tests/tools/todo/test_todowrite.py index 2ee16dc6..fe63de34 100644 --- a/libs/hexagent/tests/unit_tests/tools/todo/test_todowrite.py +++ b/libs/uniharness/tests/unit_tests/tools/todo/test_todowrite.py @@ -4,8 +4,8 @@ from typing import Literal -from hexagent.tools.todo.todowrite import TodoWriteTool -from hexagent.types import TodoItem, TodoWriteToolParams +from uniharness.tools.todo.todowrite import TodoWriteTool +from uniharness.types import TodoItem, TodoWriteToolParams def _params(items: list[TodoItem]) -> TodoWriteToolParams: diff --git a/libs/hexagent/tests/unit_tests/tools/ui/__init__.py b/libs/uniharness/tests/unit_tests/tools/ui/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/ui/__init__.py rename to libs/uniharness/tests/unit_tests/tools/ui/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/ui/test_present_to_user.py b/libs/uniharness/tests/unit_tests/tools/ui/test_present_to_user.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/ui/test_present_to_user.py rename to libs/uniharness/tests/unit_tests/tools/ui/test_present_to_user.py index b8f21263..d1117bd0 100644 --- a/libs/hexagent/tests/unit_tests/tools/ui/test_present_to_user.py +++ b/libs/uniharness/tests/unit_tests/tools/ui/test_present_to_user.py @@ -7,7 +7,7 @@ import pytest -from hexagent.tools.ui.present_to_user import ( +from uniharness.tools.ui.present_to_user import ( _DELIM, _EXT_MIME_MAP, _PREFIX_COPIED, @@ -18,7 +18,7 @@ _build_command, _parse_output, ) -from hexagent.types import CLIResult, PresentToUserToolParams +from uniharness.types import CLIResult, PresentToUserToolParams # --------------------------------------------------------------------------- # Helpers diff --git a/libs/hexagent/tests/unit_tests/tools/web/__init__.py b/libs/uniharness/tests/unit_tests/tools/web/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/web/__init__.py rename to libs/uniharness/tests/unit_tests/tools/web/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/__init__.py b/libs/uniharness/tests/unit_tests/tools/web/providers/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/web/providers/__init__.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/fetch/__init__.py b/libs/uniharness/tests/unit_tests/tools/web/providers/fetch/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/web/providers/fetch/__init__.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/fetch/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/fetch/test_firecrawl.py b/libs/uniharness/tests/unit_tests/tools/web/providers/fetch/test_firecrawl.py similarity index 97% rename from libs/hexagent/tests/unit_tests/tools/web/providers/fetch/test_firecrawl.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/fetch/test_firecrawl.py index 7c808de8..c499b450 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/providers/fetch/test_firecrawl.py +++ b/libs/uniharness/tests/unit_tests/tools/web/providers/fetch/test_firecrawl.py @@ -7,8 +7,8 @@ import httpx import pytest -from hexagent.exceptions import ConfigurationError, WebAPIError -from hexagent.tools.web.providers.fetch.firecrawl import FirecrawlFetchProvider +from uniharness.exceptions import ConfigurationError, WebAPIError +from uniharness.tools.web.providers.fetch.firecrawl import FirecrawlFetchProvider class TestFirecrawlFetchProvider: diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/fetch/test_jina.py b/libs/uniharness/tests/unit_tests/tools/web/providers/fetch/test_jina.py similarity index 97% rename from libs/hexagent/tests/unit_tests/tools/web/providers/fetch/test_jina.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/fetch/test_jina.py index 10230d42..757aa388 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/providers/fetch/test_jina.py +++ b/libs/uniharness/tests/unit_tests/tools/web/providers/fetch/test_jina.py @@ -7,8 +7,8 @@ import httpx import pytest -from hexagent.exceptions import WebAPIError -from hexagent.tools.web.providers.fetch.jina import JinaFetchProvider +from uniharness.exceptions import WebAPIError +from uniharness.tools.web.providers.fetch.jina import JinaFetchProvider class TestJinaFetchProvider: diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/search/__init__.py b/libs/uniharness/tests/unit_tests/tools/web/providers/search/__init__.py similarity index 100% rename from libs/hexagent/tests/unit_tests/tools/web/providers/search/__init__.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/search/__init__.py diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/search/test_brave.py b/libs/uniharness/tests/unit_tests/tools/web/providers/search/test_brave.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/web/providers/search/test_brave.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/search/test_brave.py index 1ae0fcf9..25bd37ae 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/providers/search/test_brave.py +++ b/libs/uniharness/tests/unit_tests/tools/web/providers/search/test_brave.py @@ -8,8 +8,8 @@ import httpx import pytest -from hexagent.exceptions import ConfigurationError, WebAPIError -from hexagent.tools.web.providers.search.brave import BraveSearchProvider +from uniharness.exceptions import ConfigurationError, WebAPIError +from uniharness.tools.web.providers.search.brave import BraveSearchProvider class TestBraveSearchProvider: diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/search/test_tavily.py b/libs/uniharness/tests/unit_tests/tools/web/providers/search/test_tavily.py similarity index 97% rename from libs/hexagent/tests/unit_tests/tools/web/providers/search/test_tavily.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/search/test_tavily.py index bd8e0eda..cddeb284 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/providers/search/test_tavily.py +++ b/libs/uniharness/tests/unit_tests/tools/web/providers/search/test_tavily.py @@ -7,8 +7,8 @@ import httpx import pytest -from hexagent.exceptions import ConfigurationError, WebAPIError -from hexagent.tools.web.providers.search.tavily import TavilySearchProvider +from uniharness.exceptions import ConfigurationError, WebAPIError +from uniharness.tools.web.providers.search.tavily import TavilySearchProvider class TestTavilySearchProvider: diff --git a/libs/hexagent/tests/unit_tests/tools/web/providers/test_retry.py b/libs/uniharness/tests/unit_tests/tools/web/providers/test_retry.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/web/providers/test_retry.py rename to libs/uniharness/tests/unit_tests/tools/web/providers/test_retry.py index c74fd407..b8319afe 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/providers/test_retry.py +++ b/libs/uniharness/tests/unit_tests/tools/web/providers/test_retry.py @@ -7,7 +7,7 @@ import httpx import pytest -from hexagent.tools.web.providers._retry import _should_retry, web_retry +from uniharness.tools.web.providers._retry import _should_retry, web_retry # Known retry configuration values MAX_RETRY_ATTEMPTS = 3 diff --git a/libs/hexagent/tests/unit_tests/tools/web/test_cache.py b/libs/uniharness/tests/unit_tests/tools/web/test_cache.py similarity index 92% rename from libs/hexagent/tests/unit_tests/tools/web/test_cache.py rename to libs/uniharness/tests/unit_tests/tools/web/test_cache.py index 131bf05f..871ae837 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/test_cache.py +++ b/libs/uniharness/tests/unit_tests/tools/web/test_cache.py @@ -2,14 +2,14 @@ from __future__ import annotations -from hexagent.tools.web._cache import ( +from uniharness.tools.web._cache import ( cache_key, clear_caches, get_fetch_cache, get_search_cache, ) -from hexagent.tools.web.providers.fetch import FetchResult -from hexagent.tools.web.providers.search import SearchResult +from uniharness.tools.web.providers.fetch import FetchResult +from uniharness.tools.web.providers.search import SearchResult class TestCacheKey: diff --git a/libs/hexagent/tests/unit_tests/tools/web/test_fetch.py b/libs/uniharness/tests/unit_tests/tools/web/test_fetch.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/web/test_fetch.py rename to libs/uniharness/tests/unit_tests/tools/web/test_fetch.py index 802ebb47..71c692b6 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/test_fetch.py +++ b/libs/uniharness/tests/unit_tests/tools/web/test_fetch.py @@ -7,9 +7,9 @@ import httpx import pytest -from hexagent.exceptions import ConfigurationError, ToolError, WebAPIError -from hexagent.tools.web import WebFetchTool, clear_caches -from hexagent.tools.web.providers.fetch import FetchResult +from uniharness.exceptions import ConfigurationError, ToolError, WebAPIError +from uniharness.tools.web import WebFetchTool, clear_caches +from uniharness.tools.web.providers.fetch import FetchResult @pytest.fixture(autouse=True) diff --git a/libs/hexagent/tests/unit_tests/tools/web/test_markdown.py b/libs/uniharness/tests/unit_tests/tools/web/test_markdown.py similarity index 97% rename from libs/hexagent/tests/unit_tests/tools/web/test_markdown.py rename to libs/uniharness/tests/unit_tests/tools/web/test_markdown.py index a62e3fb5..69728c6a 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/test_markdown.py +++ b/libs/uniharness/tests/unit_tests/tools/web/test_markdown.py @@ -1,6 +1,6 @@ """Tests for markdown text processing utilities.""" -from hexagent.tools.web._markdown import strip_links_and_images +from uniharness.tools.web._markdown import strip_links_and_images class TestStripLinksAndImages: diff --git a/libs/hexagent/tests/unit_tests/tools/web/test_search.py b/libs/uniharness/tests/unit_tests/tools/web/test_search.py similarity index 96% rename from libs/hexagent/tests/unit_tests/tools/web/test_search.py rename to libs/uniharness/tests/unit_tests/tools/web/test_search.py index 1f8d87e8..e7618d8a 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/test_search.py +++ b/libs/uniharness/tests/unit_tests/tools/web/test_search.py @@ -7,10 +7,10 @@ import httpx import pytest -from hexagent.exceptions import ConfigurationError, ToolError, WebAPIError -from hexagent.tools.web import WebSearchTool, clear_caches -from hexagent.tools.web.providers.search import SearchResult, SearchResultItem -from hexagent.tools.web.search import MAX_SEARCH_RESULTS +from uniharness.exceptions import ConfigurationError, ToolError, WebAPIError +from uniharness.tools.web import WebSearchTool, clear_caches +from uniharness.tools.web.providers.search import SearchResult, SearchResultItem +from uniharness.tools.web.search import MAX_SEARCH_RESULTS @pytest.fixture(autouse=True) diff --git a/libs/hexagent/tests/unit_tests/tools/web/test_validation.py b/libs/uniharness/tests/unit_tests/tools/web/test_validation.py similarity index 98% rename from libs/hexagent/tests/unit_tests/tools/web/test_validation.py rename to libs/uniharness/tests/unit_tests/tools/web/test_validation.py index b3e545cf..347a3c91 100644 --- a/libs/hexagent/tests/unit_tests/tools/web/test_validation.py +++ b/libs/uniharness/tests/unit_tests/tools/web/test_validation.py @@ -4,7 +4,7 @@ import pytest -from hexagent.tools.web._validation import is_private_ip, validate_url +from uniharness.tools.web._validation import is_private_ip, validate_url class TestIsPrivateIP: diff --git a/libs/uniharness/uniharness/__init__.py b/libs/uniharness/uniharness/__init__.py new file mode 100644 index 00000000..ccf80d51 --- /dev/null +++ b/libs/uniharness/uniharness/__init__.py @@ -0,0 +1,19 @@ +"""UniHarness package. + +UniHarness is an Agent SDK (supporting OpenAI-compatible LLMs) similar to +Anthropic's Claude Agent SDK. + +Core Philosophy: Give agents a CLI-based computer, allowing them to work +like humans do. +""" + +from uniharness.harness.definition import AgentDefinition +from uniharness.harness.model import ModelProfile +from uniharness.langchain import Agent, create_agent + +__all__ = [ + "Agent", + "AgentDefinition", + "ModelProfile", + "create_agent", +] diff --git a/libs/uniharness/uniharness/computer/__init__.py b/libs/uniharness/uniharness/computer/__init__.py new file mode 100644 index 00000000..01c30594 --- /dev/null +++ b/libs/uniharness/uniharness/computer/__init__.py @@ -0,0 +1,14 @@ +"""Computer abstractions for UniHarness.""" + +from uniharness.computer.base import Computer, ExecutionMetadata, Mount +from uniharness.computer.local import LocalNativeComputer, LocalVM +from uniharness.computer.remote.e2b import RemoteE2BComputer + +__all__ = [ + "Computer", + "ExecutionMetadata", + "LocalNativeComputer", + "LocalVM", + "Mount", + "RemoteE2BComputer", +] diff --git a/libs/hexagent/hexagent/computer/base.py b/libs/uniharness/uniharness/computer/base.py similarity index 98% rename from libs/hexagent/hexagent/computer/base.py rename to libs/uniharness/uniharness/computer/base.py index ceb07952..5f6abd74 100644 --- a/libs/hexagent/hexagent/computer/base.py +++ b/libs/uniharness/uniharness/computer/base.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Protocol, Self, runtime_checkable if TYPE_CHECKING: - from hexagent.types import CLIResult + from uniharness.types import CLIResult # Safety cap for command execution timeout BASH_MAX_TIMEOUT_MS = 600000 # 10 minutes diff --git a/libs/uniharness/uniharness/computer/local/__init__.py b/libs/uniharness/uniharness/computer/local/__init__.py new file mode 100644 index 00000000..0b07fbd5 --- /dev/null +++ b/libs/uniharness/uniharness/computer/local/__init__.py @@ -0,0 +1,12 @@ +"""Local computer implementations.""" + +import sys + +from uniharness.computer.local.native import LocalNativeComputer + +if sys.platform == "win32": + from uniharness.computer.local.vm_win import LocalVM +else: + from uniharness.computer.local.vm import LocalVM + +__all__ = ["LocalNativeComputer", "LocalVM"] diff --git a/libs/hexagent/hexagent/computer/local/_lima.py b/libs/uniharness/uniharness/computer/local/_lima.py similarity index 98% rename from libs/hexagent/hexagent/computer/local/_lima.py rename to libs/uniharness/uniharness/computer/local/_lima.py index 3f909754..bd1b220c 100644 --- a/libs/hexagent/hexagent/computer/local/_lima.py +++ b/libs/uniharness/uniharness/computer/local/_lima.py @@ -24,10 +24,10 @@ import yaml -from hexagent.computer.base import ExecutionMetadata -from hexagent.computer.local._types import ResolvedMount -from hexagent.exceptions import LimaError, MissingDependencyError, UnsupportedPlatformError -from hexagent.types import CLIResult +from uniharness.computer.base import ExecutionMetadata +from uniharness.computer.local._types import ResolvedMount +from uniharness.exceptions import LimaError, MissingDependencyError, UnsupportedPlatformError +from uniharness.types import CLIResult class LimaVM: diff --git a/libs/hexagent/hexagent/computer/local/_types.py b/libs/uniharness/uniharness/computer/local/_types.py similarity index 100% rename from libs/hexagent/hexagent/computer/local/_types.py rename to libs/uniharness/uniharness/computer/local/_types.py diff --git a/libs/hexagent/hexagent/computer/local/_wsl.py b/libs/uniharness/uniharness/computer/local/_wsl.py similarity index 98% rename from libs/hexagent/hexagent/computer/local/_wsl.py rename to libs/uniharness/uniharness/computer/local/_wsl.py index b62909a3..f871d1f6 100644 --- a/libs/hexagent/hexagent/computer/local/_wsl.py +++ b/libs/uniharness/uniharness/computer/local/_wsl.py @@ -28,10 +28,10 @@ import time from pathlib import Path -from hexagent.computer.base import ExecutionMetadata -from hexagent.computer.local._types import ResolvedMount -from hexagent.exceptions import MissingDependencyError, UnsupportedPlatformError, WslError -from hexagent.types import CLIResult +from uniharness.computer.base import ExecutionMetadata +from uniharness.computer.local._types import ResolvedMount +from uniharness.exceptions import MissingDependencyError, UnsupportedPlatformError, WslError +from uniharness.types import CLIResult logger = logging.getLogger(__name__) @@ -151,8 +151,8 @@ def instance(self) -> str: @property def _config_dir(self) -> Path: """Config directory for this instance.""" - data_dir = os.environ.get("HEXAGENT_DATA_DIR") - base = Path(data_dir) if data_dir else Path.home() / ".hexagent" + data_dir = os.environ.get("UNIHARNESS_DATA_DIR") + base = Path(data_dir) if data_dir else Path.home() / ".uniharness" return base / "wsl" / self._instance @property @@ -579,7 +579,7 @@ async def _apply_bind_mounts(self) -> None: # Windows ACLs allow writes. chown maps ownership to the session Linux user so # mkdir/Write behave consistently. sess = _session_user_from_guest_mount_path(m.guest_path) - skip_chown = os.environ.get("HEXAGENT_WSL_SKIP_SESSION_MOUNT_CHOWN", "").strip().lower() in ( + skip_chown = os.environ.get("UNIHARNESS_WSL_SKIP_SESSION_MOUNT_CHOWN", "").strip().lower() in ( "1", "true", "yes", diff --git a/libs/hexagent/hexagent/computer/local/native.py b/libs/uniharness/uniharness/computer/local/native.py similarity index 96% rename from libs/hexagent/hexagent/computer/local/native.py rename to libs/uniharness/uniharness/computer/local/native.py index 05b64bee..310578d1 100644 --- a/libs/hexagent/hexagent/computer/local/native.py +++ b/libs/uniharness/uniharness/computer/local/native.py @@ -14,14 +14,14 @@ import time from pathlib import Path -from hexagent.computer.base import ( +from uniharness.computer.base import ( BASH_MAX_TIMEOUT_MS, AsyncComputerMixin, Computer, ExecutionMetadata, ) -from hexagent.exceptions import CLIError, UnsupportedPlatformError -from hexagent.types import CLIResult +from uniharness.exceptions import CLIError, UnsupportedPlatformError +from uniharness.types import CLIResult class LocalNativeComputer(AsyncComputerMixin): diff --git a/libs/hexagent/hexagent/computer/local/vm.py b/libs/uniharness/uniharness/computer/local/vm.py similarity index 97% rename from libs/hexagent/hexagent/computer/local/vm.py rename to libs/uniharness/uniharness/computer/local/vm.py index 7ba91d52..1bd06f49 100644 --- a/libs/hexagent/hexagent/computer/local/vm.py +++ b/libs/uniharness/uniharness/computer/local/vm.py @@ -20,7 +20,7 @@ import petname -from hexagent.computer.base import ( +from uniharness.computer.base import ( BASH_MAX_TIMEOUT_MS, SESSION_DIRS, SESSION_OUTPUTS_DIR, @@ -29,12 +29,12 @@ Computer, Mount, ) -from hexagent.computer.local._types import ResolvedMount -from hexagent.exceptions import CLIError, UnsupportedPlatformError, VMError, VMMountConflictError +from uniharness.computer.local._types import ResolvedMount +from uniharness.exceptions import CLIError, UnsupportedPlatformError, VMError, VMMountConflictError if TYPE_CHECKING: - from hexagent.computer.local._lima import LimaVM - from hexagent.types import CLIResult + from uniharness.computer.local._lima import LimaVM + from uniharness.types import CLIResult # ------------------------------------------------------------------ @@ -207,10 +207,10 @@ class LocalVM: _instance: str _lock: asyncio.Lock - def __init__(self, *, instance: str = "hexagent") -> None: + def __init__(self, *, instance: str = "uniharness") -> None: """Initialize with a Lima VM instance name.""" if sys.platform == "darwin": - from hexagent.computer.local._lima import LimaVM as _LimaVM + from uniharness.computer.local._lima import LimaVM as _LimaVM self._vm: LimaVM = _LimaVM(instance=instance) else: diff --git a/libs/hexagent/hexagent/computer/local/vm_win.py b/libs/uniharness/uniharness/computer/local/vm_win.py similarity index 97% rename from libs/hexagent/hexagent/computer/local/vm_win.py rename to libs/uniharness/uniharness/computer/local/vm_win.py index 890433a2..69165a50 100644 --- a/libs/hexagent/hexagent/computer/local/vm_win.py +++ b/libs/uniharness/uniharness/computer/local/vm_win.py @@ -35,7 +35,7 @@ import petname -from hexagent.computer.base import ( +from uniharness.computer.base import ( BASH_MAX_TIMEOUT_MS, SESSION_DIRS, SESSION_OUTPUTS_DIR, @@ -44,12 +44,12 @@ Computer, Mount, ) -from hexagent.computer.local._types import ResolvedMount -from hexagent.exceptions import CLIError, VMError, VMMountConflictError +from uniharness.computer.local._types import ResolvedMount +from uniharness.exceptions import CLIError, VMError, VMMountConflictError if TYPE_CHECKING: - from hexagent.computer.local._wsl import WslVM - from hexagent.types import CLIResult + from uniharness.computer.local._wsl import WslVM + from uniharness.types import CLIResult # ------------------------------------------------------------------ @@ -234,7 +234,7 @@ class LocalVM: instance: WSL distribution name. """ - def __init__(self, *, instance: str = "hexagent") -> None: + def __init__(self, *, instance: str = "uniharness") -> None: """Initialize with a WSL distribution name. MERGE NOTE: When unifying with ``vm.py``, this is the platform @@ -255,7 +255,7 @@ def __init__(self, *, instance: str = "hexagent") -> None: """ # Platform check is delegated to WslVM.__init__(), which raises # UnsupportedPlatformError on non-Windows platforms. - from hexagent.computer.local._wsl import WslVM as _WslVM + from uniharness.computer.local._wsl import WslVM as _WslVM self._vm: WslVM = _WslVM(instance=instance) self._instance = instance @@ -336,7 +336,7 @@ async def mount( # noqa: PLR0912 for r in resolved_new: probe = await self._vm.shell(f"findmnt -n {shlex.quote(r.guest_path)}") if probe.exit_code != 0: - from hexagent.computer.local._wsl import _session_user_from_guest_mount_path, _win_path_to_wsl + from uniharness.computer.local._wsl import _session_user_from_guest_mount_path, _win_path_to_wsl wsl_host = _win_path_to_wsl(r.host_path) qguest = shlex.quote(r.guest_path) @@ -350,7 +350,7 @@ async def mount( # noqa: PLR0912 raise VMError(msg) sess = _session_user_from_guest_mount_path(r.guest_path) - skip_chown = os.environ.get("OPENAGENT_WSL_SKIP_SESSION_MOUNT_CHOWN", "").strip().lower() in ( + skip_chown = os.environ.get("UNIHARNESS_WSL_SKIP_SESSION_MOUNT_CHOWN", "").strip().lower() in ( "1", "true", "yes", diff --git a/libs/hexagent/hexagent/computer/remote/__init__.py b/libs/uniharness/uniharness/computer/remote/__init__.py similarity index 54% rename from libs/hexagent/hexagent/computer/remote/__init__.py rename to libs/uniharness/uniharness/computer/remote/__init__.py index f3a68c4d..941ff990 100644 --- a/libs/hexagent/hexagent/computer/remote/__init__.py +++ b/libs/uniharness/uniharness/computer/remote/__init__.py @@ -1,5 +1,5 @@ """Remote computer implementations.""" -from hexagent.computer.remote.e2b import RemoteE2BComputer +from uniharness.computer.remote.e2b import RemoteE2BComputer __all__ = ["RemoteE2BComputer"] diff --git a/libs/hexagent/hexagent/computer/remote/e2b.py b/libs/uniharness/uniharness/computer/remote/e2b.py similarity index 97% rename from libs/hexagent/hexagent/computer/remote/e2b.py rename to libs/uniharness/uniharness/computer/remote/e2b.py index 9d4ea869..3cbc0e56 100644 --- a/libs/hexagent/hexagent/computer/remote/e2b.py +++ b/libs/uniharness/uniharness/computer/remote/e2b.py @@ -15,9 +15,9 @@ Memory: $0.0162/GiB/hr Available templates: - an7tang/hexagent-c1-m1 1 CPU, 1 GiB Memory $0.0666/hr - an7tang/hexagent-c2-m4 2 CPU, 4 GiB Memory $0.1656/hr (alias: "an7tang/hexagent") - an7tang/hexagent-c4-m8 4 CPU, 8 GiB Memory $0.3312/hr + openagent-c1-m1 1 CPU, 1 GiB Memory $0.0666/hr + openagent-c2-m4 2 CPU, 4 GiB Memory $0.1656/hr (alias: "openagent") + openagent-c4-m8 4 CPU, 8 GiB Memory $0.3312/hr """ from __future__ import annotations @@ -30,14 +30,14 @@ from pathlib import Path from typing import TYPE_CHECKING -from hexagent.computer.base import ( +from uniharness.computer.base import ( BASH_MAX_TIMEOUT_MS, AsyncComputerMixin, Computer, ExecutionMetadata, ) -from hexagent.exceptions import CLIError, ConfigurationError, MissingDependencyError -from hexagent.types import CLIResult +from uniharness.exceptions import CLIError, ConfigurationError, MissingDependencyError +from uniharness.types import CLIResult if TYPE_CHECKING: from e2b import AsyncSandbox diff --git a/libs/hexagent/hexagent/exceptions.py b/libs/uniharness/uniharness/exceptions.py similarity index 96% rename from libs/hexagent/hexagent/exceptions.py rename to libs/uniharness/uniharness/exceptions.py index 449f1d19..18bd0591 100644 --- a/libs/hexagent/hexagent/exceptions.py +++ b/libs/uniharness/uniharness/exceptions.py @@ -1,6 +1,6 @@ -"""Exceptions for HexAgent. +"""Exceptions for UniHarness. -This module defines exceptions raised by HexAgent tools and components. +This module defines exceptions raised by UniHarness tools and components. """ @@ -185,7 +185,7 @@ class LimaError(VMError): Examples: ```python # VM did not start - raise LimaError("Lima instance 'hexagent' did not reach Running state within 120s") + raise LimaError("Lima instance 'uniharness' did not reach Running state within 120s") # Shell command timed out raise LimaError("timed out after 30s") @@ -202,7 +202,7 @@ class WslError(VMError): Examples: ```python # Distro did not start - raise WslError("WSL distro 'hexagent' did not start within 60s") + raise WslError("WSL distro 'uniharness' did not start within 60s") # WSL not installed raise WslError("wsl.exe not found — WSL2 must be installed") diff --git a/libs/hexagent/hexagent/harness/__init__.py b/libs/uniharness/uniharness/harness/__init__.py similarity index 71% rename from libs/hexagent/hexagent/harness/__init__.py rename to libs/uniharness/uniharness/harness/__init__.py index 5f8c5ab2..d647bb6a 100644 --- a/libs/hexagent/hexagent/harness/__init__.py +++ b/libs/uniharness/uniharness/harness/__init__.py @@ -7,23 +7,23 @@ - System reminder rules for dynamic message annotation """ -from hexagent.harness.definition import AgentDefinition -from hexagent.harness.environment import EnvironmentResolver -from hexagent.harness.model import ModelProfile -from hexagent.harness.permission import ( +from uniharness.harness.definition import AgentDefinition +from uniharness.harness.environment import EnvironmentResolver +from uniharness.harness.model import ModelProfile +from uniharness.harness.permission import ( PermissionDecision, PermissionGate, PermissionResult, SafetyRule, ) -from hexagent.harness.reminders import ( +from uniharness.harness.reminders import ( BUILTIN_REMINDERS, Reminder, available_skills_reminder, evaluate_reminders, task_completion_reminder, ) -from hexagent.harness.skills import DEFAULT_SKILL_PATHS, SkillResolver +from uniharness.harness.skills import DEFAULT_SKILL_PATHS, SkillResolver __all__ = [ "BUILTIN_REMINDERS", diff --git a/libs/hexagent/hexagent/harness/definition.py b/libs/uniharness/uniharness/harness/definition.py similarity index 91% rename from libs/hexagent/hexagent/harness/definition.py rename to libs/uniharness/uniharness/harness/definition.py index 6fbf919e..3cf1b8cb 100644 --- a/libs/hexagent/hexagent/harness/definition.py +++ b/libs/uniharness/uniharness/harness/definition.py @@ -8,7 +8,7 @@ if TYPE_CHECKING: from langchain_core.language_models import BaseChatModel - from hexagent.harness.model import ModelProfile + from uniharness.harness.model import ModelProfile @dataclass(frozen=True) diff --git a/libs/hexagent/hexagent/harness/environment.py b/libs/uniharness/uniharness/harness/environment.py similarity index 96% rename from libs/hexagent/hexagent/harness/environment.py rename to libs/uniharness/uniharness/harness/environment.py index 9aa63886..ab553745 100644 --- a/libs/hexagent/hexagent/harness/environment.py +++ b/libs/uniharness/uniharness/harness/environment.py @@ -9,10 +9,10 @@ from datetime import datetime from typing import TYPE_CHECKING -from hexagent.types import EnvironmentContext +from uniharness.types import EnvironmentContext if TYPE_CHECKING: - from hexagent.computer.base import Computer + from uniharness.computer.base import Computer class EnvironmentResolver: diff --git a/libs/hexagent/hexagent/harness/model.py b/libs/uniharness/uniharness/harness/model.py similarity index 100% rename from libs/hexagent/hexagent/harness/model.py rename to libs/uniharness/uniharness/harness/model.py diff --git a/libs/hexagent/hexagent/harness/permission.py b/libs/uniharness/uniharness/harness/permission.py similarity index 100% rename from libs/hexagent/hexagent/harness/permission.py rename to libs/uniharness/uniharness/harness/permission.py diff --git a/libs/hexagent/hexagent/harness/reminders.py b/libs/uniharness/uniharness/harness/reminders.py similarity index 94% rename from libs/hexagent/hexagent/harness/reminders.py rename to libs/uniharness/uniharness/harness/reminders.py index 8b37ee5e..fd11dc23 100644 --- a/libs/hexagent/hexagent/harness/reminders.py +++ b/libs/uniharness/uniharness/harness/reminders.py @@ -16,14 +16,14 @@ from dataclasses import dataclass from typing import TYPE_CHECKING, Any, Literal -from hexagent.prompts.content import load, substitute -from hexagent.prompts.tags import SYSTEM_REMINDER_TAG, Tag +from uniharness.prompts.content import load, substitute +from uniharness.prompts.tags import SYSTEM_REMINDER_TAG, Tag if TYPE_CHECKING: from collections.abc import Callable, Sequence - from hexagent.tasks import TaskRegistry - from hexagent.types import AgentContext + from uniharness.tasks import TaskRegistry + from uniharness.types import AgentContext # OpenAI-compatible message format. # Expected keys: "role" (str), "content" (str | list), @@ -145,6 +145,6 @@ def _rule(_messages: Sequence[Message], _ctx: AgentContext) -> str | None: """Default reminder rules for all sessions. Note: :func:`task_completion_reminder` is also a built-in reminder but requires -a :class:`~hexagent.tasks.TaskRegistry` instance. It is added +a :class:`~uniharness.tasks.TaskRegistry` instance. It is added unconditionally by the agent factory. """ diff --git a/libs/hexagent/hexagent/harness/skill_spec.py b/libs/uniharness/uniharness/harness/skill_spec.py similarity index 99% rename from libs/hexagent/hexagent/harness/skill_spec.py rename to libs/uniharness/uniharness/harness/skill_spec.py index 7f4377a9..a0f2723e 100644 --- a/libs/hexagent/hexagent/harness/skill_spec.py +++ b/libs/uniharness/uniharness/harness/skill_spec.py @@ -14,7 +14,7 @@ import yaml -from hexagent.exceptions import SkillParseError, SkillValidationError +from uniharness.exceptions import SkillParseError, SkillValidationError # --------------------------------------------------------------------------- # Constants diff --git a/libs/hexagent/hexagent/harness/skills.py b/libs/uniharness/uniharness/harness/skills.py similarity index 95% rename from libs/hexagent/hexagent/harness/skills.py rename to libs/uniharness/uniharness/harness/skills.py index 1880e8b8..1cc96e8d 100644 --- a/libs/hexagent/hexagent/harness/skills.py +++ b/libs/uniharness/uniharness/harness/skills.py @@ -10,19 +10,19 @@ import logging from typing import TYPE_CHECKING -from hexagent.exceptions import SkillError -from hexagent.harness.skill_spec import parse_skill_md, validate_skill_dir_name -from hexagent.types import Skill +from uniharness.exceptions import SkillError +from uniharness.harness.skill_spec import parse_skill_md, validate_skill_dir_name +from uniharness.types import Skill if TYPE_CHECKING: - from hexagent.computer.base import Computer + from uniharness.computer.base import Computer logger = logging.getLogger(__name__) DEFAULT_SKILL_PATHS: tuple[str, ...] = ( "/mnt/skills", - "~/.hexagent/skills", - ".hexagent/skills", + "~/.uniharness/skills", + ".uniharness/skills", ) _SKILL_FILENAMES = ("SKILL.md", "skill.md") @@ -72,7 +72,7 @@ def search_paths(self) -> tuple[str, ...]: async def has(self, name: str) -> bool: """Return True if *name* is a known skill, re-discovering on cache miss. - Satisfies the :class:`~hexagent.types.SkillCatalog` protocol. + Satisfies the :class:`~uniharness.types.SkillCatalog` protocol. Args: name: The skill name to check. diff --git a/libs/uniharness/uniharness/langchain/__init__.py b/libs/uniharness/uniharness/langchain/__init__.py new file mode 100644 index 00000000..c4961448 --- /dev/null +++ b/libs/uniharness/uniharness/langchain/__init__.py @@ -0,0 +1,25 @@ +"""LangChain integration for UniHarness. + +This module provides adapters and utilities for integrating UniHarness's +framework-agnostic tools and computer abstractions with LangChain. + +If you delete this directory, all core UniHarness functionality +(tools, computer, types, prompts) should still work independently. + +Main exports: +- Agent: UniHarness agent with managed resources +- create_agent: Create an UniHarness agent using LangChain +- to_langchain_tool: Convert BaseAgentTool to LangChain StructuredTool +- LangChainSubagentRunner: Executes subagents with isolated context +""" + +from uniharness.langchain.adapter import to_langchain_tool +from uniharness.langchain.agent import Agent, create_agent +from uniharness.langchain.subagent import LangChainSubagentRunner + +__all__ = [ + "Agent", + "LangChainSubagentRunner", + "create_agent", + "to_langchain_tool", +] diff --git a/libs/hexagent/hexagent/langchain/adapter.py b/libs/uniharness/uniharness/langchain/adapter.py similarity index 90% rename from libs/hexagent/hexagent/langchain/adapter.py rename to libs/uniharness/uniharness/langchain/adapter.py index 491b9c54..07a5e01d 100644 --- a/libs/hexagent/hexagent/langchain/adapter.py +++ b/libs/uniharness/uniharness/langchain/adapter.py @@ -1,6 +1,6 @@ -"""Adapter for converting HexAgent tools to LangChain tools. +"""Adapter for converting UniHarness tools to LangChain tools. -This module provides the bridge between HexAgent's framework-agnostic +This module provides the bridge between UniHarness's framework-agnostic BaseAgentTool and LangChain's StructuredTool interface. """ @@ -11,7 +11,7 @@ from langchain_core.tools import StructuredTool if TYPE_CHECKING: - from hexagent.tools.base import BaseAgentTool + from uniharness.tools.base import BaseAgentTool # Return type for content_and_artifact response format: # (content, artifact) where content is a list of content blocks. @@ -41,8 +41,8 @@ def to_langchain_tool( Examples: ```python - from hexagent.tools.cli import BashTool - from hexagent.langchain import to_langchain_tool + from uniharness.tools.cli import BashTool + from uniharness.langchain import to_langchain_tool bash_tool = BashTool(computer) langchain_tool = to_langchain_tool(bash_tool) diff --git a/libs/hexagent/hexagent/langchain/agent.py b/libs/uniharness/uniharness/langchain/agent.py similarity index 91% rename from libs/hexagent/hexagent/langchain/agent.py rename to libs/uniharness/uniharness/langchain/agent.py index d974fd18..f585ecc2 100644 --- a/libs/hexagent/hexagent/langchain/agent.py +++ b/libs/uniharness/uniharness/langchain/agent.py @@ -1,6 +1,6 @@ -"""LangChain agent factory for HexAgent. +"""LangChain agent factory for UniHarness. -Creates an HexAgent agent using LangChain's agent infrastructure. +Creates an UniHarness agent using LangChain's agent infrastructure. No CapabilityRegistry — tools are plain lists. System prompt is managed in state["messages"] by the middleware, not by LangChain's auto-prepend. """ @@ -16,17 +16,17 @@ from langchain.agents import create_agent as _create_langchain_agent from langchain.chat_models import init_chat_model -from hexagent.harness import BUILTIN_REMINDERS, DEFAULT_SKILL_PATHS, EnvironmentResolver, PermissionGate, SkillResolver, task_completion_reminder -from hexagent.harness.model import _FALLBACK_COMPACTION_THRESHOLD, ModelProfile -from hexagent.langchain.middleware import AgentMiddleware -from hexagent.langchain.subagent import LangChainSubagentRunner -from hexagent.prompts import FRESH_SESSION, RESUMED_SESSION, compose -from hexagent.tasks import TaskRegistry -from hexagent.tools import SkillTool, TodoWriteTool, create_cli_tools, create_web_tools -from hexagent.tools.task import TaskOutputTool, TaskStopTool -from hexagent.tools.task.agent import AgentTool -from hexagent.trace import init_langchain_tracing -from hexagent.types import AgentContext, CompletionModel +from uniharness.harness import BUILTIN_REMINDERS, DEFAULT_SKILL_PATHS, EnvironmentResolver, PermissionGate, SkillResolver, task_completion_reminder +from uniharness.harness.model import _FALLBACK_COMPACTION_THRESHOLD, ModelProfile +from uniharness.langchain.middleware import AgentMiddleware +from uniharness.langchain.subagent import LangChainSubagentRunner +from uniharness.prompts import FRESH_SESSION, RESUMED_SESSION, compose +from uniharness.tasks import TaskRegistry +from uniharness.tools import SkillTool, TodoWriteTool, create_cli_tools, create_web_tools +from uniharness.tools.task import TaskOutputTool, TaskStopTool +from uniharness.tools.task.agent import AgentTool +from uniharness.trace import init_langchain_tracing +from uniharness.types import AgentContext, CompletionModel if TYPE_CHECKING: from collections.abc import AsyncIterator, Mapping, Sequence @@ -37,13 +37,13 @@ from langgraph.graph.state import CompiledStateGraph from langgraph.types import Checkpointer - from hexagent.computer import Computer - from hexagent.harness import Reminder - from hexagent.harness.definition import AgentDefinition - from hexagent.mcp import McpClient - from hexagent.tools.base import BaseAgentTool - from hexagent.tools.web import FetchProvider, SearchProvider - from hexagent.types import McpServerConfig, Skill + from uniharness.computer import Computer + from uniharness.harness import Reminder + from uniharness.harness.definition import AgentDefinition + from uniharness.mcp import McpClient + from uniharness.tools.base import BaseAgentTool + from uniharness.tools.web import FetchProvider, SearchProvider + from uniharness.types import McpServerConfig, Skill logger = logging.getLogger(__name__) @@ -52,7 +52,7 @@ class Agent: - """An HexAgent agent with managed resources. + """An UniHarness agent with managed resources. Wraps a compiled LangGraph agent and owns async resources (e.g. MCP connections) that must be cleaned up. @@ -230,9 +230,9 @@ async def create_agent( extra_tools: Sequence[BaseAgentTool[Any]] | None = None, checkpointer: Checkpointer | None = None, ) -> Agent: - """Create an HexAgent agent using LangChain. + """Create an UniHarness agent using LangChain. - HexAgent agents require a LLM that supports tool calling. + UniHarness agents require a LLM that supports tool calling. Default tools: ``Bash``, ``Read``, ``Write``, ``Edit``, ``Glob``, ``Grep``. Web tools (``WebSearch``, ``WebFetch``) are included @@ -252,7 +252,7 @@ async def create_agent( provided. mcp_servers: MCP server configurations keyed by server name. The name is used as the tool prefix (``mcp____``). - HexAgent connects to each server, discovers their tools, + UniHarness connects to each server, discovers their tools, and manages connections for the agent's lifetime. agents: Named agent definitions for subagent spawning via the Task tool. Each key becomes a ``subagent_type`` value. @@ -273,7 +273,7 @@ async def create_agent( checkpointer: LangGraph checkpointer for conversation persistence. Returns: - A configured HexAgent agent. Use as an async context manager + A configured UniHarness agent. Use as an async context manager to ensure MCP connections are cleaned up. Examples: @@ -399,7 +399,7 @@ async def create_agent( main_profile.model, middleware=[middleware], checkpointer=checkpointer, - name="HexAgent", + name="UniHarness", ).with_config({"recursion_limit": 10_000}) return Agent( @@ -423,7 +423,7 @@ async def _connect_mcps( """Connect to MCP servers and return their clients.""" if not mcp_servers: return [] - from hexagent.mcp._connector import McpConnector + from uniharness.mcp._connector import McpConnector connector = McpConnector(mcp_servers) await resources.enter_async_context(connector) @@ -494,7 +494,7 @@ async def _complete(system: str, user: str) -> str: SystemMessage(content=system), HumanMessage(content=user), ], - config={"tags": ["hexagent:tool"]}, + config={"tags": ["uniharness:tool"]}, ) return str(resp.content) diff --git a/libs/hexagent/hexagent/langchain/middleware.py b/libs/uniharness/uniharness/langchain/middleware.py similarity index 95% rename from libs/hexagent/hexagent/langchain/middleware.py rename to libs/uniharness/uniharness/langchain/middleware.py index fb8f66ac..30f4971e 100644 --- a/libs/hexagent/hexagent/langchain/middleware.py +++ b/libs/uniharness/uniharness/langchain/middleware.py @@ -1,4 +1,4 @@ -"""Agent middleware — the actual runtime for HexAgent. +"""Agent middleware — the actual runtime for UniHarness. This middleware coordinates compaction, permission gating, skill injection, image extraction, and system reminder rules within LangChain's agent @@ -33,11 +33,11 @@ from langgraph.types import Command as LangGraphCommand from langgraph.types import Overwrite as LangGraphOverwrite -from hexagent.harness import PermissionResult, evaluate_reminders -from hexagent.langchain.adapter import to_langchain_tool -from hexagent.prompts import compose, load, substitute -from hexagent.prompts.tags import SYSTEM_REMINDER_TAG -from hexagent.types import AgentContext, CompactionPhase +from uniharness.harness import PermissionResult, evaluate_reminders +from uniharness.langchain.adapter import to_langchain_tool +from uniharness.prompts import compose, load, substitute +from uniharness.prompts.tags import SYSTEM_REMINDER_TAG +from uniharness.types import AgentContext, CompactionPhase if TYPE_CHECKING: from collections.abc import Awaitable, Callable, Sequence @@ -46,12 +46,12 @@ from langchain_core.tools import BaseTool from langgraph.runtime import Runtime - from hexagent.harness.environment import EnvironmentResolver - from hexagent.harness.permission import PermissionGate - from hexagent.harness.reminders import Reminder - from hexagent.harness.skills import SkillResolver - from hexagent.prompts import SectionFn - from hexagent.types import ApprovalCallback, EnvironmentContext, Skill + from uniharness.harness.environment import EnvironmentResolver + from uniharness.harness.permission import PermissionGate + from uniharness.harness.reminders import Reminder + from uniharness.harness.skills import SkillResolver + from uniharness.prompts import SectionFn + from uniharness.types import ApprovalCallback, EnvironmentContext, Skill logger = logging.getLogger(__name__) @@ -105,7 +105,7 @@ def _supports_tool_images(model: BaseChatModel) -> bool: # Marker key in ``additional_kwargs`` to prevent double extraction. -_IMAGE_EXTRACTED = "hexagent:images_extracted" +_IMAGE_EXTRACTED = "uniharness:images_extracted" def _extract_tool_images(messages: Sequence[BaseMessage]) -> list[BaseMessage] | None: @@ -177,7 +177,7 @@ def _detect_skill_call(openai_msgs: Sequence[dict[str, Any]]) -> str | None: Returns the skill name, or ``None`` if no recent skill tool call found or if a user message already follows (already injected). """ - from hexagent.tools.skill import SkillTool + from uniharness.tools.skill import SkillTool skill_tool_name = SkillTool.name @@ -221,14 +221,14 @@ def _detect_skill_call(openai_msgs: Sequence[dict[str, Any]]) -> str | None: return None -class HexAgentState(AgentState): +class UniHarnessState(AgentState): """Extended agent state with compaction tracking.""" compaction_phase: NotRequired[CompactionPhase] class AgentMiddleware(LangChainAgentMiddleware): - """The HexAgent runtime, implemented as LangChain middleware. + """The UniHarness runtime, implemented as LangChain middleware. Coordinates: - System prompt injection (before-agent, once per invocation) @@ -243,7 +243,7 @@ class AgentMiddleware(LangChainAgentMiddleware): 3. Annotators: reminder rules (injects into last message) """ - state_schema = HexAgentState + state_schema = UniHarnessState def __init__( self, diff --git a/libs/hexagent/hexagent/langchain/subagent.py b/libs/uniharness/uniharness/langchain/subagent.py similarity index 88% rename from libs/hexagent/hexagent/langchain/subagent.py rename to libs/uniharness/uniharness/langchain/subagent.py index 99b8b421..7f31a2bf 100644 --- a/libs/hexagent/hexagent/langchain/subagent.py +++ b/libs/uniharness/uniharness/langchain/subagent.py @@ -1,7 +1,7 @@ """LangChain-specific subagent runner. Provides the concrete LangChain-based runner that satisfies the -:class:`~hexagent.types.SubagentRunner` protocol. +:class:`~uniharness.types.SubagentRunner` protocol. Main components: @@ -14,28 +14,28 @@ import logging from typing import TYPE_CHECKING, Any -from hexagent.prompts import SUBAGENT_SESSION, compose -from hexagent.types import AgentContext, SubagentResult +from uniharness.prompts import SUBAGENT_SESSION, compose +from uniharness.types import AgentContext, SubagentResult if TYPE_CHECKING: from collections.abc import Mapping, Sequence - from hexagent.harness.definition import AgentDefinition - from hexagent.harness.environment import EnvironmentResolver - from hexagent.harness.model import ModelProfile - from hexagent.harness.permission import PermissionGate - from hexagent.harness.reminders import Reminder - from hexagent.harness.skills import SkillResolver - from hexagent.mcp import McpClient - from hexagent.tools.base import BaseAgentTool - from hexagent.types import ApprovalCallback, EnvironmentContext, Skill + from uniharness.harness.definition import AgentDefinition + from uniharness.harness.environment import EnvironmentResolver + from uniharness.harness.model import ModelProfile + from uniharness.harness.permission import PermissionGate + from uniharness.harness.reminders import Reminder + from uniharness.harness.skills import SkillResolver + from uniharness.mcp import McpClient + from uniharness.tools.base import BaseAgentTool + from uniharness.types import ApprovalCallback, EnvironmentContext, Skill logger = logging.getLogger(__name__) -SUBAGENT_EVENT_TAG_PREFIX = "hexagent:subagent:" +SUBAGENT_EVENT_TAG_PREFIX = "uniharness:subagent:" """Prefix for tags added to subagent events. -Each subagent invocation is tagged ``"hexagent:subagent:"``. +Each subagent invocation is tagged ``"uniharness:subagent:"``. Consumers can check for the prefix to detect *any* subagent event, or match the full tag to identify a specific task. Works for both foreground and background tasks. @@ -144,7 +144,7 @@ async def run( from langchain.agents import create_agent as _create_langchain_agent from langchain_core.messages import HumanMessage - from hexagent.langchain.middleware import AgentMiddleware + from uniharness.langchain.middleware import AgentMiddleware # 1. Select model type_key: str | None = None @@ -170,8 +170,8 @@ async def run( sub_skill_resolver = self._skill_resolver if has_skill_tool else None sub_reminders: list[Reminder] = [] if has_skill_tool: - from hexagent.harness.reminders import Reminder as ReminderCls - from hexagent.harness.reminders import available_skills_reminder + from uniharness.harness.reminders import Reminder as ReminderCls + from uniharness.harness.reminders import available_skills_reminder sub_reminders = [ReminderCls(rule=available_skills_reminder, position="prepend")] @@ -204,7 +204,7 @@ async def run( ) # 7. Create graph + run - graph = _create_langchain_agent(sub_profile.model, middleware=[middleware], name="HexAgent Subagent") + graph = _create_langchain_agent(sub_profile.model, middleware=[middleware], name="UniHarness Subagent") graph = graph.with_config({"recursion_limit": 10_000}) input_messages = [*prior_messages, HumanMessage(content=prompt)] if prior_messages else [HumanMessage(content=prompt)] diff --git a/libs/hexagent/hexagent/mcp/__init__.py b/libs/uniharness/uniharness/mcp/__init__.py similarity index 63% rename from libs/hexagent/hexagent/mcp/__init__.py rename to libs/uniharness/uniharness/mcp/__init__.py index 715a3afa..0f848b5d 100644 --- a/libs/hexagent/hexagent/mcp/__init__.py +++ b/libs/uniharness/uniharness/mcp/__init__.py @@ -1,11 +1,11 @@ -"""MCP (Model Context Protocol) connector for HexAgent. +"""MCP (Model Context Protocol) connector for UniHarness. Connects to remote MCP servers, discovers their tools, and integrates -them into the HexAgent tool pipeline. +them into the UniHarness tool pipeline. Usage:: - from hexagent import create_agent + from uniharness import create_agent async with await create_agent( model, @@ -17,8 +17,8 @@ result = await agent.ainvoke({"messages": [...]}) """ -from hexagent.mcp._client import McpClient -from hexagent.mcp._tool import McpTool +from uniharness.mcp._client import McpClient +from uniharness.mcp._tool import McpTool __all__ = [ "McpClient", diff --git a/libs/hexagent/hexagent/mcp/_client.py b/libs/uniharness/uniharness/mcp/_client.py similarity index 97% rename from libs/hexagent/hexagent/mcp/_client.py rename to libs/uniharness/uniharness/mcp/_client.py index 8536e912..52c0b6cb 100644 --- a/libs/hexagent/hexagent/mcp/_client.py +++ b/libs/uniharness/uniharness/mcp/_client.py @@ -18,15 +18,15 @@ from mcp.client.streamable_http import streamable_http_client from mcp.types import PaginatedRequestParams, Tool -from hexagent.mcp._schema import json_schema_to_model -from hexagent.mcp._tool import McpTool +from uniharness.mcp._schema import json_schema_to_model +from uniharness.mcp._tool import McpTool if TYPE_CHECKING: from types import TracebackType from pydantic import BaseModel - from hexagent.types import McpHttpServerConfig, McpServerConfig, McpSseServerConfig, McpStdioServerConfig + from uniharness.types import McpHttpServerConfig, McpServerConfig, McpSseServerConfig, McpStdioServerConfig logger = logging.getLogger(__name__) diff --git a/libs/hexagent/hexagent/mcp/_connector.py b/libs/uniharness/uniharness/mcp/_connector.py similarity index 97% rename from libs/hexagent/hexagent/mcp/_connector.py rename to libs/uniharness/uniharness/mcp/_connector.py index a0c74e78..9eedd63c 100644 --- a/libs/hexagent/hexagent/mcp/_connector.py +++ b/libs/uniharness/uniharness/mcp/_connector.py @@ -12,13 +12,13 @@ from contextlib import AsyncExitStack from typing import TYPE_CHECKING, Self -from hexagent.mcp._client import McpClient +from uniharness.mcp._client import McpClient if TYPE_CHECKING: from collections.abc import Mapping from types import TracebackType - from hexagent.types import McpServerConfig + from uniharness.types import McpServerConfig logger = logging.getLogger(__name__) diff --git a/libs/hexagent/hexagent/mcp/_schema.py b/libs/uniharness/uniharness/mcp/_schema.py similarity index 100% rename from libs/hexagent/hexagent/mcp/_schema.py rename to libs/uniharness/uniharness/mcp/_schema.py diff --git a/libs/hexagent/hexagent/mcp/_tool.py b/libs/uniharness/uniharness/mcp/_tool.py similarity index 94% rename from libs/hexagent/hexagent/mcp/_tool.py rename to libs/uniharness/uniharness/mcp/_tool.py index 1ba23921..9683074f 100644 --- a/libs/hexagent/hexagent/mcp/_tool.py +++ b/libs/uniharness/uniharness/mcp/_tool.py @@ -12,8 +12,8 @@ from pydantic import BaseModel -from hexagent.tools.base import BaseAgentTool -from hexagent.types import Base64Source, ImageContent, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import Base64Source, ImageContent, ToolResult if TYPE_CHECKING: import asyncio @@ -75,7 +75,7 @@ async def execute(self, params: BaseModel) -> ToolResult: def _convert_result(result: CallToolResult) -> ToolResult: - """Convert an MCP CallToolResult to an HexAgent ToolResult. + """Convert an MCP CallToolResult to an UniHarness ToolResult. Args: result: The CallToolResult from ``session.call_tool()``. diff --git a/libs/hexagent/hexagent/prompts/__init__.py b/libs/uniharness/uniharness/prompts/__init__.py similarity index 93% rename from libs/hexagent/hexagent/prompts/__init__.py rename to libs/uniharness/uniharness/prompts/__init__.py index 74131cac..235dadef 100644 --- a/libs/hexagent/hexagent/prompts/__init__.py +++ b/libs/uniharness/uniharness/prompts/__init__.py @@ -10,9 +10,9 @@ from collections.abc import Callable, Sequence -from hexagent.prompts import sections -from hexagent.prompts.content import find, load, substitute -from hexagent.types import AgentContext, GitContext +from uniharness.prompts import sections +from uniharness.prompts.content import find, load, substitute +from uniharness.types import AgentContext, GitContext SectionFn = Callable[[AgentContext], str | None] """A section function: takes context, returns content or None to opt out.""" diff --git a/libs/hexagent/hexagent/prompts/content.py b/libs/uniharness/uniharness/prompts/content.py similarity index 95% rename from libs/hexagent/hexagent/prompts/content.py rename to libs/uniharness/uniharness/prompts/content.py index e9e2a33e..f930e5b4 100644 --- a/libs/hexagent/hexagent/prompts/content.py +++ b/libs/uniharness/uniharness/prompts/content.py @@ -21,7 +21,7 @@ @functools.cache def _scan_package_keys() -> frozenset[str]: """Discover all .md fragment keys in the package.""" - package = importlib.resources.files("hexagent.prompts.fragments") + package = importlib.resources.files("uniharness.prompts.fragments") keys: set[str] = set() for item in package.iterdir(): if item.is_file() and item.name.endswith(".md"): @@ -45,7 +45,7 @@ def load(key: str) -> str: Raises: KeyError: If no fragment with the given key exists. """ - package = importlib.resources.files("hexagent.prompts.fragments") + package = importlib.resources.files("uniharness.prompts.fragments") resource = package.joinpath(f"{key}.md") try: return resource.read_text(encoding="utf-8").strip() diff --git a/libs/uniharness/uniharness/prompts/fragments/__init__.py b/libs/uniharness/uniharness/prompts/fragments/__init__.py new file mode 100644 index 00000000..43d5d578 --- /dev/null +++ b/libs/uniharness/uniharness/prompts/fragments/__init__.py @@ -0,0 +1 @@ +"""Markdown prompt fragments loaded by :mod:`uniharness.prompts.content`.""" diff --git a/libs/hexagent/hexagent/prompts/fragments/agent_prompt_webfetch_summarizer.md b/libs/uniharness/uniharness/prompts/fragments/agent_prompt_webfetch_summarizer.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/agent_prompt_webfetch_summarizer.md rename to libs/uniharness/uniharness/prompts/fragments/agent_prompt_webfetch_summarizer.md diff --git a/libs/hexagent/hexagent/prompts/fragments/agent_prompt_websearch_summarizer.md b/libs/uniharness/uniharness/prompts/fragments/agent_prompt_websearch_summarizer.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/agent_prompt_websearch_summarizer.md rename to libs/uniharness/uniharness/prompts/fragments/agent_prompt_websearch_summarizer.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_agency.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_agency.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_agency.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_agency.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_computer_use.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_computer_use.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_computer_use.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_computer_use.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_doing_tasks.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_doing_tasks.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_doing_tasks.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_doing_tasks.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_executing_actions_with_care.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_executing_actions_with_care.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_executing_actions_with_care.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_executing_actions_with_care.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_git_status.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_git_status.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_git_status.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_git_status.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_identity.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_identity.md similarity index 60% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_identity.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_identity.md index 4cf3a276..4c37046e 100644 --- a/libs/hexagent/hexagent/prompts/fragments/system_prompt_identity.md +++ b/libs/uniharness/uniharness/prompts/fragments/system_prompt_identity.md @@ -1,3 +1,3 @@ -You are HexAgent, a powerful interactive agent designed to help users with a wide range of tasks. +You are UniHarness, a powerful interactive agent designed to help users with a wide range of tasks. You work on a computer to complete tasks primarily via software engineering. Use the instructions below and the tools available to you to assist the user. diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_scratchpad_directory.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_scratchpad_directory.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_scratchpad_directory.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_scratchpad_directory.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_tone_and_style.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_tone_and_style.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_tone_and_style.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_tone_and_style.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_prompt_using_your_tools.md b/libs/uniharness/uniharness/prompts/fragments/system_prompt_using_your_tools.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_prompt_using_your_tools.md rename to libs/uniharness/uniharness/prompts/fragments/system_prompt_using_your_tools.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_reminder_initial_available_skills.md b/libs/uniharness/uniharness/prompts/fragments/system_reminder_initial_available_skills.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_reminder_initial_available_skills.md rename to libs/uniharness/uniharness/prompts/fragments/system_reminder_initial_available_skills.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_reminder_initial_instruction_memory_md.md b/libs/uniharness/uniharness/prompts/fragments/system_reminder_initial_instruction_memory_md.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_reminder_initial_instruction_memory_md.md rename to libs/uniharness/uniharness/prompts/fragments/system_reminder_initial_instruction_memory_md.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_reminder_skill_launch_failure.md b/libs/uniharness/uniharness/prompts/fragments/system_reminder_skill_launch_failure.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_reminder_skill_launch_failure.md rename to libs/uniharness/uniharness/prompts/fragments/system_reminder_skill_launch_failure.md diff --git a/libs/hexagent/hexagent/prompts/fragments/system_reminder_todowrite_reminder.md b/libs/uniharness/uniharness/prompts/fragments/system_reminder_todowrite_reminder.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/system_reminder_todowrite_reminder.md rename to libs/uniharness/uniharness/prompts/fragments/system_reminder_todowrite_reminder.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_agent.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_agent.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_agent.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_agent.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_bash.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_bash.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_bash.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_bash.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_bash_git_commit_and_pr_creation_instructions.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_bash_git_commit_and_pr_creation_instructions.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_bash_git_commit_and_pr_creation_instructions.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_bash_git_commit_and_pr_creation_instructions.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_edit.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_edit.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_edit.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_edit.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_glob.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_glob.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_glob.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_glob.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_grep.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_grep.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_grep.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_grep.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_presenttouser.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_presenttouser.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_presenttouser.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_presenttouser.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_read.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_read.md similarity index 91% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_read.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_read.md index 9fb1b8a7..52c919cb 100644 --- a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_read.md +++ b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_read.md @@ -7,7 +7,7 @@ Usage: - You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters - Any lines longer than 2000 characters will be truncated - Results are returned using cat -n format, with line numbers starting at 1 -- This tool allows HexAgent to read images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as HexAgent is a multimodal LLM. +- This tool allows UniHarness to read images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as UniHarness is a multimodal LLM. - This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations. - This tool can only read files, not directories. To read a directory, use an ls command via the ${BASH_TOOL_NAME} tool. diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_skill.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_skill.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_skill.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_skill.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_taskoutput.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_taskoutput.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_taskoutput.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_taskoutput.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_taskstop.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_taskstop.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_taskstop.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_taskstop.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_todowrite.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_todowrite.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_todowrite.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_todowrite.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_webfetch.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_webfetch.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_webfetch.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_webfetch.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_websearch.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_websearch.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_websearch.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_websearch.md diff --git a/libs/hexagent/hexagent/prompts/fragments/tool_instruction_write.md b/libs/uniharness/uniharness/prompts/fragments/tool_instruction_write.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/tool_instruction_write.md rename to libs/uniharness/uniharness/prompts/fragments/tool_instruction_write.md diff --git a/libs/hexagent/hexagent/prompts/fragments/user_prompt_compaction_request.md b/libs/uniharness/uniharness/prompts/fragments/user_prompt_compaction_request.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/user_prompt_compaction_request.md rename to libs/uniharness/uniharness/prompts/fragments/user_prompt_compaction_request.md diff --git a/libs/hexagent/hexagent/prompts/fragments/user_prompt_compaction_summary_rebuild.md b/libs/uniharness/uniharness/prompts/fragments/user_prompt_compaction_summary_rebuild.md similarity index 100% rename from libs/hexagent/hexagent/prompts/fragments/user_prompt_compaction_summary_rebuild.md rename to libs/uniharness/uniharness/prompts/fragments/user_prompt_compaction_summary_rebuild.md diff --git a/libs/hexagent/hexagent/prompts/sections.py b/libs/uniharness/uniharness/prompts/sections.py similarity index 97% rename from libs/hexagent/hexagent/prompts/sections.py rename to libs/uniharness/uniharness/prompts/sections.py index 84fb9cba..bfc65811 100644 --- a/libs/hexagent/hexagent/prompts/sections.py +++ b/libs/uniharness/uniharness/prompts/sections.py @@ -10,11 +10,11 @@ from datetime import date from typing import TYPE_CHECKING -from hexagent.prompts.content import find, load, substitute +from uniharness.prompts.content import find, load, substitute if TYPE_CHECKING: - from hexagent.harness.definition import AgentDefinition - from hexagent.types import AgentContext + from uniharness.harness.definition import AgentDefinition + from uniharness.types import AgentContext # --------------------------------------------------------------------------- diff --git a/libs/hexagent/hexagent/prompts/tags.py b/libs/uniharness/uniharness/prompts/tags.py similarity index 100% rename from libs/hexagent/hexagent/prompts/tags.py rename to libs/uniharness/uniharness/prompts/tags.py diff --git a/libs/hexagent/hexagent/tasks.py b/libs/uniharness/uniharness/tasks.py similarity index 99% rename from libs/hexagent/hexagent/tasks.py rename to libs/uniharness/uniharness/tasks.py index e29360de..1c810074 100644 --- a/libs/hexagent/hexagent/tasks.py +++ b/libs/uniharness/uniharness/tasks.py @@ -15,7 +15,7 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING, Literal -from hexagent.types import ToolResult +from uniharness.types import ToolResult if TYPE_CHECKING: from collections.abc import Coroutine diff --git a/libs/hexagent/hexagent/tools/__init__.py b/libs/uniharness/uniharness/tools/__init__.py similarity index 76% rename from libs/hexagent/hexagent/tools/__init__.py rename to libs/uniharness/uniharness/tools/__init__.py index 09b9e05d..323ef9f5 100644 --- a/libs/hexagent/hexagent/tools/__init__.py +++ b/libs/uniharness/uniharness/tools/__init__.py @@ -1,4 +1,4 @@ -"""Tool implementations for hexagent. +"""Tool implementations for uniharness. This module provides concrete tool implementations that follow Anthropic's tool patterns. Tools in this module depend on core/ for result types and @@ -27,13 +27,13 @@ - create_filesystem_tools: Create file operation tools (read, write, edit, glob, grep) - create_cli_tools: Create all CLI tools sharing a Computer instance -For LangChain integration, see hexagent.langchain module. +For LangChain integration, see uniharness.langchain module. """ from typing import Any -from hexagent.tools.base import BaseAgentTool -from hexagent.tools.cli import ( +from uniharness.tools.base import BaseAgentTool +from uniharness.tools.cli import ( BashTool, EditTool, GlobTool, @@ -44,17 +44,17 @@ create_cli_tools, create_filesystem_tools, ) -from hexagent.tools.skill import SkillTool -from hexagent.tools.task import TaskOutputTool, TaskStopTool -from hexagent.tools.task.agent import AgentTool -from hexagent.tools.todo import TodoWriteTool -from hexagent.tools.ui import PresentToUserTool -from hexagent.tools.web import ( +from uniharness.tools.skill import SkillTool +from uniharness.tools.task import TaskOutputTool, TaskStopTool +from uniharness.tools.task.agent import AgentTool +from uniharness.tools.todo import TodoWriteTool +from uniharness.tools.ui import PresentToUserTool +from uniharness.tools.web import ( WebFetchTool, WebSearchTool, create_web_tools, ) -from hexagent.types import SubagentResult, SubagentRunner +from uniharness.types import SubagentResult, SubagentRunner BUILTIN_TOOLS: tuple[type[BaseAgentTool[Any]], ...] = ( BashTool, @@ -70,12 +70,12 @@ ) """The canonical set of built-in tool classes. -HexAgent always has a computer — these tools are non-negotiable. +UniHarness always has a computer — these tools are non-negotiable. Everything that needs to know "what tools exist" derives from this tuple (template variables, prompt fragment lookup, etc.). Note: AgentTool lives in ``tools/task/agent.py`` and depends on the -:class:`~hexagent.types.SubagentRunner` protocol. TaskOutputTool and +:class:`~uniharness.types.SubagentRunner` protocol. TaskOutputTool and TaskStopTool live in ``tools/task/`` and are assembled alongside AgentTool by the agent factory. """ diff --git a/libs/hexagent/hexagent/tools/base.py b/libs/uniharness/uniharness/tools/base.py similarity index 98% rename from libs/hexagent/hexagent/tools/base.py rename to libs/uniharness/uniharness/tools/base.py index 138e06b9..10de734b 100644 --- a/libs/hexagent/hexagent/tools/base.py +++ b/libs/uniharness/uniharness/tools/base.py @@ -10,7 +10,7 @@ from pydantic import BaseModel, ValidationError -from hexagent.types import ToolResult +from uniharness.types import ToolResult ParamsT = TypeVar("ParamsT", bound=BaseModel) diff --git a/libs/hexagent/hexagent/tools/cli/__init__.py b/libs/uniharness/uniharness/tools/cli/__init__.py similarity index 84% rename from libs/hexagent/hexagent/tools/cli/__init__.py rename to libs/uniharness/uniharness/tools/cli/__init__.py index d952cc35..f56a2f5d 100644 --- a/libs/hexagent/hexagent/tools/cli/__init__.py +++ b/libs/uniharness/uniharness/tools/cli/__init__.py @@ -21,17 +21,17 @@ from typing import TYPE_CHECKING, Any -from hexagent.tools.cli.bash import BashTool -from hexagent.tools.cli.edit import EditTool -from hexagent.tools.cli.glob import GlobTool -from hexagent.tools.cli.grep import GrepTool -from hexagent.tools.cli.read import ReadTool -from hexagent.tools.cli.write import WriteTool +from uniharness.tools.cli.bash import BashTool +from uniharness.tools.cli.edit import EditTool +from uniharness.tools.cli.glob import GlobTool +from uniharness.tools.cli.grep import GrepTool +from uniharness.tools.cli.read import ReadTool +from uniharness.tools.cli.write import WriteTool if TYPE_CHECKING: - from hexagent.computer import Computer - from hexagent.tasks import TaskRegistry - from hexagent.tools.base import BaseAgentTool + from uniharness.computer import Computer + from uniharness.tasks import TaskRegistry + from uniharness.tools.base import BaseAgentTool def create_bash_tool(computer: Computer, registry: TaskRegistry) -> BashTool: @@ -62,8 +62,8 @@ def create_filesystem_tools(computer: Computer) -> list[BaseAgentTool[Any]]: Example: ```python - from hexagent.computer import LocalComputer - from hexagent.tools.cli import create_filesystem_tools + from uniharness.computer import LocalComputer + from uniharness.tools.cli import create_filesystem_tools computer = LocalComputer() fs_tools = create_filesystem_tools(computer) diff --git a/libs/hexagent/hexagent/tools/cli/bash.py b/libs/uniharness/uniharness/tools/cli/bash.py similarity index 93% rename from libs/hexagent/hexagent/tools/cli/bash.py rename to libs/uniharness/uniharness/tools/cli/bash.py index b5261b7c..45d26bbd 100644 --- a/libs/hexagent/hexagent/tools/cli/bash.py +++ b/libs/uniharness/uniharness/tools/cli/bash.py @@ -10,13 +10,13 @@ import secrets from typing import TYPE_CHECKING, Literal -from hexagent.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError -from hexagent.tools.base import BaseAgentTool -from hexagent.types import BashToolParams, CLIResult, ToolResult +from uniharness.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError +from uniharness.tools.base import BaseAgentTool +from uniharness.types import BashToolParams, CLIResult, ToolResult if TYPE_CHECKING: - from hexagent.computer import Computer - from hexagent.tasks import TaskRegistry + from uniharness.computer import Computer + from uniharness.tasks import TaskRegistry _FOREGROUND_TIMEOUT_MS = 120_000 # 2 minutes default for foreground commands diff --git a/libs/hexagent/hexagent/tools/cli/edit.py b/libs/uniharness/uniharness/tools/cli/edit.py similarity index 96% rename from libs/hexagent/hexagent/tools/cli/edit.py rename to libs/uniharness/uniharness/tools/cli/edit.py index baffaf08..ec5bb762 100644 --- a/libs/hexagent/hexagent/tools/cli/edit.py +++ b/libs/uniharness/uniharness/tools/cli/edit.py @@ -18,12 +18,12 @@ import shlex from typing import TYPE_CHECKING, Literal -from hexagent.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError -from hexagent.tools.base import BaseAgentTool -from hexagent.types import CLIResult, EditToolParams, ToolResult +from uniharness.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError +from uniharness.tools.base import BaseAgentTool +from uniharness.types import CLIResult, EditToolParams, ToolResult if TYPE_CHECKING: - from hexagent.computer import Computer + from uniharness.computer import Computer # --------------------------------------------------------------------------- # Python script executed on the target computer. diff --git a/libs/hexagent/hexagent/tools/cli/glob.py b/libs/uniharness/uniharness/tools/cli/glob.py similarity index 94% rename from libs/hexagent/hexagent/tools/cli/glob.py rename to libs/uniharness/uniharness/tools/cli/glob.py index 1262a5dd..be241ad9 100644 --- a/libs/hexagent/hexagent/tools/cli/glob.py +++ b/libs/uniharness/uniharness/tools/cli/glob.py @@ -9,12 +9,12 @@ import shlex from typing import TYPE_CHECKING, Literal -from hexagent.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError -from hexagent.tools.base import BaseAgentTool -from hexagent.types import CLIResult, GlobToolParams, ToolResult +from uniharness.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError +from uniharness.tools.base import BaseAgentTool +from uniharness.types import CLIResult, GlobToolParams, ToolResult if TYPE_CHECKING: - from hexagent.computer import Computer + from uniharness.computer import Computer _MAX_RESULTS = 100 diff --git a/libs/hexagent/hexagent/tools/cli/grep.py b/libs/uniharness/uniharness/tools/cli/grep.py similarity index 97% rename from libs/hexagent/hexagent/tools/cli/grep.py rename to libs/uniharness/uniharness/tools/cli/grep.py index 3bcaf727..1675d6a9 100644 --- a/libs/hexagent/hexagent/tools/cli/grep.py +++ b/libs/uniharness/uniharness/tools/cli/grep.py @@ -12,12 +12,12 @@ import shlex from typing import TYPE_CHECKING, Literal -from hexagent.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError -from hexagent.tools.base import BaseAgentTool -from hexagent.types import CLIResult, GrepToolParams, ToolResult +from uniharness.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError +from uniharness.tools.base import BaseAgentTool +from uniharness.types import CLIResult, GrepToolParams, ToolResult if TYPE_CHECKING: - from hexagent.computer import Computer + from uniharness.computer import Computer # ripgrep exit codes: 0 = matches found, 1 = no matches, >= 2 = error diff --git a/libs/hexagent/hexagent/tools/cli/read.py b/libs/uniharness/uniharness/tools/cli/read.py similarity index 97% rename from libs/hexagent/hexagent/tools/cli/read.py rename to libs/uniharness/uniharness/tools/cli/read.py index b88cc335..a4e09652 100644 --- a/libs/hexagent/hexagent/tools/cli/read.py +++ b/libs/uniharness/uniharness/tools/cli/read.py @@ -13,12 +13,12 @@ import shlex from typing import TYPE_CHECKING, Literal -from hexagent.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError -from hexagent.tools.base import BaseAgentTool -from hexagent.types import Base64Source, CLIResult, ReadToolParams, ToolResult +from uniharness.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError +from uniharness.tools.base import BaseAgentTool +from uniharness.types import Base64Source, CLIResult, ReadToolParams, ToolResult if TYPE_CHECKING: - from hexagent.computer import Computer + from uniharness.computer import Computer _MAX_LINE_LENGTH = 2000 _LINE_SEPARATOR = "→" diff --git a/libs/hexagent/hexagent/tools/cli/write.py b/libs/uniharness/uniharness/tools/cli/write.py similarity index 96% rename from libs/hexagent/hexagent/tools/cli/write.py rename to libs/uniharness/uniharness/tools/cli/write.py index 76ca27a8..f66fb9c5 100644 --- a/libs/hexagent/hexagent/tools/cli/write.py +++ b/libs/uniharness/uniharness/tools/cli/write.py @@ -15,12 +15,12 @@ import json from typing import TYPE_CHECKING, Literal -from hexagent.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError -from hexagent.tools.base import BaseAgentTool -from hexagent.types import CLIResult, ToolResult, WriteToolParams +from uniharness.exceptions import CLI_INFRA_ERROR_SYSTEM_REMINDER, CLIError +from uniharness.tools.base import BaseAgentTool +from uniharness.types import CLIResult, ToolResult, WriteToolParams if TYPE_CHECKING: - from hexagent.computer import Computer + from uniharness.computer import Computer # --------------------------------------------------------------------------- # Python script executed on the (possibly remote) Computer. diff --git a/libs/hexagent/hexagent/tools/skill.py b/libs/uniharness/uniharness/tools/skill.py similarity index 82% rename from libs/hexagent/hexagent/tools/skill.py rename to libs/uniharness/uniharness/tools/skill.py index d1f4c96e..8905913f 100644 --- a/libs/hexagent/hexagent/tools/skill.py +++ b/libs/uniharness/uniharness/tools/skill.py @@ -4,17 +4,17 @@ from typing import TYPE_CHECKING, Literal -from hexagent.tools.base import BaseAgentTool -from hexagent.types import SkillToolParams, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import SkillToolParams, ToolResult if TYPE_CHECKING: - from hexagent.types import SkillCatalog + from uniharness.types import SkillCatalog class SkillTool(BaseAgentTool[SkillToolParams]): """Tool for invoking skills by name. - Delegates validation to a :class:`~hexagent.types.SkillCatalog`, + Delegates validation to a :class:`~uniharness.types.SkillCatalog`, which handles caching and mid-session re-discovery internally. Actual skill content injection is handled by the middleware. diff --git a/libs/uniharness/uniharness/tools/task/__init__.py b/libs/uniharness/uniharness/tools/task/__init__.py new file mode 100644 index 00000000..4ae9abc2 --- /dev/null +++ b/libs/uniharness/uniharness/tools/task/__init__.py @@ -0,0 +1,15 @@ +"""Framework-agnostic task tools. + +These tools operate against a :class:`~uniharness.tasks.TaskRegistry` +and are assembled by the agent factory. +""" + +from uniharness.tools.task.agent import AgentTool +from uniharness.tools.task.output import TaskOutputTool +from uniharness.tools.task.stop import TaskStopTool + +__all__ = [ + "AgentTool", + "TaskOutputTool", + "TaskStopTool", +] diff --git a/libs/hexagent/hexagent/tools/task/agent.py b/libs/uniharness/uniharness/tools/task/agent.py similarity index 92% rename from libs/hexagent/hexagent/tools/task/agent.py rename to libs/uniharness/uniharness/tools/task/agent.py index f3968b0f..9a543cfc 100644 --- a/libs/hexagent/hexagent/tools/task/agent.py +++ b/libs/uniharness/uniharness/tools/task/agent.py @@ -1,8 +1,8 @@ """AgentTool — agent-facing tool for spawning subagents. -The :class:`~hexagent.types.SubagentRunner` protocol and -:class:`~hexagent.types.SubagentResult` data type live in -:mod:`hexagent.types`. +The :class:`~uniharness.types.SubagentRunner` protocol and +:class:`~uniharness.types.SubagentResult` data type live in +:mod:`uniharness.types`. """ from __future__ import annotations @@ -11,14 +11,14 @@ import secrets from typing import TYPE_CHECKING, Any -from hexagent.tools.base import BaseAgentTool -from hexagent.types import AgentToolParams, SubagentRunner, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import AgentToolParams, SubagentRunner, ToolResult if TYPE_CHECKING: from collections.abc import Mapping - from hexagent.harness.definition import AgentDefinition - from hexagent.tasks import TaskRegistry + from uniharness.harness.definition import AgentDefinition + from uniharness.tasks import TaskRegistry logger = logging.getLogger(__name__) diff --git a/libs/hexagent/hexagent/tools/task/output.py b/libs/uniharness/uniharness/tools/task/output.py similarity index 90% rename from libs/hexagent/hexagent/tools/task/output.py rename to libs/uniharness/uniharness/tools/task/output.py index f7515acb..82bff597 100644 --- a/libs/hexagent/hexagent/tools/task/output.py +++ b/libs/uniharness/uniharness/tools/task/output.py @@ -4,11 +4,11 @@ from typing import TYPE_CHECKING -from hexagent.tools.base import BaseAgentTool -from hexagent.types import TaskOutputToolParams, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import TaskOutputToolParams, ToolResult if TYPE_CHECKING: - from hexagent.tasks import TaskRegistry + from uniharness.tasks import TaskRegistry class TaskOutputTool(BaseAgentTool[TaskOutputToolParams]): diff --git a/libs/hexagent/hexagent/tools/task/stop.py b/libs/uniharness/uniharness/tools/task/stop.py similarity index 87% rename from libs/hexagent/hexagent/tools/task/stop.py rename to libs/uniharness/uniharness/tools/task/stop.py index ad15d301..27f650cd 100644 --- a/libs/hexagent/hexagent/tools/task/stop.py +++ b/libs/uniharness/uniharness/tools/task/stop.py @@ -4,11 +4,11 @@ from typing import TYPE_CHECKING -from hexagent.tools.base import BaseAgentTool -from hexagent.types import TaskStopToolParams, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import TaskStopToolParams, ToolResult if TYPE_CHECKING: - from hexagent.tasks import TaskRegistry + from uniharness.tasks import TaskRegistry class TaskStopTool(BaseAgentTool[TaskStopToolParams]): diff --git a/libs/hexagent/hexagent/tools/todo/__init__.py b/libs/uniharness/uniharness/tools/todo/__init__.py similarity index 52% rename from libs/hexagent/hexagent/tools/todo/__init__.py rename to libs/uniharness/uniharness/tools/todo/__init__.py index 1f0d65ac..bc6dc984 100644 --- a/libs/hexagent/hexagent/tools/todo/__init__.py +++ b/libs/uniharness/uniharness/tools/todo/__init__.py @@ -1,6 +1,6 @@ """Todo tracking tools.""" -from hexagent.tools.todo.todowrite import TodoWriteTool +from uniharness.tools.todo.todowrite import TodoWriteTool __all__ = [ "TodoWriteTool", diff --git a/libs/hexagent/hexagent/tools/todo/todowrite.py b/libs/uniharness/uniharness/tools/todo/todowrite.py similarity index 94% rename from libs/hexagent/hexagent/tools/todo/todowrite.py rename to libs/uniharness/uniharness/tools/todo/todowrite.py index e0411502..d5cc1b9a 100644 --- a/libs/hexagent/hexagent/tools/todo/todowrite.py +++ b/libs/uniharness/uniharness/tools/todo/todowrite.py @@ -8,8 +8,8 @@ from typing import Literal -from hexagent.tools.base import BaseAgentTool -from hexagent.types import TodoItem, TodoWriteToolParams, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import TodoItem, TodoWriteToolParams, ToolResult class TodoWriteTool(BaseAgentTool[TodoWriteToolParams]): diff --git a/libs/hexagent/hexagent/tools/ui/__init__.py b/libs/uniharness/uniharness/tools/ui/__init__.py similarity index 58% rename from libs/hexagent/hexagent/tools/ui/__init__.py rename to libs/uniharness/uniharness/tools/ui/__init__.py index 9d592333..44a63042 100644 --- a/libs/hexagent/hexagent/tools/ui/__init__.py +++ b/libs/uniharness/uniharness/tools/ui/__init__.py @@ -1,6 +1,6 @@ """UI tools for presenting content to the user.""" -from hexagent.tools.ui.present_to_user import PresentToUserTool +from uniharness.tools.ui.present_to_user import PresentToUserTool __all__ = [ "PresentToUserTool", diff --git a/libs/hexagent/hexagent/tools/ui/present_to_user.py b/libs/uniharness/uniharness/tools/ui/present_to_user.py similarity index 98% rename from libs/hexagent/hexagent/tools/ui/present_to_user.py rename to libs/uniharness/uniharness/tools/ui/present_to_user.py index b9b5df39..7371843b 100644 --- a/libs/hexagent/hexagent/tools/ui/present_to_user.py +++ b/libs/uniharness/uniharness/tools/ui/present_to_user.py @@ -9,11 +9,11 @@ import shlex from typing import TYPE_CHECKING, Literal -from hexagent.tools.base import BaseAgentTool -from hexagent.types import PresentToUserToolParams, ToolResult +from uniharness.tools.base import BaseAgentTool +from uniharness.types import PresentToUserToolParams, ToolResult if TYPE_CHECKING: - from hexagent.computer.base import Computer + from uniharness.computer.base import Computer # Delimiter used to separate per-file result lines from the bash script. # Chosen to be unlikely to appear in file paths or MIME types. diff --git a/libs/hexagent/hexagent/tools/web/__init__.py b/libs/uniharness/uniharness/tools/web/__init__.py similarity index 82% rename from libs/hexagent/hexagent/tools/web/__init__.py rename to libs/uniharness/uniharness/tools/web/__init__.py index 415d9e45..baf06566 100644 --- a/libs/hexagent/hexagent/tools/web/__init__.py +++ b/libs/uniharness/uniharness/tools/web/__init__.py @@ -12,7 +12,7 @@ - create_web_tools: Create web tools when providers are supplied Example: - >>> from hexagent.tools.web import WebSearchTool, TavilySearchProvider + >>> from uniharness.tools.web import WebSearchTool, TavilySearchProvider >>> tool = WebSearchTool(TavilySearchProvider()) """ @@ -20,9 +20,9 @@ from typing import TYPE_CHECKING, Any -from hexagent.tools.web._cache import clear_caches -from hexagent.tools.web.fetch import WebFetchTool -from hexagent.tools.web.providers import ( +from uniharness.tools.web._cache import clear_caches +from uniharness.tools.web.fetch import WebFetchTool +from uniharness.tools.web.providers import ( BraveSearchProvider, FetchProvider, FirecrawlFetchProvider, @@ -30,11 +30,11 @@ SearchProvider, TavilySearchProvider, ) -from hexagent.tools.web.search import WebSearchTool +from uniharness.tools.web.search import WebSearchTool if TYPE_CHECKING: - from hexagent.tools.base import BaseAgentTool - from hexagent.types import CompletionModel + from uniharness.tools.base import BaseAgentTool + from uniharness.types import CompletionModel def create_web_tools( diff --git a/libs/hexagent/hexagent/tools/web/_cache.py b/libs/uniharness/uniharness/tools/web/_cache.py similarity index 90% rename from libs/hexagent/hexagent/tools/web/_cache.py rename to libs/uniharness/uniharness/tools/web/_cache.py index 8ab1e1ad..40c94f9b 100644 --- a/libs/hexagent/hexagent/tools/web/_cache.py +++ b/libs/uniharness/uniharness/tools/web/_cache.py @@ -11,8 +11,8 @@ from cachetools import TTLCache if TYPE_CHECKING: - from hexagent.tools.web.providers.fetch.base import FetchResult - from hexagent.tools.web.providers.search.base import SearchResult + from uniharness.tools.web.providers.fetch.base import FetchResult + from uniharness.tools.web.providers.search.base import SearchResult # Default TTL: 15 minutes DEFAULT_TTL_SECONDS = 900 diff --git a/libs/hexagent/hexagent/tools/web/_markdown.py b/libs/uniharness/uniharness/tools/web/_markdown.py similarity index 100% rename from libs/hexagent/hexagent/tools/web/_markdown.py rename to libs/uniharness/uniharness/tools/web/_markdown.py diff --git a/libs/hexagent/hexagent/tools/web/_validation.py b/libs/uniharness/uniharness/tools/web/_validation.py similarity index 100% rename from libs/hexagent/hexagent/tools/web/_validation.py rename to libs/uniharness/uniharness/tools/web/_validation.py diff --git a/libs/hexagent/hexagent/tools/web/fetch.py b/libs/uniharness/uniharness/tools/web/fetch.py similarity index 90% rename from libs/hexagent/hexagent/tools/web/fetch.py rename to libs/uniharness/uniharness/tools/web/fetch.py index 52c55df1..3d649b5c 100644 --- a/libs/hexagent/hexagent/tools/web/fetch.py +++ b/libs/uniharness/uniharness/tools/web/fetch.py @@ -9,16 +9,16 @@ import httpx -from hexagent.exceptions import ConfigurationError, ToolError, WebAPIError -from hexagent.prompts.content import load, substitute -from hexagent.tools.base import BaseAgentTool -from hexagent.tools.web._cache import cache_key, get_fetch_cache -from hexagent.tools.web._validation import validate_url -from hexagent.types import ToolResult, WebFetchToolParams +from uniharness.exceptions import ConfigurationError, ToolError, WebAPIError +from uniharness.prompts.content import load, substitute +from uniharness.tools.base import BaseAgentTool +from uniharness.tools.web._cache import cache_key, get_fetch_cache +from uniharness.tools.web._validation import validate_url +from uniharness.types import ToolResult, WebFetchToolParams if TYPE_CHECKING: - from hexagent.tools.web.providers.fetch import FetchProvider - from hexagent.types import CompletionModel + from uniharness.tools.web.providers.fetch import FetchProvider + from uniharness.types import CompletionModel # Content size limits MAX_CONTENT_SIZE: Final[int] = 10_485_760 # 10MB hard limit @@ -61,7 +61,7 @@ class WebFetchTool(BaseAgentTool[WebFetchToolParams]): Examples: ```python - from hexagent.tools.web.providers.fetch import JinaFetchProvider + from uniharness.tools.web.providers.fetch import JinaFetchProvider provider = JinaFetchProvider() tool = WebFetchTool(provider) diff --git a/libs/hexagent/hexagent/tools/web/providers/__init__.py b/libs/uniharness/uniharness/tools/web/providers/__init__.py similarity index 87% rename from libs/hexagent/hexagent/tools/web/providers/__init__.py rename to libs/uniharness/uniharness/tools/web/providers/__init__.py index e3f4f4d7..5961a30e 100644 --- a/libs/hexagent/hexagent/tools/web/providers/__init__.py +++ b/libs/uniharness/uniharness/tools/web/providers/__init__.py @@ -11,13 +11,13 @@ from __future__ import annotations -from hexagent.tools.web.providers.fetch import ( +from uniharness.tools.web.providers.fetch import ( FetchProvider, FetchResult, FirecrawlFetchProvider, JinaFetchProvider, ) -from hexagent.tools.web.providers.search import ( +from uniharness.tools.web.providers.search import ( BraveSearchProvider, SearchProvider, SearchResultItem, diff --git a/libs/hexagent/hexagent/tools/web/providers/_retry.py b/libs/uniharness/uniharness/tools/web/providers/_retry.py similarity index 100% rename from libs/hexagent/hexagent/tools/web/providers/_retry.py rename to libs/uniharness/uniharness/tools/web/providers/_retry.py diff --git a/libs/hexagent/hexagent/tools/web/providers/fetch/__init__.py b/libs/uniharness/uniharness/tools/web/providers/fetch/__init__.py similarity index 57% rename from libs/hexagent/hexagent/tools/web/providers/fetch/__init__.py rename to libs/uniharness/uniharness/tools/web/providers/fetch/__init__.py index 0abe87f9..2c5b9195 100644 --- a/libs/hexagent/hexagent/tools/web/providers/fetch/__init__.py +++ b/libs/uniharness/uniharness/tools/web/providers/fetch/__init__.py @@ -7,9 +7,9 @@ from __future__ import annotations -from hexagent.tools.web.providers.fetch.base import FetchProvider, FetchResult -from hexagent.tools.web.providers.fetch.firecrawl import FirecrawlFetchProvider -from hexagent.tools.web.providers.fetch.jina import JinaFetchProvider +from uniharness.tools.web.providers.fetch.base import FetchProvider, FetchResult +from uniharness.tools.web.providers.fetch.firecrawl import FirecrawlFetchProvider +from uniharness.tools.web.providers.fetch.jina import JinaFetchProvider __all__ = [ "FetchProvider", diff --git a/libs/hexagent/hexagent/tools/web/providers/fetch/base.py b/libs/uniharness/uniharness/tools/web/providers/fetch/base.py similarity index 100% rename from libs/hexagent/hexagent/tools/web/providers/fetch/base.py rename to libs/uniharness/uniharness/tools/web/providers/fetch/base.py diff --git a/libs/hexagent/hexagent/tools/web/providers/fetch/firecrawl.py b/libs/uniharness/uniharness/tools/web/providers/fetch/firecrawl.py similarity index 92% rename from libs/hexagent/hexagent/tools/web/providers/fetch/firecrawl.py rename to libs/uniharness/uniharness/tools/web/providers/fetch/firecrawl.py index 3f4d43d3..383c90d3 100644 --- a/libs/hexagent/hexagent/tools/web/providers/fetch/firecrawl.py +++ b/libs/uniharness/uniharness/tools/web/providers/fetch/firecrawl.py @@ -10,10 +10,10 @@ import httpx -from hexagent.exceptions import ConfigurationError, WebAPIError -from hexagent.tools.web._markdown import strip_links_and_images -from hexagent.tools.web.providers._retry import web_retry -from hexagent.tools.web.providers.fetch.base import FetchResult +from uniharness.exceptions import ConfigurationError, WebAPIError +from uniharness.tools.web._markdown import strip_links_and_images +from uniharness.tools.web.providers._retry import web_retry +from uniharness.tools.web.providers.fetch.base import FetchResult FIRECRAWL_API_URL = "https://api.firecrawl.dev/v1/scrape" diff --git a/libs/hexagent/hexagent/tools/web/providers/fetch/jina.py b/libs/uniharness/uniharness/tools/web/providers/fetch/jina.py similarity index 94% rename from libs/hexagent/hexagent/tools/web/providers/fetch/jina.py rename to libs/uniharness/uniharness/tools/web/providers/fetch/jina.py index 75ac74cd..c4dc87cd 100644 --- a/libs/hexagent/hexagent/tools/web/providers/fetch/jina.py +++ b/libs/uniharness/uniharness/tools/web/providers/fetch/jina.py @@ -10,9 +10,9 @@ import httpx -from hexagent.exceptions import WebAPIError -from hexagent.tools.web.providers._retry import web_retry -from hexagent.tools.web.providers.fetch.base import FetchResult +from uniharness.exceptions import WebAPIError +from uniharness.tools.web.providers._retry import web_retry +from uniharness.tools.web.providers.fetch.base import FetchResult JINA_READER_URL = "https://r.jina.ai/" diff --git a/libs/hexagent/hexagent/tools/web/providers/search/__init__.py b/libs/uniharness/uniharness/tools/web/providers/search/__init__.py similarity index 68% rename from libs/hexagent/hexagent/tools/web/providers/search/__init__.py rename to libs/uniharness/uniharness/tools/web/providers/search/__init__.py index 751f772e..247ba9e4 100644 --- a/libs/hexagent/hexagent/tools/web/providers/search/__init__.py +++ b/libs/uniharness/uniharness/tools/web/providers/search/__init__.py @@ -7,13 +7,13 @@ from __future__ import annotations -from hexagent.tools.web.providers.search.base import ( +from uniharness.tools.web.providers.search.base import ( SearchProvider, SearchResult, SearchResultItem, ) -from hexagent.tools.web.providers.search.brave import BraveSearchProvider -from hexagent.tools.web.providers.search.tavily import TavilySearchProvider +from uniharness.tools.web.providers.search.brave import BraveSearchProvider +from uniharness.tools.web.providers.search.tavily import TavilySearchProvider __all__ = [ "BraveSearchProvider", diff --git a/libs/hexagent/hexagent/tools/web/providers/search/base.py b/libs/uniharness/uniharness/tools/web/providers/search/base.py similarity index 100% rename from libs/hexagent/hexagent/tools/web/providers/search/base.py rename to libs/uniharness/uniharness/tools/web/providers/search/base.py diff --git a/libs/hexagent/hexagent/tools/web/providers/search/brave.py b/libs/uniharness/uniharness/tools/web/providers/search/brave.py similarity index 95% rename from libs/hexagent/hexagent/tools/web/providers/search/brave.py rename to libs/uniharness/uniharness/tools/web/providers/search/brave.py index c319518e..498538ed 100644 --- a/libs/hexagent/hexagent/tools/web/providers/search/brave.py +++ b/libs/uniharness/uniharness/tools/web/providers/search/brave.py @@ -10,9 +10,9 @@ import httpx -from hexagent.exceptions import ConfigurationError, WebAPIError -from hexagent.tools.web.providers._retry import web_retry -from hexagent.tools.web.providers.search.base import ( +from uniharness.exceptions import ConfigurationError, WebAPIError +from uniharness.tools.web.providers._retry import web_retry +from uniharness.tools.web.providers.search.base import ( SearchResult, SearchResultItem, parse_date, diff --git a/libs/hexagent/hexagent/tools/web/providers/search/tavily.py b/libs/uniharness/uniharness/tools/web/providers/search/tavily.py similarity index 93% rename from libs/hexagent/hexagent/tools/web/providers/search/tavily.py rename to libs/uniharness/uniharness/tools/web/providers/search/tavily.py index 109257f7..4b22e1a7 100644 --- a/libs/hexagent/hexagent/tools/web/providers/search/tavily.py +++ b/libs/uniharness/uniharness/tools/web/providers/search/tavily.py @@ -10,9 +10,9 @@ import httpx -from hexagent.exceptions import ConfigurationError, WebAPIError -from hexagent.tools.web.providers._retry import web_retry -from hexagent.tools.web.providers.search.base import SearchResult, SearchResultItem +from uniharness.exceptions import ConfigurationError, WebAPIError +from uniharness.tools.web.providers._retry import web_retry +from uniharness.tools.web.providers.search.base import SearchResult, SearchResultItem TAVILY_API_URL = "https://api.tavily.com/search" diff --git a/libs/hexagent/hexagent/tools/web/search.py b/libs/uniharness/uniharness/tools/web/search.py similarity index 90% rename from libs/hexagent/hexagent/tools/web/search.py rename to libs/uniharness/uniharness/tools/web/search.py index 84092a2c..96eaf73f 100644 --- a/libs/hexagent/hexagent/tools/web/search.py +++ b/libs/uniharness/uniharness/tools/web/search.py @@ -10,15 +10,15 @@ import httpx -from hexagent.exceptions import ConfigurationError, ToolError, WebAPIError -from hexagent.prompts.content import load, substitute -from hexagent.tools.base import BaseAgentTool -from hexagent.tools.web._cache import cache_key, get_search_cache -from hexagent.types import ToolResult, WebSearchToolParams +from uniharness.exceptions import ConfigurationError, ToolError, WebAPIError +from uniharness.prompts.content import load, substitute +from uniharness.tools.base import BaseAgentTool +from uniharness.tools.web._cache import cache_key, get_search_cache +from uniharness.types import ToolResult, WebSearchToolParams if TYPE_CHECKING: - from hexagent.tools.web.providers.search import SearchProvider - from hexagent.types import CompletionModel + from uniharness.tools.web.providers.search import SearchProvider + from uniharness.types import CompletionModel MAX_SEARCH_RESULTS = 10 @@ -31,7 +31,7 @@ class WebSearchTool(BaseAgentTool[WebSearchToolParams]): Examples: ```python - from hexagent.tools.web.providers.search import TavilySearchProvider + from uniharness.tools.web.providers.search import TavilySearchProvider provider = TavilySearchProvider() tool = WebSearchTool(provider) diff --git a/libs/hexagent/hexagent/trace.py b/libs/uniharness/uniharness/trace.py similarity index 94% rename from libs/hexagent/hexagent/trace.py rename to libs/uniharness/uniharness/trace.py index 4b8e35b7..8271f0cb 100644 --- a/libs/hexagent/hexagent/trace.py +++ b/libs/uniharness/uniharness/trace.py @@ -1,4 +1,4 @@ -"""Tracing for HexAgent. +"""Tracing for UniHarness. Set environment variables to enable tracing — multiple platforms work simultaneously:: @@ -13,7 +13,7 @@ Example:: - from hexagent.trace import traced + from uniharness.trace import traced @traced @@ -70,7 +70,7 @@ def _load_tracers(platforms: list[str]) -> list[Callable[..., Any]]: # Braintrust's @traced is a no-op until init_logger() is called. if name == "braintrust": try: - mod.init_logger(project="HexAgent", api_key=os.getenv("BRAINTRUST_API_KEY")) + mod.init_logger(project="UniHarness", api_key=os.getenv("BRAINTRUST_API_KEY")) except Exception: # noqa: BLE001 logger.debug("Failed to initialise Braintrust logger", exc_info=True) return tracers @@ -141,7 +141,7 @@ def init_langchain_tracing() -> None: import braintrust from braintrust_langchain import BraintrustCallbackHandler, set_global_handler - braintrust.init_logger(project="HexAgent", api_key=os.getenv("BRAINTRUST_API_KEY")) + braintrust.init_logger(project="UniHarness", api_key=os.getenv("BRAINTRUST_API_KEY")) set_global_handler(BraintrustCallbackHandler()) except ImportError: logger.debug("braintrust-langchain not installed, skipping LangChain tracing") diff --git a/libs/hexagent/hexagent/types.py b/libs/uniharness/uniharness/types.py similarity index 98% rename from libs/hexagent/hexagent/types.py rename to libs/uniharness/uniharness/types.py index 6a88cf51..037b81fc 100644 --- a/libs/hexagent/hexagent/types.py +++ b/libs/uniharness/uniharness/types.py @@ -1,4 +1,4 @@ -"""Shared data types for HexAgent. +"""Shared data types for UniHarness. This module defines the core data structures used across the library, particularly result types returned by tools and computer operations. @@ -16,11 +16,11 @@ if TYPE_CHECKING: from datetime import datetime - from hexagent.computer.base import ExecutionMetadata - from hexagent.harness.definition import AgentDefinition - from hexagent.harness.model import ModelProfile - from hexagent.mcp import McpClient - from hexagent.tools.base import BaseAgentTool + from uniharness.computer.base import ExecutionMetadata + from uniharness.harness.definition import AgentDefinition + from uniharness.harness.model import ModelProfile + from uniharness.mcp import McpClient + from uniharness.tools.base import BaseAgentTool class CompactionPhase(str, Enum): @@ -660,7 +660,7 @@ class SubagentRunner(Protocol): Any object that implements :meth:`get_definition` and :meth:`run` can serve as a runner for the Agent tool. The concrete LangChain-based implementation lives in - :class:`~hexagent.langchain.subagent.LangChainSubagentRunner`. + :class:`~uniharness.langchain.subagent.LangChainSubagentRunner`. """ def get_definition(self, subagent_type: str) -> AgentDefinition | None: @@ -784,7 +784,7 @@ async def has(self, name: str) -> bool: class EnvironmentContext: """Detected runtime environment properties. - Populated by :class:`~hexagent.harness.environment.EnvironmentResolver` + Populated by :class:`~uniharness.harness.environment.EnvironmentResolver` via shell commands on the Computer. Attributes: @@ -901,6 +901,6 @@ def tool_name_vars(self) -> dict[str, str]: """Build ``${NAME_TOOL_NAME}`` template variables from registered tools. Returns a dict like ``{"BASH_TOOL_NAME": "Bash", "READ_TOOL_NAME": "Read", ...}`` - suitable for unpacking into :func:`~hexagent.prompts.content.substitute`. + suitable for unpacking into :func:`~uniharness.prompts.content.substitute`. """ return {f"{t.name.upper()}_TOOL_NAME": t.name for t in self.tools} diff --git a/libs/hexagent/uv.lock b/libs/uniharness/uv.lock similarity index 99% rename from libs/hexagent/uv.lock rename to libs/uniharness/uv.lock index 85c8a1d2..527553b2 100644 --- a/libs/hexagent/uv.lock +++ b/libs/uniharness/uv.lock @@ -982,87 +982,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] -[[package]] -name = "hexagent" -source = { editable = "." } -dependencies = [ - { name = "cachetools" }, - { name = "e2b" }, - { name = "httpx" }, - { name = "langchain" }, - { name = "langchain-anthropic" }, - { name = "langchain-core" }, - { name = "langchain-deepseek" }, - { name = "langchain-openai" }, - { name = "mcp" }, - { name = "petname" }, - { name = "pyyaml" }, - { name = "tenacity" }, - { name = "wcmatch" }, -] - -[package.optional-dependencies] -braintrust = [ - { name = "braintrust" }, - { name = "braintrust-langchain" }, -] -langsmith = [ - { name = "langsmith" }, -] -observe = [ - { name = "braintrust" }, - { name = "braintrust-langchain" }, - { name = "langsmith" }, -] - -[package.dev-dependencies] -test = [ - { name = "mypy" }, - { name = "pytest" }, - { name = "pytest-asyncio" }, - { name = "pytest-cov" }, - { name = "pytest-xdist" }, - { name = "ruff" }, - { name = "types-cachetools" }, - { name = "types-pyyaml" }, -] - -[package.metadata] -requires-dist = [ - { name = "braintrust", marker = "extra == 'braintrust'", specifier = ">=0.7.0" }, - { name = "braintrust", marker = "extra == 'observe'", specifier = ">=0.7.0" }, - { name = "braintrust-langchain", marker = "extra == 'braintrust'", specifier = ">=0.2.1" }, - { name = "braintrust-langchain", marker = "extra == 'observe'", specifier = ">=0.2.1" }, - { name = "cachetools", specifier = ">=5.0.0" }, - { name = "e2b", specifier = ">=2.0.0,<3.0.0" }, - { name = "httpx", specifier = ">=0.27.0" }, - { name = "langchain", specifier = ">=1.2.3,<2.0.0" }, - { name = "langchain-anthropic", specifier = ">=1.3.1,<2.0.0" }, - { name = "langchain-core", specifier = ">=1.2.6,<2.0.0" }, - { name = "langchain-deepseek", specifier = ">=1.0.1" }, - { name = "langchain-openai", specifier = ">=1.0.2,<2.0.0" }, - { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.1.0" }, - { name = "langsmith", marker = "extra == 'observe'", specifier = ">=0.1.0" }, - { name = "mcp", specifier = ">=1.25.0,<2.0.0" }, - { name = "petname", specifier = ">=2.9" }, - { name = "pyyaml", specifier = ">=6.0" }, - { name = "tenacity", specifier = ">=8.0.0" }, - { name = "wcmatch" }, -] -provides-extras = ["braintrust", "langsmith", "observe"] - -[package.metadata.requires-dev] -test = [ - { name = "mypy", specifier = ">=1.18.1,<1.19.0" }, - { name = "pytest" }, - { name = "pytest-asyncio", specifier = ">=1.3.0" }, - { name = "pytest-cov" }, - { name = "pytest-xdist" }, - { name = "ruff", specifier = ">=0.12.2,<0.13.0" }, - { name = "types-cachetools" }, - { name = "types-pyyaml" }, -] - [[package]] name = "openai" version = "2.24.0" @@ -2109,6 +2028,87 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] +[[package]] +name = "uniharness" +source = { editable = "." } +dependencies = [ + { name = "cachetools" }, + { name = "e2b" }, + { name = "httpx" }, + { name = "langchain" }, + { name = "langchain-anthropic" }, + { name = "langchain-core" }, + { name = "langchain-deepseek" }, + { name = "langchain-openai" }, + { name = "mcp" }, + { name = "petname" }, + { name = "pyyaml" }, + { name = "tenacity" }, + { name = "wcmatch" }, +] + +[package.optional-dependencies] +braintrust = [ + { name = "braintrust" }, + { name = "braintrust-langchain" }, +] +langsmith = [ + { name = "langsmith" }, +] +observe = [ + { name = "braintrust" }, + { name = "braintrust-langchain" }, + { name = "langsmith" }, +] + +[package.dev-dependencies] +test = [ + { name = "mypy" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, + { name = "pytest-xdist" }, + { name = "ruff" }, + { name = "types-cachetools" }, + { name = "types-pyyaml" }, +] + +[package.metadata] +requires-dist = [ + { name = "braintrust", marker = "extra == 'braintrust'", specifier = ">=0.7.0" }, + { name = "braintrust", marker = "extra == 'observe'", specifier = ">=0.7.0" }, + { name = "braintrust-langchain", marker = "extra == 'braintrust'", specifier = ">=0.2.1" }, + { name = "braintrust-langchain", marker = "extra == 'observe'", specifier = ">=0.2.1" }, + { name = "cachetools", specifier = ">=5.0.0" }, + { name = "e2b", specifier = ">=2.0.0,<3.0.0" }, + { name = "httpx", specifier = ">=0.27.0" }, + { name = "langchain", specifier = ">=1.2.3,<2.0.0" }, + { name = "langchain-anthropic", specifier = ">=1.3.1,<2.0.0" }, + { name = "langchain-core", specifier = ">=1.2.6,<2.0.0" }, + { name = "langchain-deepseek", specifier = ">=1.0.1" }, + { name = "langchain-openai", specifier = ">=1.0.2,<2.0.0" }, + { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.1.0" }, + { name = "langsmith", marker = "extra == 'observe'", specifier = ">=0.1.0" }, + { name = "mcp", specifier = ">=1.25.0,<2.0.0" }, + { name = "petname", specifier = ">=2.9" }, + { name = "pyyaml", specifier = ">=6.0" }, + { name = "tenacity", specifier = ">=8.0.0" }, + { name = "wcmatch" }, +] +provides-extras = ["braintrust", "langsmith", "observe"] + +[package.metadata.requires-dev] +test = [ + { name = "mypy", specifier = ">=1.18.1,<1.19.0" }, + { name = "pytest" }, + { name = "pytest-asyncio", specifier = ">=1.3.0" }, + { name = "pytest-cov" }, + { name = "pytest-xdist" }, + { name = "ruff", specifier = ">=0.12.2,<0.13.0" }, + { name = "types-cachetools" }, + { name = "types-pyyaml" }, +] + [[package]] name = "urllib3" version = "2.6.3" diff --git a/libs/hexagent_demo/README.md b/libs/uniharness_demo/README.md similarity index 88% rename from libs/hexagent_demo/README.md rename to libs/uniharness_demo/README.md index 2d01c37b..cbff20f6 100644 --- a/libs/hexagent_demo/README.md +++ b/libs/uniharness_demo/README.md @@ -1,6 +1,6 @@ -# HexAgent Demo +# UniHarness Demo -A ready-to-use desktop application built on [HexAgent](../hexagent/), demonstrating what you can build with an agent harness. This is not a toy example — it's a full-featured Chat + Cowork app that showcases HexAgent's ability to power real products. +A ready-to-use desktop application built on [UniHarness](../uniharness/), demonstrating what you can build with an agent harness. This is not a toy example — it's a full-featured Chat + Cowork app that showcases UniHarness's ability to power real products. > See it as a reference implementation: fork it, restyle it, or use it as the foundation for your own agent product. @@ -39,9 +39,9 @@ A full-featured local mode with per-conversation isolation using [Lima](https:// ## Architecture ``` -hexagent_demo/ +uniharness_demo/ ├── backend/ # FastAPI backend (Python 3.12+) -│ └── hexagent_api/ +│ └── uniharness_api/ │ ├── main.py # FastAPI app and router registration │ ├── agent_manager.py # Agent lifecycle and caching │ ├── config.py # Configuration persistence @@ -74,19 +74,19 @@ hexagent_demo/ ### Backend ```bash -cd libs/hexagent_demo/backend +cd libs/uniharness_demo/backend # Install dependencies uv sync # Run the server -uv run uvicorn hexagent_api.main:app --host 127.0.0.1 --port 8000 +uv run uvicorn uniharness_api.main:app --host 127.0.0.1 --port 8000 ``` ### Frontend ```bash -cd libs/hexagent_demo/frontend +cd libs/uniharness_demo/frontend # Install dependencies npm install @@ -100,7 +100,7 @@ The frontend runs on `http://localhost:5173` and connects to the backend on port ### Desktop App (Electron) ```bash -cd libs/hexagent_demo/electron +cd libs/uniharness_demo/electron # Install dependencies npm install @@ -123,15 +123,15 @@ Configuration is persisted in the platform-specific user data directory: | Platform | Path | |----------|------| -| macOS | `~/Library/Application Support/HexAgent/config.json` | -| Windows | `%APPDATA%/HexAgent/config.json` | -| Linux | `~/.config/HexAgent/config.json` | +| macOS | `~/Library/Application Support/UniHarness/config.json` | +| Windows | `%APPDATA%/UniHarness/config.json` | +| Linux | `~/.config/UniHarness/config.json` | ## Environment Variables | Variable | Description | |----------|-------------| -| `HEXAGENT_DATA_DIR` | Override user data directory | +| `UNIHARNESS_DATA_DIR` | Override user data directory | | `E2B_API_KEY` | E2B sandbox API key (Chat mode) | | `HOST` | Backend host (default: `127.0.0.1`) | | `PORT` | Backend port (default: `8000`) | @@ -191,14 +191,14 @@ The demo is designed to be forked and customized. Key extension points: ### Package the backend ```bash -cd libs/hexagent_demo/backend -pyinstaller --name hexagent_api_server ... # Creates standalone binary +cd libs/uniharness_demo/backend +pyinstaller --name uniharness_api_server ... # Creates standalone binary ``` ### Build the desktop app ```bash -cd libs/hexagent_demo/electron +cd libs/uniharness_demo/electron # macOS npm run build:mac # ARM64 diff --git a/libs/hexagent_demo/backend/.gitignore b/libs/uniharness_demo/backend/.gitignore similarity index 100% rename from libs/hexagent_demo/backend/.gitignore rename to libs/uniharness_demo/backend/.gitignore diff --git a/libs/hexagent_demo/backend/pyproject.toml b/libs/uniharness_demo/backend/pyproject.toml similarity index 56% rename from libs/hexagent_demo/backend/pyproject.toml rename to libs/uniharness_demo/backend/pyproject.toml index b0580319..d6cff1f0 100644 --- a/libs/hexagent_demo/backend/pyproject.toml +++ b/libs/uniharness_demo/backend/pyproject.toml @@ -1,15 +1,15 @@ [project] -name = "hexagent-demo-backend" +name = "uniharness-demo-backend" version = "0.1.0" -description = "FastAPI backend for HexAgent demo" +description = "FastAPI backend for UniHarness demo" requires-python = ">=3.12" dependencies = [ "fastapi>=0.115.0", "uvicorn[standard]>=0.34.0", "python-dotenv>=1.0.0", "langchain-deepseek>=0.1.0", - "hexagent", + "uniharness", ] [tool.uv.sources] -hexagent = { path = "../../hexagent", editable = true } +uniharness = { path = "../../uniharness", editable = true } diff --git a/libs/hexagent_demo/backend/skills/examples/data-insight-report/SKILL.md b/libs/uniharness_demo/backend/skills/examples/data-insight-report/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/data-insight-report/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/data-insight-report/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/data-insight-report/abilities/data-analysis.md b/libs/uniharness_demo/backend/skills/examples/data-insight-report/abilities/data-analysis.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/data-insight-report/abilities/data-analysis.md rename to libs/uniharness_demo/backend/skills/examples/data-insight-report/abilities/data-analysis.md diff --git a/libs/hexagent_demo/backend/skills/examples/data-insight-report/abilities/echarts-validation.md b/libs/uniharness_demo/backend/skills/examples/data-insight-report/abilities/echarts-validation.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/data-insight-report/abilities/echarts-validation.md rename to libs/uniharness_demo/backend/skills/examples/data-insight-report/abilities/echarts-validation.md diff --git a/libs/hexagent_demo/backend/skills/examples/data-insight-report/scripts/analyze.py b/libs/uniharness_demo/backend/skills/examples/data-insight-report/scripts/analyze.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/data-insight-report/scripts/analyze.py rename to libs/uniharness_demo/backend/skills/examples/data-insight-report/scripts/analyze.py diff --git a/libs/hexagent_demo/backend/skills/examples/data-insight-report/scripts/validate_echarts.py b/libs/uniharness_demo/backend/skills/examples/data-insight-report/scripts/validate_echarts.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/data-insight-report/scripts/validate_echarts.py rename to libs/uniharness_demo/backend/skills/examples/data-insight-report/scripts/validate_echarts.py diff --git a/libs/hexagent_demo/backend/skills/examples/deep-research/SKILL.md b/libs/uniharness_demo/backend/skills/examples/deep-research/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/deep-research/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/deep-research/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/doc/LICENSE.txt b/libs/uniharness_demo/backend/skills/examples/doc/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/doc/LICENSE.txt rename to libs/uniharness_demo/backend/skills/examples/doc/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/examples/doc/SKILL.md b/libs/uniharness_demo/backend/skills/examples/doc/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/doc/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/doc/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/doc/agents/openai.yaml b/libs/uniharness_demo/backend/skills/examples/doc/agents/openai.yaml similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/doc/agents/openai.yaml rename to libs/uniharness_demo/backend/skills/examples/doc/agents/openai.yaml diff --git a/libs/hexagent_demo/backend/skills/examples/doc/assets/doc-small.svg b/libs/uniharness_demo/backend/skills/examples/doc/assets/doc-small.svg similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/doc/assets/doc-small.svg rename to libs/uniharness_demo/backend/skills/examples/doc/assets/doc-small.svg diff --git a/libs/hexagent_demo/backend/skills/examples/doc/assets/doc.png b/libs/uniharness_demo/backend/skills/examples/doc/assets/doc.png similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/doc/assets/doc.png rename to libs/uniharness_demo/backend/skills/examples/doc/assets/doc.png diff --git a/libs/hexagent_demo/backend/skills/examples/doc/scripts/render_docx.py b/libs/uniharness_demo/backend/skills/examples/doc/scripts/render_docx.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/doc/scripts/render_docx.py rename to libs/uniharness_demo/backend/skills/examples/doc/scripts/render_docx.py diff --git a/libs/hexagent_demo/backend/skills/examples/excel-xlsx/SKILL.md b/libs/uniharness_demo/backend/skills/examples/excel-xlsx/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/excel-xlsx/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/excel-xlsx/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/excel-xlsx/_meta.json b/libs/uniharness_demo/backend/skills/examples/excel-xlsx/_meta.json similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/excel-xlsx/_meta.json rename to libs/uniharness_demo/backend/skills/examples/excel-xlsx/_meta.json diff --git a/libs/hexagent_demo/backend/skills/examples/find-skills/.clawhub/origin.json b/libs/uniharness_demo/backend/skills/examples/find-skills/.clawhub/origin.json similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/find-skills/.clawhub/origin.json rename to libs/uniharness_demo/backend/skills/examples/find-skills/.clawhub/origin.json diff --git a/libs/hexagent_demo/backend/skills/examples/find-skills/SKILL.md b/libs/uniharness_demo/backend/skills/examples/find-skills/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/find-skills/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/find-skills/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/find-skills/_meta.json b/libs/uniharness_demo/backend/skills/examples/find-skills/_meta.json similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/find-skills/_meta.json rename to libs/uniharness_demo/backend/skills/examples/find-skills/_meta.json diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/SKILL.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Boldonse-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/DMMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/EricaOne-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/GeistMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Gloock-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Italiana-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Light.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Light.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Light.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Light.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Medium.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Medium.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Jura-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Italic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Italic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Lora-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NationalPark-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Outfit-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PixelifySans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/SmoochSans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Medium.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Medium.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/Tektur-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Bold.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Bold.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Italic.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Italic.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/WorkSans-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-OFL.txt b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-OFL.txt rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf b/libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/asset-prompt-guide.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/asset-prompt-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/asset-prompt-guide.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/asset-prompt-guide.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/env-setup.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/env-setup.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/env-setup.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/env-setup.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-cli-reference.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-cli-reference.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-cli-reference.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-cli-reference.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-image-guide.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-image-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-image-guide.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-image-guide.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-music-guide.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-music-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-music-guide.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-music-guide.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-tts-guide.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-tts-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-tts-guide.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-tts-guide.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-video-guide.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-video-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-video-guide.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-video-guide.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-voice-catalog.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-voice-catalog.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/minimax-voice-catalog.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/minimax-voice-catalog.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/motion-recipes.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/motion-recipes.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/motion-recipes.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/motion-recipes.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/references/troubleshooting.md b/libs/uniharness_demo/backend/skills/examples/frontend-dev/references/troubleshooting.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/references/troubleshooting.md rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/references/troubleshooting.md diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_image.py b/libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_image.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_image.py rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_image.py diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_music.py b/libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_music.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_music.py rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_music.py diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_tts.py b/libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_tts.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_tts.py rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_tts.py diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_video.py b/libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_video.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/scripts/minimax_video.py rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/scripts/minimax_video.py diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/templates/generator_template.js b/libs/uniharness_demo/backend/skills/examples/frontend-dev/templates/generator_template.js similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/templates/generator_template.js rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/templates/generator_template.js diff --git a/libs/hexagent_demo/backend/skills/examples/frontend-dev/templates/viewer.html b/libs/uniharness_demo/backend/skills/examples/frontend-dev/templates/viewer.html similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/frontend-dev/templates/viewer.html rename to libs/uniharness_demo/backend/skills/examples/frontend-dev/templates/viewer.html diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/LICENSE.txt b/libs/uniharness_demo/backend/skills/examples/mcp-builder/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/LICENSE.txt rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/SKILL.md b/libs/uniharness_demo/backend/skills/examples/mcp-builder/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/evaluation.md b/libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/evaluation.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/evaluation.md rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/evaluation.md diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/mcp_best_practices.md b/libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/mcp_best_practices.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/mcp_best_practices.md rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/mcp_best_practices.md diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/node_mcp_server.md b/libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/node_mcp_server.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/node_mcp_server.md rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/node_mcp_server.md diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/python_mcp_server.md b/libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/python_mcp_server.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/reference/python_mcp_server.md rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/reference/python_mcp_server.md diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/connections.py b/libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/connections.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/connections.py rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/connections.py diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/evaluation.py b/libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/evaluation.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/evaluation.py rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/evaluation.py diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/example_evaluation.xml b/libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/example_evaluation.xml similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/example_evaluation.xml rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/example_evaluation.xml diff --git a/libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/requirements.txt b/libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/requirements.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/mcp-builder/scripts/requirements.txt rename to libs/uniharness_demo/backend/skills/examples/mcp-builder/scripts/requirements.txt diff --git a/libs/hexagent_demo/backend/skills/examples/pdf/LICENSE.txt b/libs/uniharness_demo/backend/skills/examples/pdf/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/pdf/LICENSE.txt rename to libs/uniharness_demo/backend/skills/examples/pdf/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/examples/pdf/SKILL.md b/libs/uniharness_demo/backend/skills/examples/pdf/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/pdf/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/pdf/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/pdf/agents/openai.yaml b/libs/uniharness_demo/backend/skills/examples/pdf/agents/openai.yaml similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/pdf/agents/openai.yaml rename to libs/uniharness_demo/backend/skills/examples/pdf/agents/openai.yaml diff --git a/libs/hexagent_demo/backend/skills/examples/pdf/assets/pdf.png b/libs/uniharness_demo/backend/skills/examples/pdf/assets/pdf.png similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/pdf/assets/pdf.png rename to libs/uniharness_demo/backend/skills/examples/pdf/assets/pdf.png diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/LICENSE.txt b/libs/uniharness_demo/backend/skills/examples/skill-creator/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/LICENSE.txt rename to libs/uniharness_demo/backend/skills/examples/skill-creator/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/SKILL.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/agents/analyzer.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/agents/analyzer.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/agents/analyzer.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/agents/analyzer.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/agents/comparator.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/agents/comparator.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/agents/comparator.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/agents/comparator.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/agents/grader.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/agents/grader.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/agents/grader.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/agents/grader.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/assets/eval_review.html b/libs/uniharness_demo/backend/skills/examples/skill-creator/assets/eval_review.html similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/assets/eval_review.html rename to libs/uniharness_demo/backend/skills/examples/skill-creator/assets/eval_review.html diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/eval-viewer/generate_review.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/eval-viewer/generate_review.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/eval-viewer/generate_review.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/eval-viewer/generate_review.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/eval-viewer/viewer.html b/libs/uniharness_demo/backend/skills/examples/skill-creator/eval-viewer/viewer.html similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/eval-viewer/viewer.html rename to libs/uniharness_demo/backend/skills/examples/skill-creator/eval-viewer/viewer.html diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/references/output-patterns.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/references/output-patterns.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/references/output-patterns.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/references/output-patterns.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/references/schemas.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/references/schemas.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/references/schemas.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/references/schemas.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/references/workflows.md b/libs/uniharness_demo/backend/skills/examples/skill-creator/references/workflows.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/references/workflows.md rename to libs/uniharness_demo/backend/skills/examples/skill-creator/references/workflows.md diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/aggregate_benchmark.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/aggregate_benchmark.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/aggregate_benchmark.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/aggregate_benchmark.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/generate_report.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/generate_report.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/generate_report.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/generate_report.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/improve_description.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/improve_description.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/improve_description.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/improve_description.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/init_skill.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/init_skill.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/init_skill.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/init_skill.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/package_skill.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/package_skill.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/package_skill.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/package_skill.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/quick_validate.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/quick_validate.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/quick_validate.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/quick_validate.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/run_eval.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/run_eval.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/run_eval.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/run_eval.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/run_loop.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/run_loop.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/run_loop.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/run_loop.py diff --git a/libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/utils.py b/libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/utils.py similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/skill-creator/scripts/utils.py rename to libs/uniharness_demo/backend/skills/examples/skill-creator/scripts/utils.py diff --git a/libs/hexagent_demo/backend/skills/examples/web-design-guidelines/SKILL.md b/libs/uniharness_demo/backend/skills/examples/web-design-guidelines/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/examples/web-design-guidelines/SKILL.md rename to libs/uniharness_demo/backend/skills/examples/web-design-guidelines/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/data-insight-report/SKILL.md b/libs/uniharness_demo/backend/skills/public/data-insight-report/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/data-insight-report/SKILL.md rename to libs/uniharness_demo/backend/skills/public/data-insight-report/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/data-insight-report/abilities/data-analysis.md b/libs/uniharness_demo/backend/skills/public/data-insight-report/abilities/data-analysis.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/data-insight-report/abilities/data-analysis.md rename to libs/uniharness_demo/backend/skills/public/data-insight-report/abilities/data-analysis.md diff --git a/libs/hexagent_demo/backend/skills/public/data-insight-report/abilities/echarts-validation.md b/libs/uniharness_demo/backend/skills/public/data-insight-report/abilities/echarts-validation.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/data-insight-report/abilities/echarts-validation.md rename to libs/uniharness_demo/backend/skills/public/data-insight-report/abilities/echarts-validation.md diff --git a/libs/hexagent_demo/backend/skills/public/data-insight-report/scripts/analyze.py b/libs/uniharness_demo/backend/skills/public/data-insight-report/scripts/analyze.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/data-insight-report/scripts/analyze.py rename to libs/uniharness_demo/backend/skills/public/data-insight-report/scripts/analyze.py diff --git a/libs/hexagent_demo/backend/skills/public/data-insight-report/scripts/validate_echarts.py b/libs/uniharness_demo/backend/skills/public/data-insight-report/scripts/validate_echarts.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/data-insight-report/scripts/validate_echarts.py rename to libs/uniharness_demo/backend/skills/public/data-insight-report/scripts/validate_echarts.py diff --git a/libs/hexagent_demo/backend/skills/public/deep-research/SKILL.md b/libs/uniharness_demo/backend/skills/public/deep-research/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/deep-research/SKILL.md rename to libs/uniharness_demo/backend/skills/public/deep-research/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/doc/LICENSE.txt b/libs/uniharness_demo/backend/skills/public/doc/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/doc/LICENSE.txt rename to libs/uniharness_demo/backend/skills/public/doc/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/public/doc/SKILL.md b/libs/uniharness_demo/backend/skills/public/doc/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/doc/SKILL.md rename to libs/uniharness_demo/backend/skills/public/doc/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/doc/agents/openai.yaml b/libs/uniharness_demo/backend/skills/public/doc/agents/openai.yaml similarity index 100% rename from libs/hexagent_demo/backend/skills/public/doc/agents/openai.yaml rename to libs/uniharness_demo/backend/skills/public/doc/agents/openai.yaml diff --git a/libs/hexagent_demo/backend/skills/public/doc/assets/doc-small.svg b/libs/uniharness_demo/backend/skills/public/doc/assets/doc-small.svg similarity index 100% rename from libs/hexagent_demo/backend/skills/public/doc/assets/doc-small.svg rename to libs/uniharness_demo/backend/skills/public/doc/assets/doc-small.svg diff --git a/libs/hexagent_demo/backend/skills/public/doc/assets/doc.png b/libs/uniharness_demo/backend/skills/public/doc/assets/doc.png similarity index 100% rename from libs/hexagent_demo/backend/skills/public/doc/assets/doc.png rename to libs/uniharness_demo/backend/skills/public/doc/assets/doc.png diff --git a/libs/hexagent_demo/backend/skills/public/doc/scripts/render_docx.py b/libs/uniharness_demo/backend/skills/public/doc/scripts/render_docx.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/doc/scripts/render_docx.py rename to libs/uniharness_demo/backend/skills/public/doc/scripts/render_docx.py diff --git a/libs/hexagent_demo/backend/skills/public/excel-xlsx/SKILL.md b/libs/uniharness_demo/backend/skills/public/excel-xlsx/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/excel-xlsx/SKILL.md rename to libs/uniharness_demo/backend/skills/public/excel-xlsx/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/excel-xlsx/_meta.json b/libs/uniharness_demo/backend/skills/public/excel-xlsx/_meta.json similarity index 100% rename from libs/hexagent_demo/backend/skills/public/excel-xlsx/_meta.json rename to libs/uniharness_demo/backend/skills/public/excel-xlsx/_meta.json diff --git a/libs/hexagent_demo/backend/skills/public/find-skills/.clawhub/origin.json b/libs/uniharness_demo/backend/skills/public/find-skills/.clawhub/origin.json similarity index 100% rename from libs/hexagent_demo/backend/skills/public/find-skills/.clawhub/origin.json rename to libs/uniharness_demo/backend/skills/public/find-skills/.clawhub/origin.json diff --git a/libs/hexagent_demo/backend/skills/public/find-skills/SKILL.md b/libs/uniharness_demo/backend/skills/public/find-skills/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/find-skills/SKILL.md rename to libs/uniharness_demo/backend/skills/public/find-skills/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/find-skills/_meta.json b/libs/uniharness_demo/backend/skills/public/find-skills/_meta.json similarity index 100% rename from libs/hexagent_demo/backend/skills/public/find-skills/_meta.json rename to libs/uniharness_demo/backend/skills/public/find-skills/_meta.json diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/SKILL.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/SKILL.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/ArsenalSC-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BigShoulders-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Boldonse-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/BricolageGrotesque-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/CrimsonPro-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/DMMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/EricaOne-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/GeistMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Gloock-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/IBMPlexSerif-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSans-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/InstrumentSerif-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Italiana-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/JetBrainsMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Light.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Light.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Light.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Light.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Medium.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Medium.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Jura-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/LibreBaskerville-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Italic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Italic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Lora-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NationalPark-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/NothingYouCouldDo-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Outfit-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PixelifySans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/PoiretOne-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/RedHatMono-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Silkscreen-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/SmoochSans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Medium.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Medium.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Medium.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Medium.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/Tektur-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Bold.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Bold.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Bold.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Bold.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-BoldItalic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Italic.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Italic.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Italic.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Italic.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/WorkSans-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-OFL.txt b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-OFL.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-OFL.txt rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-OFL.txt diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf b/libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf rename to libs/uniharness_demo/backend/skills/public/frontend-dev/canvas-fonts/YoungSerif-Regular.ttf diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/asset-prompt-guide.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/asset-prompt-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/asset-prompt-guide.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/asset-prompt-guide.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/env-setup.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/env-setup.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/env-setup.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/env-setup.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-cli-reference.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-cli-reference.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-cli-reference.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-cli-reference.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-image-guide.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-image-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-image-guide.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-image-guide.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-music-guide.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-music-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-music-guide.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-music-guide.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-tts-guide.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-tts-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-tts-guide.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-tts-guide.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-video-guide.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-video-guide.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-video-guide.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-video-guide.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-voice-catalog.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-voice-catalog.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/minimax-voice-catalog.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/minimax-voice-catalog.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/motion-recipes.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/motion-recipes.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/motion-recipes.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/motion-recipes.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/references/troubleshooting.md b/libs/uniharness_demo/backend/skills/public/frontend-dev/references/troubleshooting.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/references/troubleshooting.md rename to libs/uniharness_demo/backend/skills/public/frontend-dev/references/troubleshooting.md diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_image.py b/libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_image.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_image.py rename to libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_image.py diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_music.py b/libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_music.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_music.py rename to libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_music.py diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_tts.py b/libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_tts.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_tts.py rename to libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_tts.py diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_video.py b/libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_video.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/scripts/minimax_video.py rename to libs/uniharness_demo/backend/skills/public/frontend-dev/scripts/minimax_video.py diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/templates/generator_template.js b/libs/uniharness_demo/backend/skills/public/frontend-dev/templates/generator_template.js similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/templates/generator_template.js rename to libs/uniharness_demo/backend/skills/public/frontend-dev/templates/generator_template.js diff --git a/libs/hexagent_demo/backend/skills/public/frontend-dev/templates/viewer.html b/libs/uniharness_demo/backend/skills/public/frontend-dev/templates/viewer.html similarity index 100% rename from libs/hexagent_demo/backend/skills/public/frontend-dev/templates/viewer.html rename to libs/uniharness_demo/backend/skills/public/frontend-dev/templates/viewer.html diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/LICENSE.txt b/libs/uniharness_demo/backend/skills/public/mcp-builder/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/LICENSE.txt rename to libs/uniharness_demo/backend/skills/public/mcp-builder/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/SKILL.md b/libs/uniharness_demo/backend/skills/public/mcp-builder/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/SKILL.md rename to libs/uniharness_demo/backend/skills/public/mcp-builder/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/reference/evaluation.md b/libs/uniharness_demo/backend/skills/public/mcp-builder/reference/evaluation.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/reference/evaluation.md rename to libs/uniharness_demo/backend/skills/public/mcp-builder/reference/evaluation.md diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/reference/mcp_best_practices.md b/libs/uniharness_demo/backend/skills/public/mcp-builder/reference/mcp_best_practices.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/reference/mcp_best_practices.md rename to libs/uniharness_demo/backend/skills/public/mcp-builder/reference/mcp_best_practices.md diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/reference/node_mcp_server.md b/libs/uniharness_demo/backend/skills/public/mcp-builder/reference/node_mcp_server.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/reference/node_mcp_server.md rename to libs/uniharness_demo/backend/skills/public/mcp-builder/reference/node_mcp_server.md diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/reference/python_mcp_server.md b/libs/uniharness_demo/backend/skills/public/mcp-builder/reference/python_mcp_server.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/reference/python_mcp_server.md rename to libs/uniharness_demo/backend/skills/public/mcp-builder/reference/python_mcp_server.md diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/connections.py b/libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/connections.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/connections.py rename to libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/connections.py diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/evaluation.py b/libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/evaluation.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/evaluation.py rename to libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/evaluation.py diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/example_evaluation.xml b/libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/example_evaluation.xml similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/example_evaluation.xml rename to libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/example_evaluation.xml diff --git a/libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/requirements.txt b/libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/requirements.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/mcp-builder/scripts/requirements.txt rename to libs/uniharness_demo/backend/skills/public/mcp-builder/scripts/requirements.txt diff --git a/libs/hexagent_demo/backend/skills/public/pdf/LICENSE.txt b/libs/uniharness_demo/backend/skills/public/pdf/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/pdf/LICENSE.txt rename to libs/uniharness_demo/backend/skills/public/pdf/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/public/pdf/SKILL.md b/libs/uniharness_demo/backend/skills/public/pdf/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/pdf/SKILL.md rename to libs/uniharness_demo/backend/skills/public/pdf/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/pdf/agents/openai.yaml b/libs/uniharness_demo/backend/skills/public/pdf/agents/openai.yaml similarity index 100% rename from libs/hexagent_demo/backend/skills/public/pdf/agents/openai.yaml rename to libs/uniharness_demo/backend/skills/public/pdf/agents/openai.yaml diff --git a/libs/hexagent_demo/backend/skills/public/pdf/assets/pdf.png b/libs/uniharness_demo/backend/skills/public/pdf/assets/pdf.png similarity index 100% rename from libs/hexagent_demo/backend/skills/public/pdf/assets/pdf.png rename to libs/uniharness_demo/backend/skills/public/pdf/assets/pdf.png diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/LICENSE.txt b/libs/uniharness_demo/backend/skills/public/skill-creator/LICENSE.txt similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/LICENSE.txt rename to libs/uniharness_demo/backend/skills/public/skill-creator/LICENSE.txt diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/SKILL.md b/libs/uniharness_demo/backend/skills/public/skill-creator/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/SKILL.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/SKILL.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/agents/analyzer.md b/libs/uniharness_demo/backend/skills/public/skill-creator/agents/analyzer.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/agents/analyzer.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/agents/analyzer.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/agents/comparator.md b/libs/uniharness_demo/backend/skills/public/skill-creator/agents/comparator.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/agents/comparator.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/agents/comparator.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/agents/grader.md b/libs/uniharness_demo/backend/skills/public/skill-creator/agents/grader.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/agents/grader.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/agents/grader.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/assets/eval_review.html b/libs/uniharness_demo/backend/skills/public/skill-creator/assets/eval_review.html similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/assets/eval_review.html rename to libs/uniharness_demo/backend/skills/public/skill-creator/assets/eval_review.html diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/eval-viewer/generate_review.py b/libs/uniharness_demo/backend/skills/public/skill-creator/eval-viewer/generate_review.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/eval-viewer/generate_review.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/eval-viewer/generate_review.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/eval-viewer/viewer.html b/libs/uniharness_demo/backend/skills/public/skill-creator/eval-viewer/viewer.html similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/eval-viewer/viewer.html rename to libs/uniharness_demo/backend/skills/public/skill-creator/eval-viewer/viewer.html diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/references/output-patterns.md b/libs/uniharness_demo/backend/skills/public/skill-creator/references/output-patterns.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/references/output-patterns.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/references/output-patterns.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/references/schemas.md b/libs/uniharness_demo/backend/skills/public/skill-creator/references/schemas.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/references/schemas.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/references/schemas.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/references/workflows.md b/libs/uniharness_demo/backend/skills/public/skill-creator/references/workflows.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/references/workflows.md rename to libs/uniharness_demo/backend/skills/public/skill-creator/references/workflows.md diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/aggregate_benchmark.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/aggregate_benchmark.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/aggregate_benchmark.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/aggregate_benchmark.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/generate_report.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/generate_report.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/generate_report.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/generate_report.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/improve_description.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/improve_description.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/improve_description.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/improve_description.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/init_skill.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/init_skill.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/init_skill.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/init_skill.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/package_skill.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/package_skill.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/package_skill.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/package_skill.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/quick_validate.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/quick_validate.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/quick_validate.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/quick_validate.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/run_eval.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/run_eval.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/run_eval.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/run_eval.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/run_loop.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/run_loop.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/run_loop.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/run_loop.py diff --git a/libs/hexagent_demo/backend/skills/public/skill-creator/scripts/utils.py b/libs/uniharness_demo/backend/skills/public/skill-creator/scripts/utils.py similarity index 100% rename from libs/hexagent_demo/backend/skills/public/skill-creator/scripts/utils.py rename to libs/uniharness_demo/backend/skills/public/skill-creator/scripts/utils.py diff --git a/libs/hexagent_demo/backend/skills/public/web-design-guidelines/SKILL.md b/libs/uniharness_demo/backend/skills/public/web-design-guidelines/SKILL.md similarity index 100% rename from libs/hexagent_demo/backend/skills/public/web-design-guidelines/SKILL.md rename to libs/uniharness_demo/backend/skills/public/web-design-guidelines/SKILL.md diff --git a/libs/uniharness_demo/backend/uniharness_api/__init__.py b/libs/uniharness_demo/backend/uniharness_api/__init__.py new file mode 100644 index 00000000..8c349241 --- /dev/null +++ b/libs/uniharness_demo/backend/uniharness_api/__init__.py @@ -0,0 +1 @@ +"""UniHarness API backend package.""" diff --git a/libs/hexagent_demo/backend/hexagent_api/agent_manager.py b/libs/uniharness_demo/backend/uniharness_api/agent_manager.py similarity index 95% rename from libs/hexagent_demo/backend/hexagent_api/agent_manager.py rename to libs/uniharness_demo/backend/uniharness_api/agent_manager.py index 31384445..52b4a5f0 100644 --- a/libs/hexagent_demo/backend/hexagent_api/agent_manager.py +++ b/libs/uniharness_demo/backend/uniharness_api/agent_manager.py @@ -1,6 +1,6 @@ """Agent lifecycle management. -Singleton that manages the HexAgent agent lifecycle. +Singleton that manages the UniHarness agent lifecycle. - **Chat mode**: one shared ``RemoteE2BComputer`` for all conversations. - **Cowork mode**: each conversation gets its own session computer @@ -30,7 +30,7 @@ class AgentManager: - """Manages the HexAgent agent lifecycle with per-session caching. + """Manages the UniHarness agent lifecycle with per-session caching. There is no global "current agent" state. Every public method receives explicit ``model_id``, ``mode``, and ``session_name`` parameters so that @@ -74,7 +74,7 @@ async def _verify_session_dir_writable(self, session_name: str, guest_dir: str) if vm is None: return - probe = f"{guest_dir.rstrip('/')}/.hexagent_write_probe_{os.getpid()}" + probe = f"{guest_dir.rstrip('/')}/.uniharness_write_probe_{os.getpid()}" cmd = ( f"test -d {shlex.quote(guest_dir)} && " f"test -w {shlex.quote(guest_dir)} && " @@ -115,7 +115,7 @@ async def _ensure_computer( if "chat" in self._computers: return self._computers["chat"], "chat" - from hexagent_api.config import load_config + from uniharness_api.config import load_config cfg = load_config() e2b_key = cfg.sandbox.e2b_api_key or os.environ.get("E2B_API_KEY", "") @@ -126,10 +126,10 @@ async def _ensure_computer( ) os.environ["E2B_API_KEY"] = e2b_key - from hexagent.computer.remote.e2b import RemoteE2BComputer + from uniharness.computer.remote.e2b import RemoteE2BComputer logger.info("Starting RemoteE2BComputer for chat mode...") - computer = RemoteE2BComputer(template="an7tang/hexagent") + computer = RemoteE2BComputer(template="openagent") try: await asyncio.wait_for(computer.start(), timeout=30) except asyncio.TimeoutError: @@ -152,7 +152,7 @@ async def _ensure_computer( import shutil if sys.platform == "win32": - from hexagent.computer.local._wsl import _resolve_wsl_exe + from uniharness.computer.local._wsl import _resolve_wsl_exe vm_backend_ready = _resolve_wsl_exe() is not None else: @@ -176,7 +176,7 @@ async def _ensure_computer( else: from pathlib import Path - from hexagent.computer import Mount + from uniharness.computer import Mount session_mounts: list[Mount] | None = None default_cwd: str | None = None @@ -223,7 +223,7 @@ def _get_mcp_servers(self) -> dict[str, Any]: """Return MCP server configs built from config.json (rebuilt on each call after cache invalidation so config changes take effect).""" if self._mcp_servers is None: - from hexagent_api.config import load_config + from uniharness_api.config import load_config servers: dict[str, Any] = {} for mcp in load_config().mcp_servers: @@ -281,12 +281,12 @@ async def _get_or_create_agent( from langchain_anthropic import ChatAnthropic from langchain_deepseek import ChatDeepSeek from langchain_openai import ChatOpenAI - from hexagent import create_agent - from hexagent.computer.base import SESSION_OUTPUTS_DIR - from hexagent.harness.definition import AgentDefinition - from hexagent.harness.model import ModelProfile - from hexagent.tools import PresentToUserTool - from hexagent.tools.web import ( + from uniharness import create_agent + from uniharness.computer.base import SESSION_OUTPUTS_DIR + from uniharness.harness.definition import AgentDefinition + from uniharness.harness.model import ModelProfile + from uniharness.tools import PresentToUserTool + from uniharness.tools.web import ( BraveSearchProvider, FetchProvider, FirecrawlFetchProvider, @@ -295,7 +295,7 @@ async def _get_or_create_agent( TavilySearchProvider, ) - from hexagent_api.config import load_config + from uniharness_api.config import load_config cfg = load_config() target = next((m for m in cfg.models if m.id == model_id), None) @@ -403,7 +403,7 @@ async def _ensure_vm_manager(self) -> None: if self._vm_manager is not None: return - from hexagent.computer.local import LocalVM + from uniharness.computer.local import LocalVM vm = LocalVM() await vm.start() @@ -423,9 +423,9 @@ async def _mount_skills(self) -> None: """ assert self._vm_manager is not None - from hexagent.computer import Mount + from uniharness.computer import Mount - from hexagent_api.paths import bundled_skills_dir, skills_dir + from uniharness_api.paths import bundled_skills_dir, skills_dir existing_guests = {m.guest_path for m in self._vm_manager.list_mounts()} @@ -469,7 +469,7 @@ def _schedule_vm_warmup(self) -> None: import shutil if sys.platform == "win32": - from hexagent.computer.local._wsl import _resolve_wsl_exe + from uniharness.computer.local._wsl import _resolve_wsl_exe vm_backend_available = _resolve_wsl_exe() is not None else: @@ -582,7 +582,7 @@ async def mount_working_dir(self, session_name: str, working_dir: str) -> None: return from pathlib import Path - from hexagent.computer import Mount + from uniharness.computer import Mount new_target = Path(working_dir).name diff --git a/libs/hexagent_demo/backend/hexagent_api/config.py b/libs/uniharness_demo/backend/uniharness_api/config.py similarity index 96% rename from libs/hexagent_demo/backend/hexagent_api/config.py rename to libs/uniharness_demo/backend/uniharness_api/config.py index 53696e60..9382002f 100644 --- a/libs/hexagent_demo/backend/hexagent_api/config.py +++ b/libs/uniharness_demo/backend/uniharness_api/config.py @@ -15,13 +15,13 @@ def _resolve_config_path() -> Path: """Resolve config.json path. - Uses ``paths.data_dir()`` when ``HEXAGENT_DATA_DIR`` is set (production / + Uses ``paths.data_dir()`` when ``UNIHARNESS_DATA_DIR`` is set (production / Electron), otherwise falls back to ``backend/config.json`` next to the package for local development convenience. """ - from hexagent_api.paths import data_dir + from uniharness_api.paths import data_dir - data = os.environ.get("HEXAGENT_DATA_DIR") + data = os.environ.get("UNIHARNESS_DATA_DIR") if data: return data_dir() / "config.json" return Path(__file__).resolve().parent.parent / "config.json" diff --git a/libs/hexagent_demo/backend/hexagent_api/main.py b/libs/uniharness_demo/backend/uniharness_api/main.py similarity index 85% rename from libs/hexagent_demo/backend/hexagent_api/main.py rename to libs/uniharness_demo/backend/uniharness_api/main.py index 12f0c0c5..77973e01 100644 --- a/libs/hexagent_demo/backend/hexagent_api/main.py +++ b/libs/uniharness_demo/backend/uniharness_api/main.py @@ -15,9 +15,9 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from hexagent_api.agent_manager import agent_manager -from hexagent_api.paths import data_dir -from hexagent_api.routes import chat, config, conversations, sessions, setup, skills +from uniharness_api.agent_manager import agent_manager +from uniharness_api.paths import data_dir +from uniharness_api.routes import chat, config, conversations, sessions, setup, skills _LOG_DIR = data_dir() / "logs" _LOG_DIR.mkdir(parents=True, exist_ok=True) @@ -41,8 +41,8 @@ async def _cleanup_expired_sessions() -> None: import asyncio import shutil - from hexagent_api.paths import uploads_dir - from hexagent_api.store import session_store + from uniharness_api.paths import uploads_dir + from uniharness_api.store import session_store ul_dir = uploads_dir() @@ -67,7 +67,7 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: import asyncio # Ensure managed VM backend binaries are on PATH before agent manager tries to find them - from hexagent_api.routes.setup import ensure_managed_deps_on_path + from uniharness_api.routes.setup import ensure_managed_deps_on_path ensure_managed_deps_on_path() logger.info("Starting agent manager...") @@ -76,7 +76,7 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: cleanup_task = asyncio.create_task(_cleanup_expired_sessions()) yield cleanup_task.cancel() - from hexagent_api.stream_manager import stream_manager + from uniharness_api.stream_manager import stream_manager logger.info("Cancelling active streams...") stream_manager.cancel_all() logger.info("Shutting down agent manager...") @@ -84,7 +84,7 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: logger.info("Agent manager shut down.") -app = FastAPI(title="HexAgent API", version="0.1.0", lifespan=lifespan) +app = FastAPI(title="UniHarness API", version="0.1.0", lifespan=lifespan) app.add_middleware( CORSMiddleware, diff --git a/libs/hexagent_demo/backend/hexagent_api/models.py b/libs/uniharness_demo/backend/uniharness_api/models.py similarity index 97% rename from libs/hexagent_demo/backend/hexagent_api/models.py rename to libs/uniharness_demo/backend/uniharness_api/models.py index 29b6a817..2b33c57c 100644 --- a/libs/hexagent_demo/backend/hexagent_api/models.py +++ b/libs/uniharness_demo/backend/uniharness_api/models.py @@ -1,4 +1,4 @@ -"""Pydantic request/response models for the HexAgent API.""" +"""Pydantic request/response models for the UniHarness API.""" from __future__ import annotations diff --git a/libs/hexagent_demo/backend/hexagent_api/paths.py b/libs/uniharness_demo/backend/uniharness_api/paths.py similarity index 86% rename from libs/hexagent_demo/backend/hexagent_api/paths.py rename to libs/uniharness_demo/backend/uniharness_api/paths.py index d2923c40..2eb10a0b 100644 --- a/libs/hexagent_demo/backend/hexagent_api/paths.py +++ b/libs/uniharness_demo/backend/uniharness_api/paths.py @@ -1,7 +1,7 @@ -"""Centralised path resolution for the HexAgent demo backend. +"""Centralised path resolution for the UniHarness demo backend. All runtime directories are derived from a single root — either -``$HEXAGENT_DATA_DIR`` (when set) or ``~/.hexagent``. Importing +``$UNIHARNESS_DATA_DIR`` (when set) or ``~/.uniharness``. Importing code should call the functions here rather than constructing paths inline, so that a future rename or restructure only touches this file. """ @@ -17,7 +17,7 @@ # Change this if the project is ever renamed. # --------------------------------------------------------------------------- -_PROJECT_DIR_NAME = "hexagent" +_PROJECT_DIR_NAME = "uniharness" # --------------------------------------------------------------------------- # Root @@ -27,9 +27,9 @@ def data_dir() -> Path: """Root data directory. - Respects ``HEXAGENT_DATA_DIR`` if set, otherwise ``~/.hexagent``. + Respects ``UNIHARNESS_DATA_DIR`` if set, otherwise ``~/.uniharness``. """ - env = os.environ.get("HEXAGENT_DATA_DIR") + env = os.environ.get("UNIHARNESS_DATA_DIR") if env: return Path(env) return Path.home() / f".{_PROJECT_DIR_NAME}" @@ -84,7 +84,7 @@ def pdf_cache_dir() -> Path: def vm_dir() -> Path: - """Root directory for VM assets (``libs/hexagent/sandbox/vm/``). + """Root directory for VM assets (``libs/uniharness/sandbox/vm/``). In a PyInstaller bundle the sandbox tree is placed at ``sys._MEIPASS/sandbox/vm/`` via ``--add-data``. @@ -94,9 +94,9 @@ def vm_dir() -> Path: if getattr(sys, "frozen", False): return Path(sys._MEIPASS) / "sandbox" / "vm" # type: ignore[attr-defined] - import hexagent # noqa: PLC0415 — deferred to avoid circular import + import uniharness # noqa: PLC0415 — deferred to avoid circular import - return Path(hexagent.__file__).parent.parent / "sandbox" / "vm" + return Path(uniharness.__file__).parent.parent / "sandbox" / "vm" def vm_lima_dir() -> Path: diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/__init__.py b/libs/uniharness_demo/backend/uniharness_api/routes/__init__.py similarity index 100% rename from libs/hexagent_demo/backend/hexagent_api/routes/__init__.py rename to libs/uniharness_demo/backend/uniharness_api/routes/__init__.py diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/chat.py b/libs/uniharness_demo/backend/uniharness_api/routes/chat.py similarity index 98% rename from libs/hexagent_demo/backend/hexagent_api/routes/chat.py rename to libs/uniharness_demo/backend/uniharness_api/routes/chat.py index 774df14f..f2d15898 100644 --- a/libs/hexagent_demo/backend/hexagent_api/routes/chat.py +++ b/libs/uniharness_demo/backend/uniharness_api/routes/chat.py @@ -24,15 +24,15 @@ from langchain_core.messages import AIMessage, HumanMessage from starlette.background import BackgroundTask -from hexagent.computer.base import SESSION_OUTPUTS_DIR, SESSION_UPLOADS_DIR -from hexagent.exceptions import VMMountConflictError +from uniharness.computer.base import SESSION_OUTPUTS_DIR, SESSION_UPLOADS_DIR +from uniharness.exceptions import VMMountConflictError -from hexagent_api.agent_manager import agent_manager -from hexagent_api.config import load_config -from hexagent_api.models import MessageRequest -from hexagent_api.paths import pdf_cache_dir, uploads_dir -from hexagent_api.store import store -from hexagent_api.stream_manager import stream_manager +from uniharness_api.agent_manager import agent_manager +from uniharness_api.config import load_config +from uniharness_api.models import MessageRequest +from uniharness_api.paths import pdf_cache_dir, uploads_dir +from uniharness_api.store import store +from uniharness_api.stream_manager import stream_manager # Image extensions that should be passed as visual content to the LLM _IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".webp"} @@ -117,8 +117,8 @@ def _build_human_message( blocks.extend(image_blocks) return HumanMessage(content=blocks) -SUBAGENT_TAG_PREFIX = "hexagent:subagent:" -INTERNAL_TOOL_TAG = "hexagent:tool" +SUBAGENT_TAG_PREFIX = "uniharness:subagent:" +INTERNAL_TOOL_TAG = "uniharness:tool" # Seconds of silence before sending an SSE keepalive comment. # Keeps the connection alive through proxies (Vite dev proxy defaults to @@ -210,7 +210,7 @@ async def _generate_events( # noqa: C901 """Async generator that drives the agent and yields SSE event strings. Runs inside a background ``asyncio.Task`` managed by - :pymod:`hexagent_api.stream_manager` so it is **not** tied to any HTTP + :pymod:`uniharness_api.stream_manager` so it is **not** tied to any HTTP connection. Message persistence happens here (always executes). """ yield f"event: message_start\ndata: {json.dumps({'id': msg_id})}\n\n" diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/config.py b/libs/uniharness_demo/backend/uniharness_api/routes/config.py similarity index 96% rename from libs/hexagent_demo/backend/hexagent_api/routes/config.py rename to libs/uniharness_demo/backend/uniharness_api/routes/config.py index f7b1ef26..46b99eac 100644 --- a/libs/hexagent_demo/backend/hexagent_api/routes/config.py +++ b/libs/uniharness_demo/backend/uniharness_api/routes/config.py @@ -9,8 +9,8 @@ from fastapi import APIRouter -from hexagent_api.agent_manager import agent_manager -from hexagent_api.config import ( +from uniharness_api.agent_manager import agent_manager +from uniharness_api.config import ( AgentConfig, AppConfig, McpServerConfig, @@ -99,7 +99,7 @@ async def test_mcp_connection(body: dict[str, Any]) -> dict[str, Any]: Accepts the same shape as a single McpServer entry from the frontend. Returns { ok: true, tools: int } on success or { ok: false, error: str }. """ - from hexagent.mcp._client import McpClient + from uniharness.mcp._client import McpClient server_type = body.get("type", "http") name = body.get("name", "test") diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/conversations.py b/libs/uniharness_demo/backend/uniharness_api/routes/conversations.py similarity index 95% rename from libs/hexagent_demo/backend/hexagent_api/routes/conversations.py rename to libs/uniharness_demo/backend/uniharness_api/routes/conversations.py index 600442cd..4a660a17 100644 --- a/libs/hexagent_demo/backend/hexagent_api/routes/conversations.py +++ b/libs/uniharness_demo/backend/uniharness_api/routes/conversations.py @@ -10,11 +10,11 @@ from fastapi import APIRouter, HTTPException -from hexagent_api.agent_manager import agent_manager -from hexagent_api.models import ConversationCreateRequest, ConversationUpdateRequest -from hexagent_api.paths import uploads_dir -from hexagent_api.store import session_store, store -from hexagent_api.stream_manager import stream_manager +from uniharness_api.agent_manager import agent_manager +from uniharness_api.models import ConversationCreateRequest, ConversationUpdateRequest +from uniharness_api.paths import uploads_dir +from uniharness_api.store import session_store, store +from uniharness_api.stream_manager import stream_manager logger = logging.getLogger(__name__) diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/sessions.py b/libs/uniharness_demo/backend/uniharness_api/routes/sessions.py similarity index 96% rename from libs/hexagent_demo/backend/hexagent_api/routes/sessions.py rename to libs/uniharness_demo/backend/uniharness_api/routes/sessions.py index 6ce70063..63b8b8f9 100644 --- a/libs/hexagent_demo/backend/hexagent_api/routes/sessions.py +++ b/libs/uniharness_demo/backend/uniharness_api/routes/sessions.py @@ -10,12 +10,12 @@ from pathlib import Path from pydantic import BaseModel, Field -from hexagent.computer.base import SESSION_UPLOADS_DIR -from hexagent.exceptions import VMMountConflictError +from uniharness.computer.base import SESSION_UPLOADS_DIR +from uniharness.exceptions import VMMountConflictError -from hexagent_api.agent_manager import agent_manager -from hexagent_api.paths import uploads_dir -from hexagent_api.store import session_store +from uniharness_api.agent_manager import agent_manager +from uniharness_api.paths import uploads_dir +from uniharness_api.store import session_store logger = logging.getLogger(__name__) diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/setup.py b/libs/uniharness_demo/backend/uniharness_api/routes/setup.py similarity index 97% rename from libs/hexagent_demo/backend/hexagent_api/routes/setup.py rename to libs/uniharness_demo/backend/uniharness_api/routes/setup.py index 61d9a89d..308bfb9d 100644 --- a/libs/hexagent_demo/backend/hexagent_api/routes/setup.py +++ b/libs/uniharness_demo/backend/uniharness_api/routes/setup.py @@ -27,7 +27,7 @@ from fastapi import APIRouter, HTTPException from fastapi.responses import Response, StreamingResponse -from hexagent_api.paths import data_dir, deps_dir, vm_lima_dir, vm_setup_dir, vm_setup_lite_dir +from uniharness_api.paths import data_dir, deps_dir, vm_lima_dir, vm_setup_dir, vm_setup_lite_dir logger = logging.getLogger(__name__) @@ -179,11 +179,11 @@ def _lima_status() -> dict[str, object]: # WSL (Windows) # --------------------------------------------------------------------------- -_WSL_INSTANCE = "hexagent" +_WSL_INSTANCE = "uniharness" _WSL_EXPORT_SOURCE = "Ubuntu" _WSL_PREBUILT_CANDIDATES = ( - "hexagent-prebuilt.tar", - "hexagent.tar", + "uniharness-prebuilt.tar", + "uniharness.tar", ) @@ -373,7 +373,7 @@ async def _wsl_probe_start() -> tuple[bool, str]: # ``wsl -l -v`` uses the Windows display language for the STATE column. -# Cowork only needs the ``hexagent`` distro to exist; WSL starts it on demand. +# Cowork only needs the ``uniharness`` distro to exist; WSL starts it on demand. _WSL_COWORK_READY_STATES = frozenset( { "Running", @@ -526,7 +526,7 @@ def sse(event: str, data: dict[str, object]) -> str: version = await _resolve_lima_version() yield sse("progress", {"step": "downloading", "message": f"Downloading Lima v{version}..."}) - tmp_dir = tempfile.mkdtemp(prefix="hexagent_lima_") + tmp_dir = tempfile.mkdtemp(prefix="uniharness_lima_") tarball_path = os.path.join(tmp_dir, "lima.tar.gz") try: @@ -737,7 +737,7 @@ async def install_vm_backend() -> StreamingResponse: # - Multiple concurrent viewers are supported # --------------------------------------------------------------------------- -_LIMA_INSTANCE = "hexagent" +_LIMA_INSTANCE = "uniharness" def _sse(event: str, data: dict[str, object]) -> str: @@ -985,7 +985,7 @@ async def _run_lima(self) -> None: return # Instance doesn't exist — full build - yaml_path = vm_lima_dir() / "hexagent.yaml" + yaml_path = vm_lima_dir() / "uniharness.yaml" if not yaml_path.is_file(): self._emit("error", {"message": f"VM config not found: {yaml_path}"}) self._status = "error" @@ -1051,7 +1051,7 @@ async def _run_wsl(self) -> None: else: err = _combine_wsl_output(stdout_b, stderr_b) if _looks_like_missing_wsl_disk(err): - self._emit("progress", {"step": "creating", "message": "Detected broken WSL distro disk. Recreating HexAgent distro..."}) + self._emit("progress", {"step": "creating", "message": "Detected broken WSL distro disk. Recreating UniHarness distro..."}) proc_unreg = await asyncio.create_subprocess_exec( wsl_exe, "--unregister", _WSL_INSTANCE, stdout=asyncio.subprocess.PIPE, @@ -1061,7 +1061,7 @@ async def _run_wsl(self) -> None: u_out_b, u_err_b = await self._communicate_with_heartbeat( proc_unreg, step="creating", - message="Removing broken HexAgent WSL distro...", + message="Removing broken UniHarness WSL distro...", ) if proc_unreg.returncode != 0: u_err = _combine_wsl_output(u_out_b, u_err_b) @@ -1079,9 +1079,9 @@ async def _run_wsl(self) -> None: prebuilt_tar = _wsl_prebuilt_tar_path() import_dir = data_dir() / "wsl" / _WSL_INSTANCE / "disk" - # Distro does not exist: prefer bundled prebuilt HexAgent rootfs. + # Distro does not exist: prefer bundled prebuilt UniHarness rootfs. if prebuilt_tar is not None: - self._emit("progress", {"step": "creating", "message": "Importing bundled HexAgent VM image..."}) + self._emit("progress", {"step": "creating", "message": "Importing bundled UniHarness VM image..."}) if import_dir.exists(): shutil.rmtree(import_dir, ignore_errors=True) import_dir.mkdir(parents=True, exist_ok=True) @@ -1095,7 +1095,7 @@ async def _run_wsl(self) -> None: _, err_b = await self._communicate_with_heartbeat( proc_import, step="creating", - message="Importing bundled HexAgent VM image...", + message="Importing bundled UniHarness VM image...", progress_info=lambda: f"(image ~{(prebuilt_tar.stat().st_size / (1024 * 1024)):.1f} MB)", ) if proc_import.returncode != 0: @@ -1105,7 +1105,7 @@ async def _run_wsl(self) -> None: self._error = f"exit {proc_import.returncode}" return - self._emit("progress", {"step": "starting", "message": "Starting imported HexAgent WSL distro..."}) + self._emit("progress", {"step": "starting", "message": "Starting imported UniHarness WSL distro..."}) proc_start = await asyncio.create_subprocess_exec( wsl_exe, "-d", _WSL_INSTANCE, "--", "echo", "ok", stdout=asyncio.subprocess.PIPE, @@ -1115,7 +1115,7 @@ async def _run_wsl(self) -> None: out_b, err_b = await self._communicate_with_heartbeat( proc_start, step="starting", - message="Starting imported HexAgent WSL distro...", + message="Starting imported UniHarness WSL distro...", ) if proc_start.returncode == 0: self._emit("done", {"message": "WSL distro imported from bundled image and started successfully"}) @@ -1189,7 +1189,7 @@ async def _run_wsl(self) -> None: self._error = f"exit {proc_export.returncode}" return - self._emit("progress", {"step": "creating", "message": "Importing HexAgent WSL distro..."}) + self._emit("progress", {"step": "creating", "message": "Importing UniHarness WSL distro..."}) proc_import = await asyncio.create_subprocess_exec( wsl_exe, "--import", _WSL_INSTANCE, str(import_dir), str(export_tar), "--version", "2", stdout=asyncio.subprocess.PIPE, @@ -1199,7 +1199,7 @@ async def _run_wsl(self) -> None: _, err_b = await self._communicate_with_heartbeat( proc_import, step="creating", - message="Importing HexAgent WSL distro...", + message="Importing UniHarness WSL distro...", ) if proc_import.returncode != 0: err = _decode_wsl_output(err_b or b"").strip() @@ -1208,7 +1208,7 @@ async def _run_wsl(self) -> None: self._error = f"exit {proc_import.returncode}" return - self._emit("progress", {"step": "starting", "message": "Starting HexAgent WSL distro..."}) + self._emit("progress", {"step": "starting", "message": "Starting UniHarness WSL distro..."}) proc_start = await asyncio.create_subprocess_exec( wsl_exe, "-d", _WSL_INSTANCE, "--", "echo", "ok", stdout=asyncio.subprocess.PIPE, @@ -1218,7 +1218,7 @@ async def _run_wsl(self) -> None: out_b, err_b = await self._communicate_with_heartbeat( proc_start, step="starting", - message="Starting HexAgent WSL distro...", + message="Starting UniHarness WSL distro...", ) if proc_start.returncode == 0: self._emit("done", {"message": "WSL distro created and started successfully"}) @@ -1260,9 +1260,9 @@ async def _stream_stderr(self, proc: asyncio.subprocess.Process) -> str: # Provision Manager — runs setup.sh inside the VM # --------------------------------------------------------------------------- -_SETUP_MARKER_DIR = "/var/lib/hexagent/setup" -_SETUP_LOG_DIR = "/var/log/hexagent/setup" -_SETUP_VM_DIR = "/tmp/hexagent-setup" +_SETUP_MARKER_DIR = "/var/lib/uniharness/setup" +_SETUP_LOG_DIR = "/var/log/uniharness/setup" +_SETUP_VM_DIR = "/tmp/uniharness-setup" # Step IDs that setup.sh discovers (must match filenames in steps/) _PROVISION_STEPS = [ @@ -1307,14 +1307,14 @@ async def _run_lima(self, **kwargs: object) -> None: return # Tar locally, copy tarball, extract in VM - with tempfile.TemporaryDirectory(prefix="hexagent_setup_") as tmp: + with tempfile.TemporaryDirectory(prefix="uniharness_setup_") as tmp: tar_path = os.path.join(tmp, "setup.tar.gz") _sp.run( ["tar", "-czf", tar_path, "-C", str(setup_dir.parent), setup_dir.name], check=True, ) copy_proc = await asyncio.create_subprocess_exec( - "limactl", "copy", tar_path, f"{_LIMA_INSTANCE}:/tmp/hexagent-setup.tar.gz", + "limactl", "copy", tar_path, f"{_LIMA_INSTANCE}:/tmp/uniharness-setup.tar.gz", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) @@ -1328,8 +1328,8 @@ async def _run_lima(self, **kwargs: object) -> None: # Extract in VM rc, _, err = await _lima_shell( f"sudo rm -rf {_SETUP_VM_DIR} && sudo mkdir -p {_SETUP_VM_DIR} && " - f"sudo tar -xzf /tmp/hexagent-setup.tar.gz -C {_SETUP_VM_DIR} --strip-components=1 && " - f"rm -f /tmp/hexagent-setup.tar.gz", + f"sudo tar -xzf /tmp/uniharness-setup.tar.gz -C {_SETUP_VM_DIR} --strip-components=1 && " + f"rm -f /tmp/uniharness-setup.tar.gz", timeout=30, ) if rc != 0: diff --git a/libs/hexagent_demo/backend/hexagent_api/routes/skills.py b/libs/uniharness_demo/backend/uniharness_api/routes/skills.py similarity index 97% rename from libs/hexagent_demo/backend/hexagent_api/routes/skills.py rename to libs/uniharness_demo/backend/uniharness_api/routes/skills.py index 67766bfa..9f0fb9a0 100644 --- a/libs/hexagent_demo/backend/hexagent_api/routes/skills.py +++ b/libs/uniharness_demo/backend/uniharness_api/routes/skills.py @@ -20,10 +20,10 @@ from fastapi import APIRouter, File, HTTPException, UploadFile from pydantic import BaseModel -from hexagent.exceptions import SkillError -from hexagent.harness.skill_spec import parse_skill_md, validate_skill_dir_name +from uniharness.exceptions import SkillError +from uniharness.harness.skill_spec import parse_skill_md, validate_skill_dir_name -from hexagent_api.paths import bundled_skills_dir, skills_dir +from uniharness_api.paths import bundled_skills_dir, skills_dir logger = logging.getLogger(__name__) diff --git a/libs/hexagent_demo/backend/hexagent_api/server.py b/libs/uniharness_demo/backend/uniharness_api/server.py similarity index 94% rename from libs/hexagent_demo/backend/hexagent_api/server.py rename to libs/uniharness_demo/backend/uniharness_api/server.py index a24e314b..54461c0e 100644 --- a/libs/hexagent_demo/backend/hexagent_api/server.py +++ b/libs/uniharness_demo/backend/uniharness_api/server.py @@ -17,7 +17,7 @@ def main() -> None: if bundle_dir not in sys.path: sys.path.insert(0, bundle_dir) - from hexagent_api.main import app + from uniharness_api.main import app host = os.environ.get("HOST", "127.0.0.1") port = int(os.environ.get("PORT", "8000")) diff --git a/libs/hexagent_demo/backend/hexagent_api/store.py b/libs/uniharness_demo/backend/uniharness_api/store.py similarity index 100% rename from libs/hexagent_demo/backend/hexagent_api/store.py rename to libs/uniharness_demo/backend/uniharness_api/store.py diff --git a/libs/hexagent_demo/backend/hexagent_api/stream_manager.py b/libs/uniharness_demo/backend/uniharness_api/stream_manager.py similarity index 100% rename from libs/hexagent_demo/backend/hexagent_api/stream_manager.py rename to libs/uniharness_demo/backend/uniharness_api/stream_manager.py diff --git a/libs/hexagent_demo/backend/uv.lock b/libs/uniharness_demo/backend/uv.lock similarity index 99% rename from libs/hexagent_demo/backend/uv.lock rename to libs/uniharness_demo/backend/uv.lock index f452a262..a2e69c5a 100644 --- a/libs/hexagent_demo/backend/uv.lock +++ b/libs/uniharness_demo/backend/uv.lock @@ -736,82 +736,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] -[[package]] -name = "hexagent" -source = { editable = "../../hexagent" } -dependencies = [ - { name = "cachetools" }, - { name = "e2b" }, - { name = "httpx" }, - { name = "langchain" }, - { name = "langchain-anthropic" }, - { name = "langchain-core" }, - { name = "langchain-deepseek" }, - { name = "langchain-openai" }, - { name = "mcp" }, - { name = "petname" }, - { name = "pyyaml" }, - { name = "tenacity" }, - { name = "wcmatch" }, -] - -[package.metadata] -requires-dist = [ - { name = "braintrust", marker = "extra == 'braintrust'", specifier = ">=0.7.0" }, - { name = "braintrust", marker = "extra == 'observe'", specifier = ">=0.7.0" }, - { name = "braintrust-langchain", marker = "extra == 'braintrust'", specifier = ">=0.2.1" }, - { name = "braintrust-langchain", marker = "extra == 'observe'", specifier = ">=0.2.1" }, - { name = "cachetools", specifier = ">=5.0.0" }, - { name = "e2b", specifier = ">=2.0.0,<3.0.0" }, - { name = "httpx", specifier = ">=0.27.0" }, - { name = "langchain", specifier = ">=1.2.3,<2.0.0" }, - { name = "langchain-anthropic", specifier = ">=1.3.1,<2.0.0" }, - { name = "langchain-core", specifier = ">=1.2.6,<2.0.0" }, - { name = "langchain-deepseek", specifier = ">=1.0.1" }, - { name = "langchain-openai", specifier = ">=1.0.2,<2.0.0" }, - { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.1.0" }, - { name = "langsmith", marker = "extra == 'observe'", specifier = ">=0.1.0" }, - { name = "mcp", specifier = ">=1.25.0,<2.0.0" }, - { name = "petname", specifier = ">=2.9" }, - { name = "pyyaml", specifier = ">=6.0" }, - { name = "tenacity", specifier = ">=8.0.0" }, - { name = "wcmatch" }, -] -provides-extras = ["braintrust", "langsmith", "observe"] - -[package.metadata.requires-dev] -test = [ - { name = "mypy", specifier = ">=1.18.1,<1.19.0" }, - { name = "pytest" }, - { name = "pytest-asyncio", specifier = ">=1.3.0" }, - { name = "pytest-cov" }, - { name = "pytest-xdist" }, - { name = "ruff", specifier = ">=0.12.2,<0.13.0" }, - { name = "types-cachetools" }, - { name = "types-pyyaml" }, -] - -[[package]] -name = "hexagent-demo-backend" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "fastapi" }, - { name = "langchain-deepseek" }, - { name = "hexagent" }, - { name = "python-dotenv" }, - { name = "uvicorn", extra = ["standard"] }, -] - -[package.metadata] -requires-dist = [ - { name = "fastapi", specifier = ">=0.115.0" }, - { name = "langchain-deepseek", specifier = ">=0.1.0" }, - { name = "hexagent", editable = "../../hexagent" }, - { name = "python-dotenv", specifier = ">=1.0.0" }, - { name = "uvicorn", extras = ["standard"], specifier = ">=0.34.0" }, -] - [[package]] name = "openai" version = "2.24.0" @@ -1536,6 +1460,82 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] +[[package]] +name = "uniharness" +source = { editable = "../../uniharness" } +dependencies = [ + { name = "cachetools" }, + { name = "e2b" }, + { name = "httpx" }, + { name = "langchain" }, + { name = "langchain-anthropic" }, + { name = "langchain-core" }, + { name = "langchain-deepseek" }, + { name = "langchain-openai" }, + { name = "mcp" }, + { name = "petname" }, + { name = "pyyaml" }, + { name = "tenacity" }, + { name = "wcmatch" }, +] + +[package.metadata] +requires-dist = [ + { name = "braintrust", marker = "extra == 'braintrust'", specifier = ">=0.7.0" }, + { name = "braintrust", marker = "extra == 'observe'", specifier = ">=0.7.0" }, + { name = "braintrust-langchain", marker = "extra == 'braintrust'", specifier = ">=0.2.1" }, + { name = "braintrust-langchain", marker = "extra == 'observe'", specifier = ">=0.2.1" }, + { name = "cachetools", specifier = ">=5.0.0" }, + { name = "e2b", specifier = ">=2.0.0,<3.0.0" }, + { name = "httpx", specifier = ">=0.27.0" }, + { name = "langchain", specifier = ">=1.2.3,<2.0.0" }, + { name = "langchain-anthropic", specifier = ">=1.3.1,<2.0.0" }, + { name = "langchain-core", specifier = ">=1.2.6,<2.0.0" }, + { name = "langchain-deepseek", specifier = ">=1.0.1" }, + { name = "langchain-openai", specifier = ">=1.0.2,<2.0.0" }, + { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.1.0" }, + { name = "langsmith", marker = "extra == 'observe'", specifier = ">=0.1.0" }, + { name = "mcp", specifier = ">=1.25.0,<2.0.0" }, + { name = "petname", specifier = ">=2.9" }, + { name = "pyyaml", specifier = ">=6.0" }, + { name = "tenacity", specifier = ">=8.0.0" }, + { name = "wcmatch" }, +] +provides-extras = ["braintrust", "langsmith", "observe"] + +[package.metadata.requires-dev] +test = [ + { name = "mypy", specifier = ">=1.18.1,<1.19.0" }, + { name = "pytest" }, + { name = "pytest-asyncio", specifier = ">=1.3.0" }, + { name = "pytest-cov" }, + { name = "pytest-xdist" }, + { name = "ruff", specifier = ">=0.12.2,<0.13.0" }, + { name = "types-cachetools" }, + { name = "types-pyyaml" }, +] + +[[package]] +name = "uniharness-demo-backend" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "fastapi" }, + { name = "langchain-deepseek" }, + { name = "python-dotenv" }, + { name = "uniharness" }, + { name = "uvicorn", extra = ["standard"] }, +] + +[package.metadata] +requires-dist = [ + { name = "fastapi", specifier = ">=0.115.0" }, + { name = "langchain-deepseek", specifier = ">=0.1.0" }, + { name = "python-dotenv", specifier = ">=1.0.0" }, + { name = "uniharness", editable = "../../uniharness" }, + { name = "uvicorn", extras = ["standard"], specifier = ">=0.34.0" }, +] + [[package]] name = "urllib3" version = "2.6.3" diff --git a/libs/hexagent_demo/electron/.gitignore b/libs/uniharness_demo/electron/.gitignore similarity index 100% rename from libs/hexagent_demo/electron/.gitignore rename to libs/uniharness_demo/electron/.gitignore diff --git a/libs/hexagent_demo/electron/main.js b/libs/uniharness_demo/electron/main.js similarity index 98% rename from libs/hexagent_demo/electron/main.js rename to libs/uniharness_demo/electron/main.js index f7a5cf5e..4c661a09 100644 --- a/libs/hexagent_demo/electron/main.js +++ b/libs/uniharness_demo/electron/main.js @@ -15,9 +15,9 @@ let backendStderr = ""; // capture stderr for error reporting // ── User data directory ───────────────────────────────────────────────────── // Store config.json, .env, etc. in a persistent location: -// macOS: ~/Library/Application Support/HexAgent/ -// Windows: %APPDATA%/HexAgent/ -// Linux: ~/.config/HexAgent/ +// macOS: ~/Library/Application Support/UniHarness/ +// Windows: %APPDATA%/UniHarness/ +// Linux: ~/.config/UniHarness/ const userDataDir = app.getPath("userData"); function ensureUserData() { @@ -115,7 +115,7 @@ async function spawnBackend() { [ "run", "uvicorn", - "hexagent_api.main:app", + "uniharness_api.main:app", "--host", "127.0.0.1", "--port", @@ -124,7 +124,7 @@ async function spawnBackend() { { cwd: backendDir, stdio: "pipe" } ); } else { - let binaryName = "hexagent_api_server"; + let binaryName = "uniharness_api_server"; if (process.platform === "win32") binaryName += ".exe"; const binaryPath = path.join( process.resourcesPath, @@ -166,7 +166,7 @@ async function spawnBackend() { PATH: newPath, HOST: "127.0.0.1", PORT: String(port), - HEXAGENT_DATA_DIR: userDataDir, + UNIHARNESS_DATA_DIR: userDataDir, }, }); } diff --git a/libs/hexagent_demo/electron/package-lock.json b/libs/uniharness_demo/electron/package-lock.json similarity index 99% rename from libs/hexagent_demo/electron/package-lock.json rename to libs/uniharness_demo/electron/package-lock.json index 89a5430b..c580f9ae 100644 --- a/libs/hexagent_demo/electron/package-lock.json +++ b/libs/uniharness_demo/electron/package-lock.json @@ -1,11 +1,11 @@ { - "name": "hexagent", + "name": "uniharness", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "hexagent", + "name": "uniharness", "version": "0.0.1", "dependencies": { "tree-kill": "^1.2.2" diff --git a/libs/hexagent_demo/electron/package.json b/libs/uniharness_demo/electron/package.json similarity index 93% rename from libs/hexagent_demo/electron/package.json rename to libs/uniharness_demo/electron/package.json index 75fd69b7..014e4354 100644 --- a/libs/hexagent_demo/electron/package.json +++ b/libs/uniharness_demo/electron/package.json @@ -1,7 +1,7 @@ { - "name": "hexagent", + "name": "uniharness", "version": "0.0.1", - "description": "HexAgent Desktop App", + "description": "UniHarness Desktop App", "main": "main.js", "scripts": { "dev": "ELECTRON_DEV=1 electron .", @@ -21,8 +21,8 @@ "electron-builder": "^25.1.8" }, "build": { - "appId": "com.hexagent.app", - "productName": "HexAgent", + "appId": "com.uniharness.app", + "productName": "UniHarness", "directories": { "buildResources": "resources", "output": "dist" diff --git a/libs/hexagent_demo/electron/preload.js b/libs/uniharness_demo/electron/preload.js similarity index 100% rename from libs/hexagent_demo/electron/preload.js rename to libs/uniharness_demo/electron/preload.js diff --git a/libs/hexagent_demo/electron/resources/background.png b/libs/uniharness_demo/electron/resources/background.png similarity index 100% rename from libs/hexagent_demo/electron/resources/background.png rename to libs/uniharness_demo/electron/resources/background.png diff --git a/libs/hexagent_demo/electron/resources/icon.icns b/libs/uniharness_demo/electron/resources/icon.icns similarity index 100% rename from libs/hexagent_demo/electron/resources/icon.icns rename to libs/uniharness_demo/electron/resources/icon.icns diff --git a/libs/hexagent_demo/electron/resources/icon.ico b/libs/uniharness_demo/electron/resources/icon.ico similarity index 100% rename from libs/hexagent_demo/electron/resources/icon.ico rename to libs/uniharness_demo/electron/resources/icon.ico diff --git a/libs/uniharness_demo/electron/resources/installer.nsh b/libs/uniharness_demo/electron/resources/installer.nsh new file mode 100644 index 00000000..f1323ba6 --- /dev/null +++ b/libs/uniharness_demo/electron/resources/installer.nsh @@ -0,0 +1,3 @@ +!macro customUnInstall + RMDir /r "$PROFILE\.uniharness" +!macroend diff --git a/libs/hexagent_demo/electron/scripts/afterPack.js b/libs/uniharness_demo/electron/scripts/afterPack.js similarity index 95% rename from libs/hexagent_demo/electron/scripts/afterPack.js rename to libs/uniharness_demo/electron/scripts/afterPack.js index 72955f4b..9573d317 100644 --- a/libs/hexagent_demo/electron/scripts/afterPack.js +++ b/libs/uniharness_demo/electron/scripts/afterPack.js @@ -34,7 +34,7 @@ exports.default = async function afterPack(context) { `find "${backendDir}" -type f \\( -name "*.dylib" -o -name "*.so" \\) -exec codesign --force --sign - {} \\;`, { stdio: "inherit" } ); - const backendBin = path.join(backendDir, "hexagent_api_server"); + const backendBin = path.join(backendDir, "uniharness_api_server"); if (fs.existsSync(backendBin)) { execSync(`codesign --force --sign - "${backendBin}"`, { stdio: "inherit", @@ -58,7 +58,7 @@ exports.default = async function afterPack(context) { // Step 2 overwrote limactl's signature without entitlements — we must // apply it again AFTER the deep sign. const limaBin = path.join(appPath, "Contents", "Resources", "lima", "bin", "limactl"); - const entitlements = path.join(__dirname, "..", "..", "..", "hexagent", "sandbox", "vm", "lima", "entitlements.plist"); + const entitlements = path.join(__dirname, "..", "..", "..", "uniharness", "sandbox", "vm", "lima", "entitlements.plist"); if (fs.existsSync(limaBin)) { if (!fs.existsSync(entitlements)) { console.error("[afterPack] FATAL: entitlements.plist not found at", entitlements); diff --git a/libs/hexagent_demo/electron/scripts/build-all.ps1 b/libs/uniharness_demo/electron/scripts/build-all.ps1 similarity index 93% rename from libs/hexagent_demo/electron/scripts/build-all.ps1 rename to libs/uniharness_demo/electron/scripts/build-all.ps1 index d26a5905..a26e6f64 100644 --- a/libs/hexagent_demo/electron/scripts/build-all.ps1 +++ b/libs/uniharness_demo/electron/scripts/build-all.ps1 @@ -3,10 +3,10 @@ $ErrorActionPreference = 'Stop' $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $ElectronDir = Resolve-Path "$ScriptDir\.." $Target = if ($args.Count -gt 0) { $args[0] } else { 'win' } -$EmbedWslPrebuilt = ($env:OPENAGENT_EMBED_WSL_PREBUILT -eq "1") +$EmbedWslPrebuilt = ($env:UNIHARNESS_EMBED_WSL_PREBUILT -eq "1") Write-Host '=========================================' -Write-Host ' HexAgent Desktop - Build ('$Target')' +Write-Host ' UniHarness Desktop - Build ('$Target')' Write-Host '=========================================' Write-Host '' diff --git a/libs/hexagent_demo/electron/scripts/build-all.sh b/libs/uniharness_demo/electron/scripts/build-all.sh similarity index 96% rename from libs/hexagent_demo/electron/scripts/build-all.sh rename to libs/uniharness_demo/electron/scripts/build-all.sh index d491840b..935d8f83 100755 --- a/libs/hexagent_demo/electron/scripts/build-all.sh +++ b/libs/uniharness_demo/electron/scripts/build-all.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Build HexAgent desktop app for specified platforms. +# Build UniHarness desktop app for specified platforms. # # Usage: # bash build-all.sh # macOS arm64 (default) @@ -14,7 +14,7 @@ ELECTRON_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" TARGET="${1:-mac-arm64}" echo "=========================================" -echo " HexAgent Desktop — Build ($TARGET)" +echo " UniHarness Desktop — Build ($TARGET)" echo "=========================================" echo "" diff --git a/libs/hexagent_demo/electron/scripts/build-backend.ps1 b/libs/uniharness_demo/electron/scripts/build-backend.ps1 similarity index 85% rename from libs/hexagent_demo/electron/scripts/build-backend.ps1 rename to libs/uniharness_demo/electron/scripts/build-backend.ps1 index 16cbd8e2..dfc8c9e1 100644 --- a/libs/hexagent_demo/electron/scripts/build-backend.ps1 +++ b/libs/uniharness_demo/electron/scripts/build-backend.ps1 @@ -7,7 +7,7 @@ $BackendDir = Resolve-Path "$ElectronDir\..\backend" Write-Host "==> Installing PyInstaller..." Set-Location $BackendDir $pyinstallerArgs = @( - "--name", "hexagent_api_server", + "--name", "uniharness_api_server", "--onedir", "--noconfirm", "--hidden-import", "uvicorn.logging", @@ -26,12 +26,12 @@ $pyinstallerArgs = @( "--hidden-import", "uvicorn.lifespan", "--hidden-import", "uvicorn.lifespan.on", "--hidden-import", "uvicorn.lifespan.off", - "--collect-submodules", "hexagent_api", - "--collect-submodules", "hexagent", - "--collect-data", "hexagent", - "--add-data", "../../hexagent/sandbox/vm;sandbox/vm", + "--collect-submodules", "uniharness_api", + "--collect-submodules", "uniharness", + "--collect-data", "uniharness", + "--add-data", "../../uniharness/sandbox/vm;sandbox/vm", "--add-data", "skills;skills", - "hexagent_api/server.py" + "uniharness_api/server.py" ) # Ensure the skills directory exists so --add-data doesn't fail @@ -56,6 +56,6 @@ Write-Host "==> Copying dist to electron/backend_dist..." if (Test-Path "$ElectronDir\backend_dist") { Remove-Item -Recurse -Force "$ElectronDir\backend_dist" } -Copy-Item -Recurse "$BackendDir\dist\hexagent_api_server" "$ElectronDir\backend_dist" +Copy-Item -Recurse "$BackendDir\dist\uniharness_api_server" "$ElectronDir\backend_dist" Write-Host "==> Backend build complete." diff --git a/libs/hexagent_demo/electron/scripts/build-backend.sh b/libs/uniharness_demo/electron/scripts/build-backend.sh similarity index 90% rename from libs/hexagent_demo/electron/scripts/build-backend.sh rename to libs/uniharness_demo/electron/scripts/build-backend.sh index 10661e62..ac4cf42d 100755 --- a/libs/hexagent_demo/electron/scripts/build-backend.sh +++ b/libs/uniharness_demo/electron/scripts/build-backend.sh @@ -15,7 +15,7 @@ TARGET_ARCH="${1:-}" # ── PyInstaller flags (shared) ── PYINSTALLER_ARGS=( - --name hexagent_api_server + --name uniharness_api_server --onedir --noconfirm --clean @@ -35,12 +35,12 @@ PYINSTALLER_ARGS=( --hidden-import uvicorn.lifespan --hidden-import uvicorn.lifespan.on --hidden-import uvicorn.lifespan.off - --collect-submodules hexagent_api - --collect-submodules hexagent - --collect-data hexagent + --collect-submodules uniharness_api + --collect-submodules uniharness + --collect-data uniharness --add-data "skills:skills" - --add-data "../../hexagent/sandbox/vm:sandbox/vm" - hexagent_api/server.py + --add-data "../../uniharness/sandbox/vm:sandbox/vm" + uniharness_api/server.py ) # Ensure the skills directory exists so --add-data doesn't fail @@ -70,7 +70,7 @@ run_pyinstaller() { echo "==> Copying dist to electron/backend_dist..." rm -rf "$ELECTRON_DIR/backend_dist" - cp -r "$BACKEND_DIR/dist/hexagent_api_server" "$ELECTRON_DIR/backend_dist" + cp -r "$BACKEND_DIR/dist/uniharness_api_server" "$ELECTRON_DIR/backend_dist" } run_pyinstaller_arch() { @@ -113,7 +113,7 @@ run_pyinstaller_arch() { unset UV_PROJECT_ENVIRONMENT rm -rf "$ELECTRON_DIR/backend_dist" - cp -r "$BACKEND_DIR/dist/hexagent_api_server" "$ELECTRON_DIR/backend_dist" + cp -r "$BACKEND_DIR/dist/uniharness_api_server" "$ELECTRON_DIR/backend_dist" } # ── Build based on target architecture ── @@ -139,9 +139,9 @@ case "$TARGET_ARCH" in echo "==> Creating universal binary with lipo..." cp -r "$ELECTRON_DIR/backend_dist_arm64" "$ELECTRON_DIR/backend_dist" lipo -create \ - "$ELECTRON_DIR/backend_dist_arm64/hexagent_api_server" \ - "$ELECTRON_DIR/backend_dist_x64/hexagent_api_server" \ - -output "$ELECTRON_DIR/backend_dist/hexagent_api_server" + "$ELECTRON_DIR/backend_dist_arm64/uniharness_api_server" \ + "$ELECTRON_DIR/backend_dist_x64/uniharness_api_server" \ + -output "$ELECTRON_DIR/backend_dist/uniharness_api_server" rm -rf "$ELECTRON_DIR/backend_dist_arm64" "$ELECTRON_DIR/backend_dist_x64" ;; *) diff --git a/libs/hexagent_demo/electron/scripts/build-frontend.sh b/libs/uniharness_demo/electron/scripts/build-frontend.sh similarity index 100% rename from libs/hexagent_demo/electron/scripts/build-frontend.sh rename to libs/uniharness_demo/electron/scripts/build-frontend.sh diff --git a/libs/hexagent_demo/electron/scripts/create-dmg.sh b/libs/uniharness_demo/electron/scripts/create-dmg.sh similarity index 100% rename from libs/hexagent_demo/electron/scripts/create-dmg.sh rename to libs/uniharness_demo/electron/scripts/create-dmg.sh diff --git a/libs/hexagent_demo/electron/scripts/prepare-wsl-prebuilt.ps1 b/libs/uniharness_demo/electron/scripts/prepare-wsl-prebuilt.ps1 similarity index 83% rename from libs/hexagent_demo/electron/scripts/prepare-wsl-prebuilt.ps1 rename to libs/uniharness_demo/electron/scripts/prepare-wsl-prebuilt.ps1 index 33396e6e..0fa54b97 100644 --- a/libs/hexagent_demo/electron/scripts/prepare-wsl-prebuilt.ps1 +++ b/libs/uniharness_demo/electron/scripts/prepare-wsl-prebuilt.ps1 @@ -1,10 +1,10 @@ $ErrorActionPreference = "Stop" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path -$HexagentRoot = Resolve-Path "$ScriptDir\..\..\.." -$PrebuiltDir = Join-Path $HexagentRoot "hexagent\sandbox\vm\wsl\prebuilt" -$PrebuiltTar = Join-Path $PrebuiltDir "openagent-prebuilt.tar" -$DistroName = "openagent" +$UniharnessRoot = Resolve-Path "$ScriptDir\..\..\.." +$PrebuiltDir = Join-Path $UniharnessRoot "uniharness\sandbox\vm\wsl\prebuilt" +$PrebuiltTar = Join-Path $PrebuiltDir "uniharness-prebuilt.tar" +$DistroName = "uniharness" if ($env:OS -ne "Windows_NT") { Write-Host "Skipping WSL prebuilt export: non-Windows environment." diff --git a/libs/hexagent_demo/frontend/.gitignore b/libs/uniharness_demo/frontend/.gitignore similarity index 100% rename from libs/hexagent_demo/frontend/.gitignore rename to libs/uniharness_demo/frontend/.gitignore diff --git a/libs/hexagent_demo/frontend/eslint.config.js b/libs/uniharness_demo/frontend/eslint.config.js similarity index 100% rename from libs/hexagent_demo/frontend/eslint.config.js rename to libs/uniharness_demo/frontend/eslint.config.js diff --git a/libs/hexagent_demo/frontend/index.html b/libs/uniharness_demo/frontend/index.html similarity index 100% rename from libs/hexagent_demo/frontend/index.html rename to libs/uniharness_demo/frontend/index.html diff --git a/libs/hexagent_demo/frontend/package-lock.json b/libs/uniharness_demo/frontend/package-lock.json similarity index 99% rename from libs/hexagent_demo/frontend/package-lock.json rename to libs/uniharness_demo/frontend/package-lock.json index ec9d4b22..954e807b 100644 --- a/libs/hexagent_demo/frontend/package-lock.json +++ b/libs/uniharness_demo/frontend/package-lock.json @@ -1,11 +1,11 @@ { - "name": "hexagent-demo-frontend", + "name": "uniharness-demo-frontend", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "hexagent-demo-frontend", + "name": "uniharness-demo-frontend", "version": "0.0.1", "dependencies": { "docx-preview": "^0.3.7", diff --git a/libs/hexagent_demo/frontend/package.json b/libs/uniharness_demo/frontend/package.json similarity index 96% rename from libs/hexagent_demo/frontend/package.json rename to libs/uniharness_demo/frontend/package.json index 3ce315d2..7b123cd5 100644 --- a/libs/hexagent_demo/frontend/package.json +++ b/libs/uniharness_demo/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "hexagent-demo-frontend", + "name": "uniharness-demo-frontend", "private": true, "version": "0.0.1", "type": "module", diff --git a/libs/hexagent_demo/frontend/public/favicon.png b/libs/uniharness_demo/frontend/public/favicon.png similarity index 100% rename from libs/hexagent_demo/frontend/public/favicon.png rename to libs/uniharness_demo/frontend/public/favicon.png diff --git a/libs/hexagent_demo/frontend/public/favicon.svg b/libs/uniharness_demo/frontend/public/favicon.svg similarity index 100% rename from libs/hexagent_demo/frontend/public/favicon.svg rename to libs/uniharness_demo/frontend/public/favicon.svg diff --git a/libs/hexagent_demo/frontend/public/vite.svg b/libs/uniharness_demo/frontend/public/vite.svg similarity index 100% rename from libs/hexagent_demo/frontend/public/vite.svg rename to libs/uniharness_demo/frontend/public/vite.svg diff --git a/libs/hexagent_demo/frontend/src/App.css b/libs/uniharness_demo/frontend/src/App.css similarity index 99% rename from libs/hexagent_demo/frontend/src/App.css rename to libs/uniharness_demo/frontend/src/App.css index cccd25df..5fe4becf 100644 --- a/libs/hexagent_demo/frontend/src/App.css +++ b/libs/uniharness_demo/frontend/src/App.css @@ -652,7 +652,7 @@ display: inline-block; } -/* Chat mode — phase 1: "HexAgent," centers, then phase 2: rest expands in */ +/* Chat mode — phase 1: "UniHarness," centers, then phase 2: rest expands in */ .wh-first { animation: chatFirstWord 600ms cubic-bezier(0.16, 1, 0.3, 1) both; } diff --git a/libs/hexagent_demo/frontend/src/App.tsx b/libs/uniharness_demo/frontend/src/App.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/App.tsx rename to libs/uniharness_demo/frontend/src/App.tsx diff --git a/libs/hexagent_demo/frontend/src/api.ts b/libs/uniharness_demo/frontend/src/api.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/api.ts rename to libs/uniharness_demo/frontend/src/api.ts diff --git a/libs/hexagent_demo/frontend/src/assets/brand-logo.png b/libs/uniharness_demo/frontend/src/assets/brand-logo.png similarity index 100% rename from libs/hexagent_demo/frontend/src/assets/brand-logo.png rename to libs/uniharness_demo/frontend/src/assets/brand-logo.png diff --git a/libs/hexagent_demo/frontend/src/assets/favicon.svg b/libs/uniharness_demo/frontend/src/assets/favicon.svg similarity index 100% rename from libs/hexagent_demo/frontend/src/assets/favicon.svg rename to libs/uniharness_demo/frontend/src/assets/favicon.svg diff --git a/libs/hexagent_demo/frontend/src/components/ChatArea.tsx b/libs/uniharness_demo/frontend/src/components/ChatArea.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/ChatArea.tsx rename to libs/uniharness_demo/frontend/src/components/ChatArea.tsx diff --git a/libs/hexagent_demo/frontend/src/components/ChatInput.tsx b/libs/uniharness_demo/frontend/src/components/ChatInput.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/ChatInput.tsx rename to libs/uniharness_demo/frontend/src/components/ChatInput.tsx diff --git a/libs/hexagent_demo/frontend/src/components/CodeBlock.tsx b/libs/uniharness_demo/frontend/src/components/CodeBlock.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/CodeBlock.tsx rename to libs/uniharness_demo/frontend/src/components/CodeBlock.tsx diff --git a/libs/hexagent_demo/frontend/src/components/DocxViewer.tsx b/libs/uniharness_demo/frontend/src/components/DocxViewer.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/DocxViewer.tsx rename to libs/uniharness_demo/frontend/src/components/DocxViewer.tsx diff --git a/libs/hexagent_demo/frontend/src/components/EChartsBlock.tsx b/libs/uniharness_demo/frontend/src/components/EChartsBlock.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/EChartsBlock.tsx rename to libs/uniharness_demo/frontend/src/components/EChartsBlock.tsx diff --git a/libs/hexagent_demo/frontend/src/components/FilePreview.tsx b/libs/uniharness_demo/frontend/src/components/FilePreview.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/FilePreview.tsx rename to libs/uniharness_demo/frontend/src/components/FilePreview.tsx diff --git a/libs/hexagent_demo/frontend/src/components/FolderPicker.tsx b/libs/uniharness_demo/frontend/src/components/FolderPicker.tsx similarity index 94% rename from libs/hexagent_demo/frontend/src/components/FolderPicker.tsx rename to libs/uniharness_demo/frontend/src/components/FolderPicker.tsx index 0a6c67f8..98520183 100644 --- a/libs/hexagent_demo/frontend/src/components/FolderPicker.tsx +++ b/libs/uniharness_demo/frontend/src/components/FolderPicker.tsx @@ -149,10 +149,10 @@ export default function FolderPicker({ value, onChange, disabled, onDisabledClic

- Allow HexAgent to access files in "{pendingFolder}"? + Allow UniHarness to access files in "{pendingFolder}"?

- This grants access to all files and subfolders. HexAgent will be able to read, edit, and delete files in this directory. File contents may be shared with connected AI models and tools. Avoid selecting folders containing sensitive or private data. + This grants access to all files and subfolders. UniHarness will be able to read, edit, and delete files in this directory. File contents may be shared with connected AI models and tools. Avoid selecting folders containing sensitive or private data.

- WSL runtime installation is complete, but Windows must restart before OpenAgent can continue. + WSL runtime installation is complete, but Windows must restart before UniHarness can continue.

Please restart your computer now, otherwise VM/Cowork features will not work. diff --git a/libs/hexagent_demo/frontend/src/components/RightPanel.tsx b/libs/uniharness_demo/frontend/src/components/RightPanel.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/RightPanel.tsx rename to libs/uniharness_demo/frontend/src/components/RightPanel.tsx diff --git a/libs/hexagent_demo/frontend/src/components/ScrollableText.tsx b/libs/uniharness_demo/frontend/src/components/ScrollableText.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/ScrollableText.tsx rename to libs/uniharness_demo/frontend/src/components/ScrollableText.tsx diff --git a/libs/hexagent_demo/frontend/src/components/SearchModal.tsx b/libs/uniharness_demo/frontend/src/components/SearchModal.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/SearchModal.tsx rename to libs/uniharness_demo/frontend/src/components/SearchModal.tsx diff --git a/libs/hexagent_demo/frontend/src/components/SettingsModal.tsx b/libs/uniharness_demo/frontend/src/components/SettingsModal.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/SettingsModal.tsx rename to libs/uniharness_demo/frontend/src/components/SettingsModal.tsx diff --git a/libs/hexagent_demo/frontend/src/components/Sidebar.tsx b/libs/uniharness_demo/frontend/src/components/Sidebar.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/Sidebar.tsx rename to libs/uniharness_demo/frontend/src/components/Sidebar.tsx diff --git a/libs/hexagent_demo/frontend/src/components/SubagentBlock.tsx b/libs/uniharness_demo/frontend/src/components/SubagentBlock.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/SubagentBlock.tsx rename to libs/uniharness_demo/frontend/src/components/SubagentBlock.tsx diff --git a/libs/hexagent_demo/frontend/src/components/ThinkingBlock.tsx b/libs/uniharness_demo/frontend/src/components/ThinkingBlock.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/ThinkingBlock.tsx rename to libs/uniharness_demo/frontend/src/components/ThinkingBlock.tsx diff --git a/libs/hexagent_demo/frontend/src/components/Toast.tsx b/libs/uniharness_demo/frontend/src/components/Toast.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/Toast.tsx rename to libs/uniharness_demo/frontend/src/components/Toast.tsx diff --git a/libs/hexagent_demo/frontend/src/components/ToolCallBlock.tsx b/libs/uniharness_demo/frontend/src/components/ToolCallBlock.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/ToolCallBlock.tsx rename to libs/uniharness_demo/frontend/src/components/ToolCallBlock.tsx diff --git a/libs/hexagent_demo/frontend/src/components/ToolIcon.tsx b/libs/uniharness_demo/frontend/src/components/ToolIcon.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/ToolIcon.tsx rename to libs/uniharness_demo/frontend/src/components/ToolIcon.tsx diff --git a/libs/hexagent_demo/frontend/src/components/VMSetupFloater.tsx b/libs/uniharness_demo/frontend/src/components/VMSetupFloater.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/VMSetupFloater.tsx rename to libs/uniharness_demo/frontend/src/components/VMSetupFloater.tsx diff --git a/libs/hexagent_demo/frontend/src/components/VizBlock.tsx b/libs/uniharness_demo/frontend/src/components/VizBlock.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/VizBlock.tsx rename to libs/uniharness_demo/frontend/src/components/VizBlock.tsx diff --git a/libs/hexagent_demo/frontend/src/components/VizModal.tsx b/libs/uniharness_demo/frontend/src/components/VizModal.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/VizModal.tsx rename to libs/uniharness_demo/frontend/src/components/VizModal.tsx diff --git a/libs/hexagent_demo/frontend/src/components/WelcomeScreen.tsx b/libs/uniharness_demo/frontend/src/components/WelcomeScreen.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/WelcomeScreen.tsx rename to libs/uniharness_demo/frontend/src/components/WelcomeScreen.tsx diff --git a/libs/hexagent_demo/frontend/src/components/XlsxViewer.tsx b/libs/uniharness_demo/frontend/src/components/XlsxViewer.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/components/XlsxViewer.tsx rename to libs/uniharness_demo/frontend/src/components/XlsxViewer.tsx diff --git a/libs/hexagent_demo/frontend/src/electron.d.ts b/libs/uniharness_demo/frontend/src/electron.d.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/electron.d.ts rename to libs/uniharness_demo/frontend/src/electron.d.ts diff --git a/libs/hexagent_demo/frontend/src/hooks/useFileDrop.ts b/libs/uniharness_demo/frontend/src/hooks/useFileDrop.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/hooks/useFileDrop.ts rename to libs/uniharness_demo/frontend/src/hooks/useFileDrop.ts diff --git a/libs/hexagent_demo/frontend/src/hooks/useSettings.ts b/libs/uniharness_demo/frontend/src/hooks/useSettings.ts similarity index 97% rename from libs/hexagent_demo/frontend/src/hooks/useSettings.ts rename to libs/uniharness_demo/frontend/src/hooks/useSettings.ts index f3c617a0..84224378 100644 --- a/libs/hexagent_demo/frontend/src/hooks/useSettings.ts +++ b/libs/uniharness_demo/frontend/src/hooks/useSettings.ts @@ -5,7 +5,7 @@ export interface Settings { theme: "light" | "dark" | "system"; } -const STORAGE_KEY = "hexagent-settings"; +const STORAGE_KEY = "uniharness-settings"; const DEFAULT_SETTINGS: Settings = { fullName: "", diff --git a/libs/hexagent_demo/frontend/src/hooks/useSyntaxTheme.ts b/libs/uniharness_demo/frontend/src/hooks/useSyntaxTheme.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/hooks/useSyntaxTheme.ts rename to libs/uniharness_demo/frontend/src/hooks/useSyntaxTheme.ts diff --git a/libs/hexagent_demo/frontend/src/hooks/useThemeMode.ts b/libs/uniharness_demo/frontend/src/hooks/useThemeMode.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/hooks/useThemeMode.ts rename to libs/uniharness_demo/frontend/src/hooks/useThemeMode.ts diff --git a/libs/hexagent_demo/frontend/src/index.css b/libs/uniharness_demo/frontend/src/index.css similarity index 100% rename from libs/hexagent_demo/frontend/src/index.css rename to libs/uniharness_demo/frontend/src/index.css diff --git a/libs/hexagent_demo/frontend/src/main.tsx b/libs/uniharness_demo/frontend/src/main.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/main.tsx rename to libs/uniharness_demo/frontend/src/main.tsx diff --git a/libs/hexagent_demo/frontend/src/recentFolders.ts b/libs/uniharness_demo/frontend/src/recentFolders.ts similarity index 96% rename from libs/hexagent_demo/frontend/src/recentFolders.ts rename to libs/uniharness_demo/frontend/src/recentFolders.ts index 2efd1543..df8b183a 100644 --- a/libs/hexagent_demo/frontend/src/recentFolders.ts +++ b/libs/uniharness_demo/frontend/src/recentFolders.ts @@ -6,7 +6,7 @@ export interface RecentFolder { alwaysAllowed: boolean; } -const STORAGE_KEY = "hexagent_recent_folders"; +const STORAGE_KEY = "uniharness_recent_folders"; export function loadRecentFolders(): RecentFolder[] { try { diff --git a/libs/hexagent_demo/frontend/src/store.ts b/libs/uniharness_demo/frontend/src/store.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/store.ts rename to libs/uniharness_demo/frontend/src/store.ts diff --git a/libs/hexagent_demo/frontend/src/tools/index.ts b/libs/uniharness_demo/frontend/src/tools/index.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/index.ts rename to libs/uniharness_demo/frontend/src/tools/index.ts diff --git a/libs/hexagent_demo/frontend/src/tools/parse.ts b/libs/uniharness_demo/frontend/src/tools/parse.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/parse.ts rename to libs/uniharness_demo/frontend/src/tools/parse.ts diff --git a/libs/hexagent_demo/frontend/src/tools/registry.ts b/libs/uniharness_demo/frontend/src/tools/registry.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/registry.ts rename to libs/uniharness_demo/frontend/src/tools/registry.ts diff --git a/libs/hexagent_demo/frontend/src/tools/renderers/PresentFilesResult.tsx b/libs/uniharness_demo/frontend/src/tools/renderers/PresentFilesResult.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/renderers/PresentFilesResult.tsx rename to libs/uniharness_demo/frontend/src/tools/renderers/PresentFilesResult.tsx diff --git a/libs/hexagent_demo/frontend/src/tools/renderers/TodoProgress.tsx b/libs/uniharness_demo/frontend/src/tools/renderers/TodoProgress.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/renderers/TodoProgress.tsx rename to libs/uniharness_demo/frontend/src/tools/renderers/TodoProgress.tsx diff --git a/libs/hexagent_demo/frontend/src/tools/renderers/WebSearchResult.tsx b/libs/uniharness_demo/frontend/src/tools/renderers/WebSearchResult.tsx similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/renderers/WebSearchResult.tsx rename to libs/uniharness_demo/frontend/src/tools/renderers/WebSearchResult.tsx diff --git a/libs/hexagent_demo/frontend/src/tools/types.ts b/libs/uniharness_demo/frontend/src/tools/types.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/types.ts rename to libs/uniharness_demo/frontend/src/tools/types.ts diff --git a/libs/hexagent_demo/frontend/src/tools/useFavicon.ts b/libs/uniharness_demo/frontend/src/tools/useFavicon.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/tools/useFavicon.ts rename to libs/uniharness_demo/frontend/src/tools/useFavicon.ts diff --git a/libs/hexagent_demo/frontend/src/types.ts b/libs/uniharness_demo/frontend/src/types.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/types.ts rename to libs/uniharness_demo/frontend/src/types.ts diff --git a/libs/hexagent_demo/frontend/src/vite-env.d.ts b/libs/uniharness_demo/frontend/src/vite-env.d.ts similarity index 100% rename from libs/hexagent_demo/frontend/src/vite-env.d.ts rename to libs/uniharness_demo/frontend/src/vite-env.d.ts diff --git a/libs/hexagent_demo/frontend/src/vmSetup.tsx b/libs/uniharness_demo/frontend/src/vmSetup.tsx similarity index 99% rename from libs/hexagent_demo/frontend/src/vmSetup.tsx rename to libs/uniharness_demo/frontend/src/vmSetup.tsx index 4b31321d..cf6c8cf8 100644 --- a/libs/hexagent_demo/frontend/src/vmSetup.tsx +++ b/libs/uniharness_demo/frontend/src/vmSetup.tsx @@ -280,7 +280,7 @@ export function VMSetupProvider({ children }: { children: ReactNode }) { return; } if (!pre.ok && autoFixable) { - notify("Windows features are not enabled yet. OpenAgent will try to enable them with admin permission.", "info"); + notify("Windows features are not enabled yet. UniHarness will try to enable them with admin permission.", "info"); } if (pre.rebootPending) { const msg = "Windows restart is pending. Please restart first, then continue VM setup."; diff --git a/libs/hexagent_demo/frontend/tsconfig.json b/libs/uniharness_demo/frontend/tsconfig.json similarity index 100% rename from libs/hexagent_demo/frontend/tsconfig.json rename to libs/uniharness_demo/frontend/tsconfig.json diff --git a/libs/hexagent_demo/frontend/vite.config.ts b/libs/uniharness_demo/frontend/vite.config.ts similarity index 100% rename from libs/hexagent_demo/frontend/vite.config.ts rename to libs/uniharness_demo/frontend/vite.config.ts diff --git a/libs/hexagent_demo/start-dev.ps1 b/libs/uniharness_demo/start-dev.ps1 similarity index 92% rename from libs/hexagent_demo/start-dev.ps1 rename to libs/uniharness_demo/start-dev.ps1 index 29d34f8b..dca25bbc 100644 --- a/libs/hexagent_demo/start-dev.ps1 +++ b/libs/uniharness_demo/start-dev.ps1 @@ -34,7 +34,7 @@ if (-not (Test-Path '.venv')) { uv sync } Write-Host '[backend] starting on http://127.0.0.1:8000' -ForegroundColor Cyan -uv run uvicorn hexagent_api.main:app --host 127.0.0.1 --port 8000 +uv run uvicorn uniharness_api.main:app --host 127.0.0.1 --port 8000 "@ $frontendCmd = @" @@ -49,7 +49,7 @@ npm run dev if ($CurrentWindow) { Write-Host "Starting backend in a background job (CurrentWindow mode)..." -ForegroundColor Green - Start-Job -Name "hexagent-backend" -ScriptBlock { + Start-Job -Name "uniharness-backend" -ScriptBlock { param($cmd) powershell -NoProfile -NoExit -Command $cmd } -ArgumentList $backendCmd | Out-Null @@ -64,7 +64,7 @@ Start-Process powershell -ArgumentList "-NoProfile", "-NoExit", "-ExecutionPolic Start-Process powershell -ArgumentList "-NoProfile", "-NoExit", "-ExecutionPolicy", "Bypass", "-Command", $frontendCmd | Out-Null Write-Host "" -Write-Host "HexAgent dev services launched." -ForegroundColor Green +Write-Host "UniHarness dev services launched." -ForegroundColor Green Write-Host "Frontend: http://localhost:3000" Write-Host "Backend : http://127.0.0.1:8000/health" Write-Host ""