Rl capabilities && File Operator Tools - #15
Conversation
- Updated `.env.example` to include Tinker and WandB API keys for reinforcement learning training. - Enhanced `model_tools.py` to clarify configuration options and streamline the RL training process. - Expanded `README.md` with detailed instructions for setting up RL training using Tinker and WandB. - Modified `hermes_cli` files to integrate RL training tools and ensure proper configuration checks. - Improved `rl_training_tool.py` to reflect changes in training parameters and configuration management.
- Added the tinker-atropos submodule for enhanced RL training capabilities. - Updated model_tools.py to reorder RL function definitions and improve descriptions. - Modified rl_cli.py to include checks for the tinker-atropos setup and provide user guidance. - Adjusted toolsets.py and __init__.py to reflect changes in RL function availability. - Enhanced rl_training_tool.py to manage training processes directly without a separate API server.
- Modified `model_tools.py` to update default model IDs and add new RL function `rl_test_inference`. - Enhanced `README.md` with installation instructions for submodules and updated API key usage. - Improved `rl_cli.py` to load configuration from `~/.hermes/config.yaml` and set terminal working directory for RL tools. - Updated `run_agent.py` to handle empty string arguments as empty objects for better JSON validation. - Refined installation scripts to ensure submodules are cloned and installed correctly, enhancing setup experience.
… streaming - Added unique run ID generation for WandB tracking during test inference. - Enabled WandB usage for test tracking and updated command-line arguments accordingly. - Implemented real-time output streaming for process execution, improving log visibility and debugging. - Enhanced error handling to display last few lines of stderr for better troubleshooting.
- Introduced file manipulation capabilities in `model_tools.py`, including functions for reading, writing, patching, and searching files. - Added a new `file` toolset in `toolsets.py` and updated distributions to include file tools. - Enhanced `setup-hermes.sh` and `install.sh` scripts to check for and optionally install `ripgrep` for faster file searching. - Implemented a new `file_operations.py` module to encapsulate file operations using shell commands. - Updated `doctor.py` and `install.ps1` to check for `ripgrep` and provide installation guidance if not found. - Added fuzzy matching and patch parsing capabilities to improve file manipulation accuracy and flexibility.
🔍 자동 분석 결과이슈 요약리더보드 시스템 — 주간/월간/지역별 순위로 경쟁 유도 + 보상 제공 기술 구현 고려사항백엔드 (Phoenix/Ash)
iOS (SwiftUI)
우선순위 제안
관련existing 코드
🤖 HanNyang Auto Resolver |
* fix: cross-platform terminal/browser support and build fixes - Use platform-aware default shell (zsh on macOS, bash on Linux/Windows) instead of hardcoding /bin/zsh everywhere - Mark Playwright packages as external in Vite to fix chromium-bidi bundle errors during dev - Copy pty-helper.py to dist/server/assets/ on build so production server can find it - Fix browser launch guard to check `context` instead of `browser` (which is always null with launchPersistentContext) - Exclude unused diagnostics.ts stub from route tree - Update README with Playwright install step and Extra section Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add Ubuntu/Debian prerequisites for Tauri desktop build Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Previously hermes-api.ts helper functions (hermesGet, hermesPost, hermesPatch, hermesDeleteReq, streamChat) sent no Authorization header, causing 401 'Invalid API key' errors when the gateway has API_SERVER_KEY configured. Also exports BEARER_TOKEN from gateway-capabilities.ts so hermes-api.ts can import and reuse it for auth headers. Co-authored-by: mgnyc11 <mgnyc11@users.noreply.github.com>
|
已合并到 PR #45 |
1 similar comment
|
已合并到 PR #45 |
…ameter + schema property' (NousResearch#15) from fix/terminal-notify-on-complete into main
Rl capabilities && File Operator Tools
Fixes 12 remaining MEDIUM issues from the deep audit (19 total, 7 fixed in Round 12): design_agent: - NousResearch#15: add asyncio.wait_for(300s) around LLM API call to prevent infinite hangs - NousResearch#17: replace 2x hardcoded 'claude-opus-4-8' with shared DEFAULT_MODEL constant qa_agent / validate_agent: - NousResearch#20,NousResearch#22,NousResearch#23: already fixed in Round 12 (verified — dynamic timeout/threshold values used) memory.py: - NousResearch#24: frontmatter parser uses regex r'^---$' instead of str.split('---',2), preventing false splits on content containing '---' (SQL, markdown tables) - NousResearch#25: parse and preserve 'description' field from frontmatter in metadata, fixing write→load roundtrip data loss profiles.py: - NousResearch#26: ProfileConfig now frozen=True (immutable dataclass per coding standards) deploy_agent: - NousResearch#31: replace 2x sync subprocess.run with asyncio.create_subprocess_exec - fix 5x .decode() → .decode('utf-8', errors='replace') for Windows CJK safety - remove unused import subprocess db.py: - NousResearch#27: add class docstring explaining RLock + _unlocked pattern - NousResearch#28: FK constraints already in DDL (verified PRAGMA foreign_keys=ON active) - NousResearch#29: add _ensure_connection() with PRAGMA integrity_check(1) + auto-reconnect on 4 critical methods (create_task, get_task, claim_task, submit_result) - extract _create_connection() static method for reuse by reconnect Tests: 79 passed, 0 failed
|
Refactor progress on PR #15 file operations, fifth slice: extracted read/delete/move behavior into tools/file_operations_read.py and moved shared result dataclasses into tools/file_operations_results.py while preserving tools.file_operations exports and ShellFileOperations wrapper methods. Commit: a20c28974 (refactor(file-ops): extract read and file actions). Validation: py_compile for touched modules; focused file-operation/parser/live suite 241 passed; standard gateway batches 265 passed and 115 passed; git diff --check clean. Current line counts: tools/file_operations.py 879, read 221, results 82, search 380, lint 339, support 164. |
|
Refactor progress on PR #15 file operations, sixth slice: extracted write/patch mutation behavior into tools/file_operations_write.py and moved the abstract FileOperations interface into tools/file_operations_interface.py. Commit: 80da36609 (refactor(file-ops): extract write and patch actions). Validation: py_compile for touched modules; focused mutation/read/parser/LSP suite 284 passed; standard gateway batches 265 passed and 115 passed; git diff --check clean. The original hotspot is now under target: tools/file_operations.py 476 lines; interface 75; write 222; read 221; results 82; search 380; lint 339; support 164. |
|
Progress update for PRD #15: Implemented the next file-tool refactor slice in e6683b654 (refactor(file-tools): extract tracker state). What changed:
Line counts after this slice:
Validation:
Notes:
|
|
Progress update for PRD #15: Implemented another file-tool refactor slice in 6c6ead02f (refactor(file-tools): extract path safety helpers). What changed:
Line counts after this slice:
Validation:
Notes:
|
|
Progress update for PRD #15: Implemented the third file-tools slice in 37c3bdd13 (refactor(file-tools): extract env cache helpers). What changed:
Line counts after this slice:
Validation:
This continues the low-merge-risk pattern: move implementation behind small modules while preserving the old tools.file_tools import and patch surface. |
|
Progress update for PRD #15: Implemented the next file-tools slice in 9a3e19b4d (refactor(file-tools): extract read handler). What changed:
Line counts after this slice:
Validation:
Note:
|
|
Progress update for PRD #15: Implemented the next file-tools slice in 6138eaa1a (refactor(file-tools): extract search handler). What changed:
Line counts after this slice:
Validation:
Next remaining PR #15 seam is the write/patch mutation handler block; extracting that should bring tools/file_tools.py close to or under the 500-line target. |
|
Progress update for PRD #15: Implemented the mutation/schema slice in 50e42d119 (refactor(file-tools): extract mutation handlers). What changed:
Line counts after this slice:
Validation:
Known existing caveats kept separate:
|
…ded for version bumps) (NousResearch#15) * [agento] fix: green-gate Gate 3 — auto-PASS dependabot PRs (no CR needed for version bumps) dependabot[bot] PRs are automated dependency bumps. Requiring a CodeRabbit review blocks them indefinitely when CR hits rate limits. Add PR_GATE3_AUTHOR check: if author == dependabot[bot], Gate 3 auto-PASSes. Human-authored PRs continue to require CR APPROVED. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * [agento] fix: set LATEST_CR=APPROVED for dependabot Gate 3 auto-PASS (Gate 5 fast-path) BugBot caught that LATEST_CR was unset when dependabot PRs auto-PASS Gate 3, making Gate 5's CR-approved non-blocking fast-path unreachable for those PRs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * [agento] fix: skeptic-cron Gate 3 — dependabot PRs auto-PASS (no CR needed) Mirrors green-gate Gate 3 dependabot exemption so dependabot version bumps can be auto-merged by skeptic-cron without requiring a formal CR review. Adds author field to PR JSON payload so dependabot detection works in the loop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Rl capabilities && File Operator Tools
…de changes) Ran a read-only dry-run against a real exported skill library (76 SKILL.md, 25 candidates, nested category dirs + CJK) in an isolated HERMES_HOME. Pipeline ran cleanly and safely (no mutation); LLM decisions were sensible (2 consolidations proposed, rest kept standalone). Two real gaps fixtures could never expose: - dry-run under-reports consolidation proposals (counts/arrays stay 0 while prose proposes merges) — asymmetric vs split/deprecate (KNOWN_ISSUES NousResearch#15) - keyword-retention guard is near-inert on nested/CJK skills: _load_skill_keywords resolves only flat paths -> name-only fallback (KNOWN_ISSUES NousResearch#16) Guards were not exercised (model used the YAML channel; 25 skill_view, 0 skill_manage). No code changed. Co-Authored-By: Claude <noreply@anthropic.com>
…n report (NousResearch#15 / P0) In dry-run nothing is removed, so the removal-based classification left consolidated/pruned empty even when the model proposed merges — while splits/deprecations already surfaced their YAML proposals. A dry-run preview therefore under-reported what a real run would do (REPORT.md printed 'consolidated: 0' above a prose body proposing merges). Surface the YAML-block consolidation/pruning proposals into run.json counts/arrays + REPORT.md, tagged source='model (proposed, dry-run)' and behind a DRY-RUN banner. The fold runs AFTER the cron-rewrite block so a dry-run never mutates cron/jobs.json; real-run classification is unchanged (guarded by a test). Co-Authored-By: Claude <noreply@anthropic.com>
…h-pass real-data re-verification Co-Authored-By: Claude <noreply@anthropic.com>
…o code changes) Ran a read-only dry-run against a larger, deliberately uncleaned backup (130 usage records vs 123 files, path-prefixed keys, all-active-despite-archive, external symlink). Result: no errors/exceptions handling the dirty data; LLM emitted a well-formed empty structured block (keep all 27); guard not exercised (YAML channel). NousResearch#15 fix makes the reported 0 trustworthy (matches empty block) vs the 8th-pass ambiguous 0. One untested dimension noted: the active-vs-archived usage mismatch's effect on the deterministic prune is not covered by dry-run (prune is skipped). No code changed. Co-Authored-By: Claude <noreply@anthropic.com>
Anthropic bills any >200K-input request on a subscription (OAuth) account
to the EXTRA-USAGE budget, not plan limits — even without the context-1m
beta header (1M context is GA on Claude 4.6+). A 339K-token desktop session
got permanent 'You are out of extra usage' 400s while a small probe on the
same token returned 200.
Fix: _apply_subscription_context_cap() clamps the resolved context to 200K
when the token is an OAuth/setup token (sk-ant-oat*, eyJ*, cc-*). Metered
API keys (sk-ant-api*) are NOT capped. Escape hatch: anthropic.long_context.
Tests: test_critical26_subscription_context_capped_at_plan_lane,
test_critical26_long_context_escape_hatch (both pass)
See CRITICAL NousResearch#15 in CRITICAL-ISSUES.md for full RCA.
Findings #1 and NousResearch#2, together, because NousResearch#2 makes #1 bypassable: a gate in the model-tools path is worth nothing while `registry.dispatch()` reaches handlers without consulting it. `resolve()` now has a production caller. A non-AUTO tool cannot execute without an execution capability, and a capability cannot exist without a decision — not "approved" as a boolean somebody might set early, but a token minted at consent, bound to the exact call, and destroyed by being used. Four properties, each with a test that fails without it. Bound to the tool and an argument fingerprint, so approving one call cannot execute a different one and mutating arguments between consent and execution invalidates the token. One-use, so a retry loop cannot turn one approval into several executions. Short-lived, because consent goes stale. And `consume()` raises rather than returning a boolean — a caller that forgets to check a boolean executes anyway, and this is the one check where forgetting must not be survivable. Fail-closed throughout. A broken permission lookup refuses; `requires_capability` returns True on any exception; an unreadable trust list trusts nothing; minting without a `tool_call_id` is refused outright, because a capability that could match any call is not a capability. Every refusal test asserts the handler ran **zero** times — a gate that refuses after the side effect is not a gate. **The default is `observe`, and that is a gap rather than a preference.** `get_tier()` returns ALWAYS_APPROVAL for unregistered tools — deliberately, so an unknown tool is never assumed safe — and most tools here were never registered. Switching straight to `enforce` would refuse nearly every call in the product, which is an outage, not a safety improvement. `observe` audits every call that *would* be refused, with its tool name, so the registration backlog is measurable against real traffic and the switch can be flipped once the audit goes quiet. This mirrors HERMES_APPROVAL_INTEGRITY_MODE, which exists for the same reason; both must reach `enforce` for the tier system to mean anything, and neither is there yet. Enforce mode is fully tested. Also corrected, per the review: the baseline-failure classification, which I had called environmental wholesale. Three of them are real defects at baseline — `atomic_config_write` NameErrors, a SQLite journal-mode assertion, and a jobs asset-contract failure — and the evidence now says so per failure. And the rollback procedure, which claimed one merge revert covered a many-commit range; it now gives a non-destructive runtime pin plus three repository options, with the history-rewriting one marked as needing explicit approval. Regression check: tests/tools 8532 passed / 19 failed — the failing set byte-identical to baseline, so the gate broke nothing. Still not merged to main. Remaining findings: NousResearch#6 undo wiring, NousResearch#10 Now composition, NousResearch#11 native resume, NousResearch#12 New Chat, NousResearch#13 free-form clarify, NousResearch#14 approval acknowledgement, NousResearch#15 reconnect, NousResearch#16 readiness coupling, NousResearch#17 sensor delivery. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nu2Qaq5Y7EScuooGz8co34
…, coupling **NousResearch#14 — a card could resolve on a decision the gateway never recorded.** `approval.respond` answers with how many approvals it resolved, and zero is a *successful RPC that decided nothing* — the request expired, or was answered elsewhere. The client read the envelope and closed the card, so the owner believed they had answered while the agent stayed blocked. Now only a `resolved >= 1` resolves it, and only an explicit `status: "ok"` resolves a clarify. **NousResearch#13 — free-form clarify answers went out as new prompts.** The native path had a steering step that was a no-op returning true, after which the text was sent via `prompt.submit`: the question stayed open and the answer arrived as an unrelated message. Replaced by one `answerClarifyFreeText` that addresses the request by id natively and walks the menu on the terminal — one method, because splitting it into "steer, then send" is what let the two halves disagree. **NousResearch#11 — resume threw the transcript away.** `session.resume` returns `messages`; `open()` read only the identity fields. A refresh reattached to a running session and showed an empty feed, so execution continued against a conversation the owner could no longer see. History is now delivered through an `onHistory` hook that fires *before* `subscribe()` — ordering is the other half of the fix, since applying the past after live deltas have landed interleaves them — and merges through the existing hydration path rather than a second one. **NousResearch#12 — New Chat did nothing natively.** Both controls rotated a PTY identity that native mode does not use. The session stayed open, its durable id stayed in storage, and the next prompt continued the old conversation under a heading that said it was new. `startNew()` closes the session, clears the profile-scoped durable id before the rebuild so the effect cannot read a stale one, drops the live id immediately, and opens fresh without resuming. **NousResearch#16 — a missing TUI disabled the transport that exists to avoid the TUI.** The chat-readiness probe asks whether the *TUI* can start, and its verdict also gated native session creation. Each transport is now gated on its own prerequisite, and the probe does not run at all under native chat — the banner it raises describes a dependency native chat does not have. Gates: typecheck 0, eslint 0, 74 files / 706 frontend tests, build green. Remaining from the review: NousResearch#6 undo not wired to production, NousResearch#10 Now not consuming the ranking modules, NousResearch#15 reconnect, NousResearch#17 sensor delivery. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nu2Qaq5Y7EScuooGz8co34
**NousResearch#15 — messages could sit "sending" for the rest of the session.** The hook opened once and, on failure, reported an error and stopped. Held messages waited on a `ready` that was never coming. Reconnect is now bounded with backoff and has its own visible state: `reconnecting` is distinct from `connecting` because the owner needs to know a previous attempt failed, and `gaveUp` is distinct from both because it names the point at which nothing further happens without them. When it gives up, held messages are marked failed — an optimistic row that never resolves is a message the owner believes was delivered, and telling the truth eventually is the entire purpose of the optimistic row. The retry budget resets on a successful open, so a later drop gets its own full allowance rather than inheriting an exhausted one. It retries the *open*, never the send: a fresh session is not a reason to re-run a prompt whose fate is unknown. **NousResearch#10 — the ranking modules were asserted and unenforced.** `nowOrder.ts` and `outcomeRanking.ts` had tests while `NowPage.tsx` imported neither and rendered its old composition, which is the same shape of gap as a tier that classifies and a dispatcher that never asks. Now projects real hub state through `nowOutcomes.ts` into the ranker and renders the top three: one recommendation marked *in words* rather than by colour, its reason underneath, each item's work state spelled out, and a native keyboard-operable button to replace the recommendation with a way back to Imperator's. The projection is where invented data would have come from, so it is the narrow place to look: every candidate derives from something the hub reported, there is no placeholder or "get started" row, and an empty hub renders no section at all. A halted guardrail outranks everything because nothing else on the page can proceed while it holds. Tests render the *real* `NowView` against a real payload. Testing the modules in isolation is exactly what let the page ignore them, and after two rounds of my own fixtures agreeing with my own mistakes, a test that builds its own version of the subject is not evidence. Gates: typecheck 0, eslint 0, 74 files / 714 frontend tests, build green. Remaining from the review: NousResearch#6 undo not wired to production, NousResearch#17 sensor capture paths not built. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nu2Qaq5Y7EScuooGz8co34
… — Codex PR NousResearch#30 review (NousResearch#31) Two chatgpt-codex-connector[bot] review comments on PR NousResearch#30 that still applied to current main (the other 13 were already addressed in the merged PR): 1. client.py NousResearch#13 — Cancel timed-out MCP calls: _run_sync now cancels the concurrent.futures.Future on timeout before re-raising, so a stalled MCP endpoint doesn't leave a pending HTTP session running on the shared background loop after the caller has given up / opened the breaker. 2. __init__.py NousResearch#15 — Parse the host before allowing keyless local mode: is_available() now urlparse's the URL and requires an exact loopback host (localhost/127.0.0.1/::1) instead of a substring match, so a URL like 'https://localhost@example.com/mcp' (host=example.com) is no longer trusted as local keyless mode. Adds regression tests: test_memgw_client_timeout.py (cancel-on-timeout fails against pre-fix client) + TestKeylessLocalModeHostParsing (3/4 fail pre-fix). Deferred (already fixed in merged PR NousResearch#30): MCP dep import check, MCP dep pin, loop lock, isError handling, stale-prefetch generation, sync/delegation thread tracking + shutdown join, session-switch prefetch invalidation, no join on turn path, default provider unset. Deferred (complex, needs interface change): NousResearch#3/NousResearch#4 per-turn user_id refresh for shared gateway sessions — sync_turn/prefetch only receive session_id, not user_id, so threading identity through requires a MemoryProvider interface change; NousResearch#1 in-tree placement is an architectural call (AGENTS.md says existing in-tree providers stay).
Initial RL training toolset and complete file operations toolset (to make it operate much more like a coding agent)