Skip to content

feat(cli): add /format-prompt command to enhance rough prompts#1

Closed
jecruz wants to merge 11 commits into
mainfrom
feature-prompt-fix
Closed

feat(cli): add /format-prompt command to enhance rough prompts#1
jecruz wants to merge 11 commits into
mainfrom
feature-prompt-fix

Conversation

@jecruz

@jecruz jecruz commented Mar 31, 2026

Copy link
Copy Markdown
Owner

Summary

Add /format-prompt command that uses the active model to restructure rough user prompts into well-structured agent prompts.

  • /format-prompt <rough prompt> - enhances prompts using the active model
  • Restructures into: Role, Goal, Context, Steps, Output, Style
  • Options: Accept (submit), Edit (opens $EDITOR), Cancel

Motivation

Help users create better prompts to save turns, tokens, and time by submitting structured prompts.

Test plan

  • Test with various prompt inputs
  • Verify Accept/Edit/Cancel workflow
  • Confirm enhancement uses active model credentials

jecruz and others added 11 commits March 31, 2026 08:57
Binding to 0.0.0.0 exposes the webhook receiver on all network interfaces, bypassing reverse proxies and firewalls that front the service.

Change DEFAULT_HOST from 0.0.0.0 to 127.0.0.1 and add WEBHOOK_HOST env var for override. 3 new TestBindAddress tests added. SMS adapter same issue is out of scope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Constant-time comparison prevents timing attacks where an attacker
could measure response latency to brute-force the API key byte-by-byte.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Storing plaintext passwords in .env.example normalizes a security risk.
The file is version-controlled and trivially readable, making it
inappropriate for credentials. Safer alternatives are already documented
above this line: passwordless sudo via /etc/sudoers, SSH backend,
or running as root in containers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Security hardening for API server authentication:

H1 - Auth bypass when no key configured:
- API server now requires explicit opt-in via API_SERVER_ALLOW_NOAUTH=true
- Without this flag, requests are rejected with 401 when no API key is set
- Added startup warning when host is non-loopback and no key is set
- Hmac.compare_digest already in place for constant-time key comparison

H6 - ResponseStore concurrency protection:
- Added threading.RLock to serialize all SQLite operations
- Protects against race conditions when multiple concurrent requests
  access the response store simultaneously

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sandboxed code execution must not be able to import hermes-agent
source-tree modules to exfiltrate credentials. Previously, the
_hermes_root was prepended to the child's PYTHONPATH, allowing
sandboxed scripts to 'from hermes_cli.auth import _load_auth_store'
and read OAuth tokens from the auth store.

Fix: only add tmpdir (where hermes_tools.py lives) to PYTHONPATH.
This allows 'from hermes_tools import ...' to work as expected while
blocking access to the full source tree.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces 11 inline re.sub()/re.compile() calls across _voice_speak_response, _strip_reasoning, and process_loop with module-level pre-compiled pattern constants.
New agent/http_cache.py module provides a thread-safe, TTL-based
in-memory cache for HTTP responses. Applied to web search and extract
functions in tools/web_tools.py:

- _tavily_request: caches POST responses (key: url + params, 5min TTL)
- _parallel_search / _parallel_extract: caches SDK responses (5min TTL)
- _exa_search / _exa_extract: caches SDK responses (5min TTL)

Also added fix to secret-scanner.py hook: FALSE_POSITIVE_VALUES set
and proper break/continue handling to skip known placeholder env var
names without blocking commits.
…ive deps

