Spaces:
Running
Running
Sync runtime dotenv loading
Browse files- README.md +69 -33
- agent_base/react_agent.py +2 -3
- agent_base/utils.py +9 -0
- frontend/local_server.py +2 -2
README.md
CHANGED
|
@@ -38,29 +38,80 @@ Maintenance rule:
|
|
| 38 |
it is genuinely general-purpose.
|
| 39 |
- Public documentation should be updated in the main repo, not duplicated here.
|
| 40 |
|
| 41 |
-
##
|
| 42 |
|
| 43 |
-
|
| 44 |
-
|
|
|
|
| 45 |
|
| 46 |
-
|
| 47 |
-
compatibility, trace/session state, image handling, compaction logic, and
|
| 48 |
-
imported runtime helpers required by that core.
|
| 49 |
-
- `agent_base/tools/`: hosted-safe tool implementations used by the frontend.
|
| 50 |
-
- `frontend/static/`: shared browser UI assets, styles, and client logic.
|
| 51 |
-
- `frontend/local_server.py`: WebSocket streaming frontend server base, with
|
| 52 |
-
Space-specific managed-workspace behavior preserved.
|
| 53 |
-
- `requirements.txt`: Python runtime dependencies needed by the hosted app.
|
| 54 |
|
| 55 |
-
|
| 56 |
-
Space-specific
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
-
- `app.py` is the Hugging Face entrypoint and owns Space startup, cleanup, and
|
| 63 |
-
trajectory collection configuration.
|
| 64 |
- Users cannot select arbitrary server folders. Each new chat gets an isolated
|
| 65 |
managed run directory under `RH_SPACE_RUNS_DIR`.
|
| 66 |
- The runtime layout is always:
|
|
@@ -81,21 +132,6 @@ These behaviors are intentional Space-only deltas:
|
|
| 81 |
- Old inactive runs are cleaned periodically so the Space does not grow without
|
| 82 |
bound.
|
| 83 |
|
| 84 |
-
## Intentionally Removed From The Space
|
| 85 |
-
|
| 86 |
-
The Space intentionally does not keep the full main-repo surface area:
|
| 87 |
-
|
| 88 |
-
- `run_agent.py`, `run_server.py`, `run_frontend.py`
|
| 89 |
-
- OpenAI-compatible API server code under `api/`
|
| 90 |
-
- benchmark adapters and benchmark documentation under `benchmarks/`
|
| 91 |
-
- long-form tutorials under `docs/`
|
| 92 |
-
- local placeholder directories such as `workspace/`, `api_runs/`, and `traces/`
|
| 93 |
-
- test fixtures and local test suites
|
| 94 |
-
- `.env.example`
|
| 95 |
-
|
| 96 |
-
Removing these files keeps the deployed app small and avoids stale code or
|
| 97 |
-
misleading documentation drifting away from the main repository.
|
| 98 |
-
|
| 99 |
## Required Secrets
|
| 100 |
|
| 101 |
Configure these as Hugging Face Space secrets before starting the app:
|
|
|
|
| 38 |
it is genuinely general-purpose.
|
| 39 |
- Public documentation should be updated in the main repo, not duplicated here.
|
| 40 |
|
| 41 |
+
## Sync Policy
|
| 42 |
|
| 43 |
+
The Space should stay small and deployment-focused. When the main repository
|
| 44 |
+
changes, sync only the files needed by the hosted browser app, then inspect the
|
| 45 |
+
diff manually. Do not copy the whole main repository into this Space.
|
| 46 |
|
| 47 |
+
### Fully Synced From The Main Repository
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
+
These files/directories should normally match the main repo exactly, unless a
|
| 50 |
+
future Space-specific need is documented here:
|
| 51 |
|
| 52 |
+
| Path | Purpose |
|
| 53 |
+
| --- | --- |
|
| 54 |
+
| `agent_base/base.py` | Base agent interface. |
|
| 55 |
+
| `agent_base/console_utils.py` | Shared console/event formatting helpers. |
|
| 56 |
+
| `agent_base/context_compact.py` | Context compaction logic. |
|
| 57 |
+
| `agent_base/model_profiles.py` | Provider/model profile helpers. |
|
| 58 |
+
| `agent_base/prompt.py` | Base system prompt. |
|
| 59 |
+
| `agent_base/prompts/system_base.md` | Shared base prompt text. |
|
| 60 |
+
| `agent_base/provider_compat.py` | Provider compatibility normalization. |
|
| 61 |
+
| `agent_base/session_state.py` | Session state serialization. |
|
| 62 |
+
| `agent_base/tools/*.py` | Tool implementations exposed by the Space app. |
|
| 63 |
+
| `agent_base/trace_utils.py` | Trace writing utilities. |
|
| 64 |
+
| `agent_base/utils.py` | Shared runtime utilities, including default `.env` loading. |
|
| 65 |
+
| `VERSION` | Version marker shown by the app/runtime when needed. |
|
| 66 |
+
|
| 67 |
+
### Partially Synced And Space-Modified
|
| 68 |
+
|
| 69 |
+
These files are related to main-repo files, but must be merged manually because
|
| 70 |
+
the hosted Space has different deployment semantics:
|
| 71 |
+
|
| 72 |
+
| Path | Maintenance rule |
|
| 73 |
+
| --- | --- |
|
| 74 |
+
| `agent_base/react_agent.py` | Keep core ReAct/runtime behavior aligned with main. Preserve Space compatibility only when it is genuinely required by the hosted app. |
|
| 75 |
+
| `frontend/local_server.py` | Based on the main local frontend server, but Space-modified for managed temporary workspaces, forced `agent_workspace/` + `agent_trace/` layout, workspace zip download, automatic cleanup, trajectory collection hooks, and no arbitrary server-folder picker semantics. Never overwrite this file blindly from main. |
|
| 76 |
+
| `frontend/static/index.html` | Starts from the main frontend HTML, but removes the local workspace picker and adds hosted workspace download UI. |
|
| 77 |
+
| `frontend/static/app.js` | Starts from the main frontend client, but removes local folder selection and adds download-token / workspace-zip handling. |
|
| 78 |
+
| `frontend/static/app.css` | Starts from the main frontend CSS, but includes Space-only hosted workspace/download styling and omits local folder picker modal styles. |
|
| 79 |
+
| `requirements.txt` | Starts from the main runtime dependencies, but keeps Space-only hosted dependencies such as `huggingface_hub` and `uvicorn[standard]`. |
|
| 80 |
+
| `app.py` | Space-only FastAPI/Hugging Face entrypoint. It owns startup, cleanup scheduling, static mounting, and hosted defaults. |
|
| 81 |
+
| `check_space_runtime.py` | Space-only smoke test for deployment import/runtime sanity. |
|
| 82 |
+
| `Dockerfile` | Space-only Docker build. |
|
| 83 |
+
| `.dockerignore` | Space-only Docker context pruning. |
|
| 84 |
+
| `.gitattributes` | Space repository metadata. |
|
| 85 |
+
| `.gitignore` | Space-only generated files, cache, and temporary run ignores. |
|
| 86 |
+
| `README.md` | Space maintenance notes only. Public project docs belong in the main repo. |
|
| 87 |
+
|
| 88 |
+
### Out Of Scope For The Space
|
| 89 |
+
|
| 90 |
+
These main-repo areas should not be copied into this Space unless the hosted app
|
| 91 |
+
explicitly starts using them:
|
| 92 |
+
|
| 93 |
+
| Main-repo path | Reason |
|
| 94 |
+
| --- | --- |
|
| 95 |
+
| `pyproject.toml`, `MANIFEST.in`, `researchharness/` | PyPI packaging belongs to the main open-source repo, not the hosted app mirror. |
|
| 96 |
+
| `.github/` | GitHub CI/release automation does not run in the Hugging Face Space repo. |
|
| 97 |
+
| `run_agent.py`, `run_server.py`, `run_frontend.py` | Local CLI/API/frontend entrypoints are not how the Space is launched. |
|
| 98 |
+
| `api/` | OpenAI-compatible API server is not part of the Space app. |
|
| 99 |
+
| `benchmarks/` | Benchmark adapters and benchmark docs belong to the main repo. |
|
| 100 |
+
| `docs/` | Long-form tutorials belong to the main repo. |
|
| 101 |
+
| `tests/` | Main local/CI tests belong to the main repo; Space keeps only focused smoke checks. |
|
| 102 |
+
| `.env.example` | Public environment template belongs to the main repo. |
|
| 103 |
+
| `agent_base/tools/README.md` | Tool documentation belongs to the main repo; Space keeps only runtime code. |
|
| 104 |
+
| `agent_base/prompts/plugins/` | Plugin prompt assets are not used by the hosted app unless a future Space feature explicitly needs them. |
|
| 105 |
+
| `workspace/`, `api_runs/`, `traces/` | Local placeholder/runtime directories are not checked into Space. |
|
| 106 |
+
| local benchmark helpers such as `benchmarks/**/local_*` | Local development helpers must not be deployed. |
|
| 107 |
+
|
| 108 |
+
Keeping these files out prevents stale code paths and misleading documentation
|
| 109 |
+
from accumulating in the Space.
|
| 110 |
+
|
| 111 |
+
## Space-Specific Runtime Behavior
|
| 112 |
+
|
| 113 |
+
These behaviors are intentional hosted-app deltas:
|
| 114 |
|
|
|
|
|
|
|
| 115 |
- Users cannot select arbitrary server folders. Each new chat gets an isolated
|
| 116 |
managed run directory under `RH_SPACE_RUNS_DIR`.
|
| 117 |
- The runtime layout is always:
|
|
|
|
| 132 |
- Old inactive runs are cleaned periodically so the Space does not grow without
|
| 133 |
bound.
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
## Required Secrets
|
| 136 |
|
| 137 |
Configure these as Hugging Face Space secrets before starting the app:
|
agent_base/react_agent.py
CHANGED
|
@@ -27,12 +27,11 @@ from agent_base.tools.tool_runtime import Bash, TerminalInterrupt, TerminalKill,
|
|
| 27 |
from agent_base.tools.tool_user import AskUser
|
| 28 |
from agent_base.tools.tool_web import ScholarSearch, WebFetch, WebSearch
|
| 29 |
from agent_base.utils import (
|
| 30 |
-
PROJECT_ROOT,
|
| 31 |
MissingRequiredEnvError,
|
| 32 |
append_saved_image_paths_to_prompt,
|
| 33 |
env_flag,
|
| 34 |
image_input_content_parts,
|
| 35 |
-
|
| 36 |
read_role_prompt_files,
|
| 37 |
require_required_env,
|
| 38 |
safe_jsonable,
|
|
@@ -1494,7 +1493,7 @@ def _parse_cli_args(argv: list[str]) -> tuple[str, Optional[str], Optional[str],
|
|
| 1494 |
|
| 1495 |
|
| 1496 |
def main(argv: Optional[list[str]] = None) -> int:
|
| 1497 |
-
|
| 1498 |
try:
|
| 1499 |
require_required_env("ResearchHarness agent")
|
| 1500 |
prompt_text, trace_dir, workspace_root, role_prompt, role_prompt_files, image_paths, chat_arg, extra_tools = _parse_cli_args(argv or sys.argv[1:])
|
|
|
|
| 27 |
from agent_base.tools.tool_user import AskUser
|
| 28 |
from agent_base.tools.tool_web import ScholarSearch, WebFetch, WebSearch
|
| 29 |
from agent_base.utils import (
|
|
|
|
| 30 |
MissingRequiredEnvError,
|
| 31 |
append_saved_image_paths_to_prompt,
|
| 32 |
env_flag,
|
| 33 |
image_input_content_parts,
|
| 34 |
+
load_default_dotenvs,
|
| 35 |
read_role_prompt_files,
|
| 36 |
require_required_env,
|
| 37 |
safe_jsonable,
|
|
|
|
| 1493 |
|
| 1494 |
|
| 1495 |
def main(argv: Optional[list[str]] = None) -> int:
|
| 1496 |
+
load_default_dotenvs()
|
| 1497 |
try:
|
| 1498 |
require_required_env("ResearchHarness agent")
|
| 1499 |
prompt_text, trace_dir, workspace_root, role_prompt, role_prompt_files, image_paths, chat_arg, extra_tools = _parse_cli_args(argv or sys.argv[1:])
|
agent_base/utils.py
CHANGED
|
@@ -69,6 +69,15 @@ def load_dotenv(path: Union[str, Path]) -> None:
|
|
| 69 |
_DOTENV_LAST_LOADED[marker] = parsed_value
|
| 70 |
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
def env_flag(name: str) -> bool:
|
| 73 |
return os.getenv(name, "").lower() in {"1", "true", "yes", "on"}
|
| 74 |
|
|
|
|
| 69 |
_DOTENV_LAST_LOADED[marker] = parsed_value
|
| 70 |
|
| 71 |
|
| 72 |
+
def load_default_dotenvs() -> None:
|
| 73 |
+
"""Load dotenv files for both installed and source-tree usage."""
|
| 74 |
+
cwd_env = Path.cwd() / ".env"
|
| 75 |
+
project_env = PROJECT_ROOT / ".env"
|
| 76 |
+
load_dotenv(cwd_env)
|
| 77 |
+
if cwd_env.resolve() != project_env.resolve():
|
| 78 |
+
load_dotenv(project_env)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
def env_flag(name: str) -> bool:
|
| 82 |
return os.getenv(name, "").lower() in {"1", "true", "yes", "on"}
|
| 83 |
|
frontend/local_server.py
CHANGED
|
@@ -27,7 +27,7 @@ from agent_base.utils import (
|
|
| 27 |
PROJECT_ROOT,
|
| 28 |
append_saved_image_paths_to_prompt,
|
| 29 |
image_input_content_parts,
|
| 30 |
-
|
| 31 |
require_required_env,
|
| 32 |
safe_jsonable,
|
| 33 |
stage_image_bytes_for_input,
|
|
@@ -608,7 +608,7 @@ def _run_agent_thread(
|
|
| 608 |
model_name: str = "",
|
| 609 |
) -> None:
|
| 610 |
try:
|
| 611 |
-
|
| 612 |
require_required_env("ResearchHarness frontend")
|
| 613 |
agent = FrontendInteractiveAgent(
|
| 614 |
bridge=bridge,
|
|
|
|
| 27 |
PROJECT_ROOT,
|
| 28 |
append_saved_image_paths_to_prompt,
|
| 29 |
image_input_content_parts,
|
| 30 |
+
load_default_dotenvs,
|
| 31 |
require_required_env,
|
| 32 |
safe_jsonable,
|
| 33 |
stage_image_bytes_for_input,
|
|
|
|
| 608 |
model_name: str = "",
|
| 609 |
) -> None:
|
| 610 |
try:
|
| 611 |
+
load_default_dotenvs()
|
| 612 |
require_required_env("ResearchHarness frontend")
|
| 613 |
agent = FrontendInteractiveAgent(
|
| 614 |
bridge=bridge,
|