docs: add repo docs and CI scaffolding
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
name: Bug report
|
||||
description: Report a reproducible problem in OpenHarness
|
||||
title: "[Bug]: "
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for reporting a bug. Please include concrete steps, environment details, and error output.
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Describe the bug and the behavior you expected.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Include commands, prompts, or config that reliably reproduces the issue.
|
||||
placeholder: |
|
||||
1. Run `uv run oh ...`
|
||||
2. Trigger ...
|
||||
3. Observe ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: OS, Python version, Node version if relevant, provider/base URL, and install method.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant logs or screenshots
|
||||
description: Paste error output, stack traces, or terminal screenshots.
|
||||
render: shell
|
||||
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Contribution guide
|
||||
url: https://github.com/HKUDS/OpenHarness/blob/main/CONTRIBUTING.md
|
||||
about: Read local setup, validation, and PR expectations before contributing.
|
||||
- name: Showcase ideas
|
||||
url: https://github.com/HKUDS/OpenHarness/blob/main/docs/SHOWCASE.md
|
||||
about: See example workflows and suggest new real-world use cases.
|
||||
@@ -0,0 +1,33 @@
|
||||
name: Feature request
|
||||
description: Propose a focused improvement or missing workflow
|
||||
title: "[Feature]: "
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please describe the workflow gap as concretely as possible. Small, scoped requests are easier to prioritize.
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: What workflow is missing or painful today?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: proposal
|
||||
attributes:
|
||||
label: Proposed change
|
||||
description: Explain the behavior you want and any relevant CLI, UI, or provider details.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives considered
|
||||
description: If you have a workaround or competing approach, include it here.
|
||||
- type: textarea
|
||||
id: extra
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Links to related issues, code references, or benchmarks.
|
||||
@@ -0,0 +1,15 @@
|
||||
## Summary
|
||||
|
||||
- What problem does this PR solve?
|
||||
- What changed?
|
||||
|
||||
## Validation
|
||||
|
||||
- [ ] `uv run ruff check src tests scripts`
|
||||
- [ ] `uv run pytest -q`
|
||||
- [ ] `cd frontend/terminal && npx tsc --noEmit` (if frontend touched)
|
||||
|
||||
## Notes
|
||||
|
||||
- Related issue:
|
||||
- Follow-up work:
|
||||
@@ -0,0 +1,83 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
python-tests:
|
||||
name: Python tests (${{ matrix.python-version }})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --frozen --extra dev
|
||||
|
||||
- name: Run test suite
|
||||
run: uv run pytest -q
|
||||
|
||||
python-quality:
|
||||
name: Python quality
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --frozen --extra dev
|
||||
|
||||
- name: Ruff
|
||||
run: uv run ruff check src tests scripts
|
||||
|
||||
frontend-typecheck:
|
||||
name: Frontend typecheck
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: frontend/terminal
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/terminal/package-lock.json
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: TypeScript check
|
||||
run: npx tsc --noEmit
|
||||
@@ -0,0 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to OpenHarness should be recorded in this file.
|
||||
|
||||
The format is based on Keep a Changelog, and this project currently tracks changes in a lightweight, repository-oriented way.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- GitHub Actions CI workflow for Python linting, tests, and frontend TypeScript checks.
|
||||
- `CONTRIBUTING.md` with local setup, validation commands, and PR expectations.
|
||||
- `docs/SHOWCASE.md` with concrete OpenHarness usage patterns and demo commands.
|
||||
- GitHub issue templates and a pull request template.
|
||||
|
||||
### Changed
|
||||
|
||||
- README now links to contribution docs, changelog, showcase material, and provider compatibility guidance.
|
||||
- README quick start now includes a one-command demo and clearer provider compatibility notes.
|
||||
|
||||
## [0.1.0] - 2026-04-01
|
||||
|
||||
### Added
|
||||
|
||||
- Initial public release of OpenHarness.
|
||||
- Core agent loop, tool registry, permission system, hooks, skills, plugins, MCP support, and terminal UI.
|
||||
@@ -0,0 +1,68 @@
|
||||
# Contributing to OpenHarness
|
||||
|
||||
OpenHarness is an open-source agent harness focused on clarity, hackability, and compatibility with Claude-style workflows.
|
||||
|
||||
## Ways to contribute
|
||||
|
||||
- Fix bugs or tighten edge-case handling in the harness runtime.
|
||||
- Improve docs, onboarding, examples, and architecture notes.
|
||||
- Add tests for tools, permissions, plugins, MCP, or multi-agent flows.
|
||||
- Contribute new skills, plugins, or provider compatibility improvements.
|
||||
- Share real usage patterns that can be added to [`docs/SHOWCASE.md`](docs/SHOWCASE.md).
|
||||
|
||||
## Development setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/HKUDS/OpenHarness.git
|
||||
cd OpenHarness
|
||||
uv sync --extra dev
|
||||
```
|
||||
|
||||
If you want to work on the React terminal UI as well:
|
||||
|
||||
```bash
|
||||
cd frontend/terminal
|
||||
npm ci
|
||||
cd ../..
|
||||
```
|
||||
|
||||
## Local checks
|
||||
|
||||
Run the same core checks that CI runs before opening a PR:
|
||||
|
||||
```bash
|
||||
uv run ruff check src tests scripts
|
||||
uv run pytest -q
|
||||
```
|
||||
|
||||
Frontend sanity check:
|
||||
|
||||
```bash
|
||||
cd frontend/terminal
|
||||
npx tsc --noEmit
|
||||
```
|
||||
|
||||
## Pull request expectations
|
||||
|
||||
- Keep PRs scoped. Small, reviewable changes merge faster than broad rewrites.
|
||||
- Include the problem, the change, and how you verified it.
|
||||
- Add or update tests when behavior changes.
|
||||
- Update docs when CLI flags, workflows, or compatibility claims change.
|
||||
- Add a short entry under `Unreleased` in [`CHANGELOG.md`](CHANGELOG.md) for user-visible changes.
|
||||
- If you are improving type coverage, feel free to run `uv run mypy src/openharness`, but it is not yet a required green check for the whole repo.
|
||||
|
||||
## Documentation and community contributions
|
||||
|
||||
Issue [#7](https://github.com/HKUDS/OpenHarness/issues/7) surfaced several high-value docs needs. Useful contributions in that area include:
|
||||
|
||||
- README accuracy improvements and compatibility notes.
|
||||
- Short, reproducible examples for common workflows.
|
||||
- Showcase entries based on real usage rather than generic marketing claims.
|
||||
- Contribution and maintenance docs that make the repo easier to navigate.
|
||||
|
||||
## Reporting bugs and proposing features
|
||||
|
||||
- Use the GitHub issue templates when possible.
|
||||
- Include environment details, exact commands, and error output for bugs.
|
||||
- For features, explain the concrete workflow gap and expected behavior.
|
||||
- If the request is mostly documentation or maintenance related, say that explicitly so it can be scoped as a docs PR.
|
||||
@@ -13,11 +13,12 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/python-≥3.11-blue?logo=python&logoColor=white" alt="Python">
|
||||
<img src="https://img.shields.io/badge/python-≥3.10-blue?logo=python&logoColor=white" alt="Python">
|
||||
<img src="https://img.shields.io/badge/React+Ink-TUI-61DAFB?logo=react&logoColor=white" alt="React">
|
||||
<img src="https://img.shields.io/badge/pytest-114_pass-brightgreen" alt="Pytest">
|
||||
<img src="https://img.shields.io/badge/E2E-6_suites-orange" alt="E2E">
|
||||
<img src="https://img.shields.io/badge/output-text_|_json_|_stream--json-blueviolet" alt="Output">
|
||||
<a href="https://github.com/HKUDS/OpenHarness/actions/workflows/ci.yml"><img src="https://github.com/HKUDS/OpenHarness/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
||||
<a href="https://github.com/HKUDS/.github/blob/main/profile/README.md"><img src="https://img.shields.io/badge/Feishu-Group-E9DBFC?style=flat&logo=feishu&logoColor=white" alt="Feishu"></a>
|
||||
<a href="https://github.com/HKUDS/.github/blob/main/profile/README.md"><img src="https://img.shields.io/badge/WeChat-Group-C5EAB4?style=flat&logo=wechat&logoColor=white" alt="WeChat"></a>
|
||||
</p>
|
||||
@@ -35,7 +36,6 @@ Supports CLI agent integration including OpenClaw, nanobot, Cursor, and more.
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## ✨ OpenHarness's Key Harness Features
|
||||
|
||||
<table align="center" width="100%">
|
||||
@@ -164,16 +164,31 @@ OpenHarness is an open-source Python implementation designed for **researchers,
|
||||
|
||||
- **2026-04-01** 🎨 **v0.1.0** — Initial **OpenHarness** open-source release featuring complete Harness architecture:
|
||||
|
||||
<p align="center">
|
||||
<strong>Start here:</strong>
|
||||
<a href="#-quick-start">Quick Start</a> ·
|
||||
<a href="#-provider-compatibility">Provider Compatibility</a> ·
|
||||
<a href="docs/SHOWCASE.md">Showcase</a> ·
|
||||
<a href="CONTRIBUTING.md">Contributing</a> ·
|
||||
<a href="CHANGELOG.md">Changelog</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Python 3.11+** and [uv](https://docs.astral.sh/uv/)
|
||||
- **Node.js 18+** (for the React terminal UI)
|
||||
- **Python 3.10+** and [uv](https://docs.astral.sh/uv/)
|
||||
- **Node.js 18+** (optional, for the React terminal UI)
|
||||
- An LLM API key
|
||||
|
||||
### One-Command Demo
|
||||
|
||||
```bash
|
||||
ANTHROPIC_API_KEY=your_key uv run oh -p "Inspect this repository and list the top 3 refactors"
|
||||
```
|
||||
|
||||
### Install & Run
|
||||
|
||||
```bash
|
||||
@@ -209,6 +224,20 @@ oh -p "List all functions in main.py" --output-format json
|
||||
oh -p "Fix the bug" --output-format stream-json
|
||||
```
|
||||
|
||||
## 🔌 Provider Compatibility
|
||||
|
||||
OpenHarness currently detects and adapts to a small set of provider profiles in code. The table below is intentionally conservative and reflects the profiles implemented in `src/openharness/api/provider.py`.
|
||||
|
||||
| Provider profile | Detection signal | Auth kind | Voice mode | Notes |
|
||||
|------------------|------------------|-----------|------------|-------|
|
||||
| **Anthropic** | Default when no custom `ANTHROPIC_BASE_URL` is set | API key | Not wired in current build | Default Claude-oriented setup |
|
||||
| **Moonshot / Kimi** | `ANTHROPIC_BASE_URL` contains `moonshot` or model starts with `kimi` | API key | Not wired in current build | Works through an Anthropic-compatible endpoint |
|
||||
| **Vertex-compatible** | Base URL contains `vertex` or `aiplatform` | GCP | Not wired in current build | Good fit for Anthropic-style gateways on Vertex |
|
||||
| **Bedrock-compatible** | Base URL contains `bedrock` | AWS | Not wired in current build | Intended for Bedrock-style deployments |
|
||||
| **Generic Anthropic-compatible** | Any other explicit `ANTHROPIC_BASE_URL` | API key | Not wired in current build | Useful for proxies and internal gateways |
|
||||
|
||||
If you are evaluating cross-provider workflows or want a concrete demo path, start with Anthropic or the Kimi example above, then compare behavior against your own compatible endpoint.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Harness Architecture
|
||||
@@ -254,6 +283,20 @@ while True:
|
||||
|
||||
The model decides **what** to do. The harness handles **how** — safely, efficiently, with full observability.
|
||||
|
||||
### Harness Flow
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
U[User Prompt] --> C[CLI or React TUI]
|
||||
C --> R[RuntimeBundle]
|
||||
R --> Q[QueryEngine]
|
||||
Q --> A[Anthropic-compatible API Client]
|
||||
A -->|tool_use| T[Tool Registry]
|
||||
T --> P[Permissions + Hooks]
|
||||
P --> X[Files Shell Web MCP Tasks]
|
||||
X --> Q
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✨ Features
|
||||
@@ -317,6 +360,16 @@ oh plugin install <source>
|
||||
oh plugin enable <name>
|
||||
```
|
||||
|
||||
### 🤝 Ecosystem Workflows
|
||||
|
||||
OpenHarness is useful as a lightweight harness layer around Claude-style tooling conventions:
|
||||
|
||||
- **OpenClaw-oriented workflows** can reuse Markdown-first knowledge and command-driven collaboration patterns.
|
||||
- **Claude-style plugins and skills** stay portable because OpenHarness keeps those formats familiar.
|
||||
- **ClawTeam-style multi-agent work** maps well onto the built-in team, task, and background execution primitives.
|
||||
|
||||
For concrete usage ideas instead of generic claims, see [`docs/SHOWCASE.md`](docs/SHOWCASE.md).
|
||||
|
||||
### 🛡️ Permissions
|
||||
|
||||
Multi-level safety with fine-grained control:
|
||||
@@ -443,6 +496,20 @@ Add commands in `commands/*.md`, hooks in `hooks/hooks.json`, agents in `agents/
|
||||
|
||||
---
|
||||
|
||||
## 🌍 Showcase
|
||||
|
||||
OpenHarness is most useful when treated as a small, inspectable harness you can adapt to a real workflow:
|
||||
|
||||
- **Repo coding assistant** for reading code, patching files, and running checks locally.
|
||||
- **Headless scripting tool** for `json` and `stream-json` output in automation flows.
|
||||
- **Plugin and skill testbed** for experimenting with Claude-style extensions.
|
||||
- **Multi-agent prototype harness** for task delegation and background execution.
|
||||
- **Provider comparison sandbox** across Anthropic-compatible backends.
|
||||
|
||||
See [`docs/SHOWCASE.md`](docs/SHOWCASE.md) for short, reproducible examples.
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
OpenHarness is a **community-driven research project**. We welcome contributions in:
|
||||
@@ -460,11 +527,17 @@ OpenHarness is a **community-driven research project**. We welcome contributions
|
||||
```bash
|
||||
# Development setup
|
||||
git clone https://github.com/HKUDS/OpenHarness.git
|
||||
cd openharness
|
||||
cd OpenHarness
|
||||
uv sync --extra dev
|
||||
uv run pytest -q # Verify everything works
|
||||
```
|
||||
|
||||
Useful contributor entry points:
|
||||
|
||||
- [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup, checks, and PR expectations
|
||||
- [`CHANGELOG.md`](CHANGELOG.md) for user-visible changes
|
||||
- [`docs/SHOWCASE.md`](docs/SHOWCASE.md) for real-world usage patterns worth documenting
|
||||
|
||||
---
|
||||
|
||||
## 📄 License
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# OpenHarness Showcase
|
||||
|
||||
This page collects concrete ways to use OpenHarness without overselling the project. Each example is intended to be small, reproducible, and easy to extend.
|
||||
|
||||
## 1. Repository-aware coding assistant
|
||||
|
||||
Use OpenHarness as a lightweight local coding agent for reading code, making edits, and running validation commands.
|
||||
|
||||
```bash
|
||||
uv run oh
|
||||
```
|
||||
|
||||
Example prompt:
|
||||
|
||||
```text
|
||||
Review this repo, identify the highest-risk bug, patch it, and run the relevant tests.
|
||||
```
|
||||
|
||||
## 2. Headless automation for scripts and CI
|
||||
|
||||
The print mode is useful when you want structured output in shell pipelines or automation jobs.
|
||||
|
||||
```bash
|
||||
uv run oh -p "Summarize the purpose of this repository" --output-format json
|
||||
uv run oh -p "List files that define the permission system" --output-format stream-json
|
||||
```
|
||||
|
||||
## 3. Skill and plugin playground
|
||||
|
||||
OpenHarness can load Markdown skills and Claude-style plugin layouts, which makes it useful for experimentation with custom workflows.
|
||||
|
||||
Examples:
|
||||
|
||||
- Put a custom skill in `~/.openharness/skills/`.
|
||||
- Install a plugin into `~/.openharness/plugins/`.
|
||||
- Use the same workflow conventions across multiple local projects.
|
||||
|
||||
## 4. Multi-agent and background task experiments
|
||||
|
||||
The repo includes team coordination primitives, background task management, and task inspection tools.
|
||||
|
||||
Example prompts:
|
||||
|
||||
```text
|
||||
Spawn a worker to audit the test suite while you inspect the CLI command registry.
|
||||
```
|
||||
|
||||
```text
|
||||
Create a background task that runs the slow integration script and report back when it finishes.
|
||||
```
|
||||
|
||||
## 5. Provider compatibility testbed
|
||||
|
||||
OpenHarness is useful when you need to compare Anthropic-compatible backends behind one harness.
|
||||
|
||||
Typical scenarios:
|
||||
|
||||
- Default Anthropic setup.
|
||||
- Moonshot/Kimi through an Anthropic-compatible endpoint.
|
||||
- Vertex-compatible and Bedrock-compatible gateways.
|
||||
- Internal proxies that expose an Anthropic-style API surface.
|
||||
|
||||
See the provider compatibility table in [`README.md`](../README.md#-provider-compatibility).
|
||||
|
||||
## 6. Documentation-first onboarding
|
||||
|
||||
If you are evaluating the project rather than contributing code, start here:
|
||||
|
||||
- [`README.md`](../README.md) for install, usage, and architecture.
|
||||
- [`CONTRIBUTING.md`](../CONTRIBUTING.md) for contributor workflow.
|
||||
- [`CHANGELOG.md`](../CHANGELOG.md) for visible repo changes.
|
||||
|
||||
## How to contribute a showcase entry
|
||||
|
||||
Good showcase additions are:
|
||||
|
||||
- Based on a real workflow you ran.
|
||||
- Short enough to reproduce locally.
|
||||
- Honest about prerequisites and limitations.
|
||||
- Focused on what OpenHarness makes easier, not on generic LLM claims.
|
||||
@@ -7,7 +7,6 @@ import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
# Colors for output
|
||||
|
||||
@@ -10,7 +10,6 @@ import asyncio
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
||||
@@ -43,7 +42,7 @@ def _run_oh(*args: str, timeout: int = 90) -> subprocess.CompletedProcess:
|
||||
|
||||
async def test_api_retry_config() -> tuple[bool, str]:
|
||||
"""Test that retry configuration is properly set up."""
|
||||
from openharness.api.client import MAX_RETRIES, RETRYABLE_STATUS_CODES, _is_retryable, _get_retry_delay
|
||||
from openharness.api.client import MAX_RETRIES, RETRYABLE_STATUS_CODES, _get_retry_delay
|
||||
|
||||
if MAX_RETRIES != 3:
|
||||
return False, f"Expected MAX_RETRIES=3, got {MAX_RETRIES}"
|
||||
|
||||
@@ -119,7 +119,6 @@ async def test_real_model_headless() -> tuple[bool, str]:
|
||||
if not settings["api_key"]:
|
||||
return False, "ANTHROPIC_AUTH_TOKEN not set"
|
||||
|
||||
from openharness.api.client import AnthropicApiClient
|
||||
from openharness.ui.app import run_print_mode
|
||||
|
||||
try:
|
||||
|
||||
@@ -10,7 +10,6 @@ from __future__ import annotations
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
GREEN = "\033[92m"
|
||||
|
||||
@@ -12,7 +12,6 @@ import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
||||
|
||||
@@ -55,8 +55,6 @@ def test_command_picker_shows() -> tuple[bool, str]:
|
||||
try:
|
||||
child.expect(pexpect.EOF, timeout=25)
|
||||
output = child.before or ""
|
||||
# Check for key UI elements
|
||||
has_shortcuts = "send" in output.lower() or "enter" in output.lower()
|
||||
has_welcome = "Oh my Harness!" in output
|
||||
if has_welcome:
|
||||
return True, f"TUI launched with welcome banner and shortcuts. Output: {len(output)} chars"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
"""API client exports."""
|
||||
"""API exports."""
|
||||
|
||||
from openharness.api.provider import ProviderInfo, auth_status, detect_provider
|
||||
|
||||
__all__ = ["ProviderInfo", "auth_status", "detect_provider"]
|
||||
from openharness.api.client import AnthropicApiClient
|
||||
from openharness.api.errors import OpenHarnessApiError
|
||||
from openharness.api.provider import ProviderInfo, auth_status, detect_provider
|
||||
from openharness.api.usage import UsageSnapshot
|
||||
|
||||
__all__ = ["AnthropicApiClient", "OpenHarnessApiError", "UsageSnapshot"]
|
||||
__all__ = [
|
||||
"AnthropicApiClient",
|
||||
"OpenHarnessApiError",
|
||||
"ProviderInfo",
|
||||
"UsageSnapshot",
|
||||
"auth_status",
|
||||
"detect_provider",
|
||||
]
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from typing import Any
|
||||
import httpx
|
||||
|
||||
from openharness.api.client import ApiMessageCompleteEvent, ApiMessageRequest, SupportsStreamingMessages
|
||||
from openharness.engine.messages import ConversationMessage, TextBlock
|
||||
from openharness.engine.messages import ConversationMessage
|
||||
from openharness.hooks.events import HookEvent
|
||||
from openharness.hooks.loader import HookRegistry
|
||||
from openharness.hooks.schemas import (
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import fnmatch
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
from dataclasses import dataclass
|
||||
|
||||
from openharness.config.settings import PermissionSettings
|
||||
from openharness.permissions.modes import PermissionMode
|
||||
|
||||
@@ -5,7 +5,6 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
from openharness.hooks.schemas import HookDefinition
|
||||
from openharness.mcp.types import McpServerConfig
|
||||
from openharness.plugins.schemas import PluginManifest
|
||||
from openharness.skills.types import SkillDefinition
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from openharness.config.paths import get_cron_registry_path
|
||||
|
||||
@@ -8,7 +8,6 @@ import shlex
|
||||
import time
|
||||
from dataclasses import replace
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from uuid import uuid4
|
||||
|
||||
from openharness.config.paths import get_tasks_dir
|
||||
|
||||
@@ -8,7 +8,6 @@ import json
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from uuid import uuid4
|
||||
|
||||
from openharness.api.client import SupportsStreamingMessages
|
||||
|
||||
@@ -6,7 +6,6 @@ from rich.console import Console
|
||||
from rich.markdown import Markdown
|
||||
from rich.panel import Panel
|
||||
from rich.syntax import Syntax
|
||||
from rich.text import Text
|
||||
|
||||
from openharness.engine.stream_events import (
|
||||
AssistantTextDelta,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from openharness.coordinator import get_team_registry
|
||||
from openharness.coordinator.coordinator_mode import TeamRegistry
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ from openharness.api.usage import UsageSnapshot
|
||||
from openharness.engine.messages import ConversationMessage, TextBlock
|
||||
from openharness.services.session_storage import (
|
||||
export_session_markdown,
|
||||
get_project_session_dir,
|
||||
load_session_snapshot,
|
||||
save_session_snapshot,
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from openharness.tasks import get_task_manager
|
||||
from openharness.tasks.manager import BackgroundTaskManager
|
||||
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ async def test_agent_send_message_flow_restarts_completed_agent(tmp_path: Path,
|
||||
)
|
||||
task_id = create_result.output.split()[-1]
|
||||
|
||||
for _ in range(40):
|
||||
for _ in range(80):
|
||||
output = await task_output.execute(task_output.input_model(task_id=task_id), context)
|
||||
if "AGENT_ECHO:ready" in output.output:
|
||||
break
|
||||
@@ -160,8 +160,8 @@ async def test_agent_send_message_flow_restarts_completed_agent(tmp_path: Path,
|
||||
)
|
||||
assert send_result.is_error is False
|
||||
|
||||
await asyncio.sleep(0.1)
|
||||
for _ in range(40):
|
||||
await asyncio.sleep(0.2)
|
||||
for _ in range(80):
|
||||
output = await task_output.execute(task_output.input_model(task_id=task_id), context)
|
||||
if "AGENT_ECHO:agent ping" in output.output:
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user