Add explicit minimum constraints for packages with known CVEs:
- cryptography>=46.0.6 (CVE-2026-34073)
- pillow>=12.1.1 (CVE-2026-25990)
- pygments>=2.20.0 (CVE-2026-4539)
- pypdf>=6.9.2 (DoS/memory/loop CVEs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uses the active model to restructure user prompts into a well-structured
format with Role, Goal, Context, Steps, Output, and Style sections.
Supports Accept, Edit, or Cancel workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

⚠️ Supply Chain Risk Detected

This PR contains patterns commonly associated with supply chain attacks. This does not mean the PR is malicious — but these patterns require careful human review before merging.

⚠️ WARNING: Outbound network calls (POST/PUT)

Outbound POST/PUT requests in new code could be data exfiltration. Verify the destination URLs are legitimate.

Matches (first 10):

1518:+    response = httpx.post(url, json=request_payload, timeout=60)

Automated scan triggered by supply-chain-audit. If this is a false positive, a maintainer can approve after manual review.

@jecruz jecruz closed this Mar 31, 2026
jecruz pushed a commit that referenced this pull request Apr 19, 2026
…ts (NousResearch#11745)

Move moonshotai/kimi-k2.5 to position #1 in every model picker list:
- OPENROUTER_MODELS (with 'recommended' tag)
- _PROVIDER_MODELS: nous, kimi-coding, opencode-zen, opencode-go, alibaba, huggingface
- _model_flow_kimi() Coding Plan model list in main.py

kimi-coding-cn and moonshot lists already had kimi-k2.5 first.
jecruz pushed a commit that referenced this pull request Apr 22, 2026
When the live Vercel AI Gateway catalog exposes a Moonshot model with
zero input AND output pricing, it's promoted to position #1 as the
recommended default — even if the exact ID isn't in the curated
AI_GATEWAY_MODELS list. This enables dynamic discovery of new free
Moonshot variants without requiring a PR to update curation.

Paid Moonshot models are unaffected; falls back to the normal curated
recommended tag when no free Moonshot is live.
jecruz pushed a commit that referenced this pull request Apr 22, 2026
…#13354)

Classic-CLI /steer typed during an active agent run was queued through
self._pending_input alongside ordinary user input.  process_loop, which
drains that queue, is blocked inside self.chat() for the entire run,
so the queued command was not pulled until AFTER _agent_running had
flipped back to False — at which point process_command() took the idle
fallback ("No agent running; queued as next turn") and delivered the
steer as an ordinary next-turn user message.

From Utku's bug report on PR NousResearch#13205: mid-run /steer arrived minutes
later at the end of the turn as a /queue-style message, completely
defeating its purpose.

Fix: add _should_handle_steer_command_inline() gating — when
_agent_running is True and the user typed /steer, dispatch
process_command(text) directly from the prompt_toolkit Enter handler
on the UI thread instead of queueing.  This mirrors the existing
_should_handle_model_command_inline() pattern for /model and is
safe because agent.steer() is thread-safe (uses _pending_steer_lock,
no prompt_toolkit state mutation, instant return).

No changes to the idle-path behavior: /steer typed with no active
agent still takes the normal queue-and-drain route so the fallback
"No agent running; queued as next turn" message is preserved.

Validation:
- 7 new unit tests in tests/cli/test_cli_steer_busy_path.py covering
  the detector, dispatch path, and idle-path control behavior.
- All 21 existing tests in tests/run_agent/test_steer.py still pass.
- Live PTY end-to-end test with real agent + real openrouter model:
    22:36:22 API call #1 (model requested execute_code)
    22:36:26 ENTER FIRED: agent_running=True, text='/steer ...'
    22:36:26 INLINE STEER DISPATCH fired
    22:36:43 agent.log: 'Delivered /steer to agent after tool batch'
    22:36:44 API call #2 included the steer; response contained marker
  Same test on the tip of main without this fix shows the steer
  landing as a new user turn ~20s after the run ended.
jecruz pushed a commit that referenced this pull request Apr 22, 2026
Previously the breaker was only cleared when the post-reconnect retry
call itself succeeded (via _reset_server_error at the end of the try
block). If OAuth recovery succeeded but the retry call happened to
fail for a different reason, control fell through to the
needs_reauth path which called _bump_server_error — adding to an
already-tripped count instead of the fresh count the reconnect
justified. With fix #1 in place this would still self-heal on the
next cooldown, but we should not pay a 60s stall when we already
have positive evidence the server is viable.

Move _reset_server_error(server_name) up to immediately after the
reconnect-and-ready-wait block, before the retry_call. The
subsequent retry still goes through _bump_server_error on failure,
so a genuinely broken server re-trips the breaker as normal — but
the retry starts from a clean count (1 after a failure), not a
stale one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant