forked from NousResearch/hermes-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(computer-use): draw self-localization action marker on follow-up captures #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
166 commits
Select commit
Hold shift + click to select a range
d91083b
fix(website-policy): key blocklist cache on the real default config path
aydnOktay a0c90ed
fix(skills): retry rate-limited Contents API directory listings
teknium1 9e872db
fix(redact): skip env-assignment redaction for programmatic env lookups
teknium1 316e775
fix(vision): unified image-source resolver + terminal-backend confine…
jquesnelle ab2f5a0
fix(vision): address review — restore bare relative paths, remove dea…
teknium1 ac94f2c
fix(vision): convert SVG/unsupported image formats to PNG before embe…
JAlmanzarMint 4ac8c75
fix(vision): mkdir converted-PNG output dir; wire SVG pass-through to…
teknium1 6c06835
fix(vision): stdin=DEVNULL on rasterizer subprocess (stdin guard)
teknium1 0d27d2e
fix(vision): bound the sandbox exec-read at the ingest cap
teknium1 ec29590
fix(webhook): enforce body-size limit on chunked requests
2b4ec00
fix(api_server): return 413 for oversized chunked bodies
ddd3a2d
fix(auxiliary): fall back to token resolver when anthropic pool has n…
Jigoooo 2bb11ad
fix: classify OpenRouter 'no tool use' 404 as model_not_found with fa…
webtecnica 55e7986
fix(poolside): handle integer finish_reason and tool_call id
70dffb6
fix(codex): recover final app-server text without completion
ooiuuii 8552cac
fix: drop unrelated package-lock churn and dead poolside picker entry
teknium1 10f7cb0
chore(release): AUTHOR_MAP entries for salvaged PR authors
teknium1 ff4c817
fix(gateway): attach credential_pool to session /model overrides
tuancookiez-hub 11b4a21
fix(gateway): clear last-resolved-model cache on /new and compression…
liuhao1024 7e8f50a
fix(gateway): load display config from routed profile
tianma-if af01b3c
fix(config): stop provider-key warn-storm that stalls Windows logging
lEWFkRAD eb0cc27
fix(logging): drive rotating file handlers through an async QueueList…
lEWFkRAD ac68a64
fix(gateway): drain async log queue on os._exit shutdown backstop
kshitijk4poor 1388cd1
fix(logging): thread-safe queue state + bounded hard-exit drain + rec…
kshitijk4poor f512d6f
feat(plugins): pre_tool_call approve action escalates to human gate
kshitijk4poor a0a3c71
fix(telegram): dedup saturated mid-stream overflow previews to stop f…
teknium1 5b85932
fix(gateway): cap proxy SSE line buffer
ooiuuii 132bb8a
fix(yuanbao): restore active singleton after WS reconnect
liuhao1024 6c7960c
fix(whatsapp_cloud): honor documented WHATSAPP_CLOUD_ALLOWED_USERS / …
sahil-shubham c018096
test(whatsapp_cloud): intake-gate regression coverage for documented …
teknium1 d810ff2
chore(release): AUTHOR_MAP entries for salvaged PR authors
teknium1 485ae54
fix(gateway): pass full transcript to compressor instead of filtered …
teknium1 6f052b7
fix(copilot): set x-initiator per turn so user prompts bill as premiu…
teknium1 f23026f
Merge pull request #58536 from NousResearch/salvage/3955-webhook-chun…
teknium1 4eaf5ba
Merge pull request #58534 from NousResearch/salvage/2854-redact-geten…
teknium1 d51657c
Merge pull request #58531 from NousResearch/salvage/3033-contents-api…
teknium1 b3c7b34
Merge pull request #58526 from NousResearch/salvage/3923-website-poli…
teknium1 9ae17b8
security(vision): route local-file inputs through the shared credenti…
srojk34 b6b9bcd
fix(profiles): preserve symlinks during profile export
liuhao1024 8d9684c
fix(profiles): allowlist default-export paths + preserve symlinks (#5…
b7192b1
fix(profiles): preserve symlinks in clone-all and skills clone paths
mvanhorn 020a716
chore(release): AUTHOR_MAP entries for salvaged PR authors
teknium1 fc18d15
fix: preserve static custom provider models
lord-dubious 7915837
fix(auth): prune stale custom model credentials
tianma-if e4da3a7
chore(release): AUTHOR_MAP entry for salvaged PR author
teknium1 ce82b0c
fix: `hermes journey` crashes on Windows due to `%-d` strftime directive
wyuebei-cloud 7e037e1
fix: cover remaining GNU-only %-d strftime site in learning graph render
teknium1 dec4485
chore(release): AUTHOR_MAP entries for salvaged PR authors
teknium1 70449a4
fix(security): add timestamp-bound V2 signature for generic webhook r…
MorAlekss 708b57e
fix(webhook): rate-limit V1 deprecation warning + document V2 signature
teknium1 1b7853d
fix(gateway): add system dirs to PATH for UV Python compatibility
kevinrajaram 619db01
fix(gateway): move PATH bootstrap below imports, gate to POSIX
teknium1 4751af0
feat(errors): fail fast on TLS certificate verification failures with…
teknium1 edf8e0b
feat(mcp): surface MCP server log notifications in agent.log (#57416)
teknium1 3047996
fix(gateway): tolerate punctuation on silence markers
ooiuuii 9767e19
feat(skills): stacked slash-skill invocations — /skill-a /skill-b do …
teknium1 cb6c47a
feat(approvals): /deny <reason> relays denial reason to the agent (po…
teknium1 ebfc49c
fix(approval): require exact ./.. segments in the root-collapse hardl…
teknium1 d577408
fix(webhook): reject generic V2 signature missing timestamp instead o…
MorAlekss e02cef0
fix(memory): guard local uploads against credential reads
necoweb3 8324dd1
fix(agent): replace custom socket_options transport with httpx pool-l…
DavidMetcalfe 51c1ba6
fix(agent): apply pool-level keepalive to the process_bootstrap sibli…
teknium1 c13281a
Guard native image routing with file safety
necoweb3 d8b5126
fix(update): skip cua-driver refresh when Applications is unwritable
d537d29
fix(computer-use): increase cua-driver session startup timeout from 1…
liuhao1024 7fde19a
fix(cli): unwedge cua-driver installer timeouts — group-kill, stale-l…
teknium1 1c15673
docs: warn that mid-session model switches break prompt caching (#58747)
teknium1 2c0820c
feat(cli): autocomplete + ghost text for stacked slash-skill invocati…
teknium1 24a7546
fix(cli): drop shell=True from cua-driver installer — download to mks…
teknium1 de4310c
fix(computer-use): report the wedged startup phase in the session rea…
teknium1 7af9abd
fix(computer_use): fall back to CLI transport when cua-driver MCP bri…
13b75e7
fix(computer_use): re-fetch via CLI when MCP returns silent-empty cap…
519ec7b
fix(computer_use): parse (label) and = "value" AX element label forms
95fc3c6
chore: add alastraz to AUTHOR_MAP for PR #41383 salvage
teknium1 bfc5262
feat: add STT transcript echo toggle
devatnull 406eb71
fix: gate interrupt STT transcript echoes
devatnull 4be749d
fix: honor top-level STT transcript echo config
devatnull 5580013
feat(desktop,docs): surface stt.echo_transcripts in desktop settings …
vKongv 0ca2a92
chore: add devatnull to AUTHOR_MAP for PR #58697 salvage
teknium1 11627fd
feat(whatsapp): native Baileys polls, clarify-as-poll, locations, and…
devatnull b0f2bdb
fix(whatsapp): gate poll-vote events to Hermes-created polls + salvag…
teknium1 4bf5b56
feat: add generic gateway status phrases
devatnull fddc95f
chore: limit generic status phrases to long-running notifications
devatnull 46fbd73
fix: strip tool progress display modes
devatnull 12f03b1
feat: make busy steer ack configurable
devatnull d111faa
fix: preserve busy steer env override
devatnull b9de704
fix: preserve log tool-progress mode with status phrases
devatnull 14c91ad
fix: normalize display boolean strings
devatnull 372c0b5
chore: add devatnull to AUTHOR_MAP for PR #58700 salvage
teknium1 ea125dd
fix: keep Codex commentary phase out of user-visible text
devatnull 538173f
fix(codex): route commentary-phase preamble text to reasoning channel…
annguyenNous b3b1e58
fix(codex): stream commentary deltas through the reasoning channel
teknium1 8a04b51
Port from cline/cline#11803: recursively normalize JSON-string tool a…
teknium1 605727e
feat(discord): optional admin-only gate for exec-approval buttons (#5…
teknium1 24add1d
fix(compressor): keep a user turn when compression would drop the las…
HexLab98 10ced05
test(compressor): pin the zero-user-turn compaction guard (#58753)
HexLab98 b2c5558
test(compressor): drop source-string guardrail tests
kshitijk4poor abf9638
Merge pull request #58974 from kshitijk4poor/salvage/compressor-zero-…
kshitijk4poor 368e5f1
Merge pull request #58698 from kshitijk4poor/feat/pre-tool-call-appro…
kshitijk4poor 01ee312
fix(telegram): forward keepalive limits into fallback transport
liuhao1024 5b04a02
docs(telegram): clarify fallback-branch limits wiring vs siblings
kshitijk4poor b109ade
fix(config): refuse unreadable config overwrites
ooiuuii 123c6f3
fix(config): close unreadable-overwrite bug class at a single chokepoint
kshitijk4poor beaa1a0
fix(config): guard xai migration writer + drop gratuitous annotation
kshitijk4poor dcd70c5
fix(gateway): drain in-flight cron delivery on restart instead of dro…
HexLab98 6b14be0
test(gateway): cover cron-delivery drain on restart
HexLab98 18058c4
fix(gateway): drain housekeeping thread over its own 30s future on sh…
kshitijk4poor 8aab8be
fix(cron): skip delivery/dispatch when the interpreter is shutting down
HexLab98 6d9eff2
test(cron): cover the interpreter-shutdown scheduling guard (#58720)
HexLab98 5986cdd
fix(cron): deliver before tearing down the agent's async clients (#58…
kshitijk4poor e01f58f
feat(mcp): adopt mcp__server__tool naming convention
teknium1 3d02761
test: update MCP parallel-batch fixture names to mcp__server__tool co…
teknium1 55e3ee1
fix: remove dead f-string prefixes via ruff F541 (216 sites) (#52336)
teknium1 ba31699
chore(providers): remove dead cloudcode-pa quota-fallback branches (#…
teknium1 a6079dd
feat(providers): GLM-5.2 native reasoning_effort controls (#58884)
teknium1 77700a0
fix(feishu): send WebSocket CLOSE frame on disconnect (#10202)
teknium1 1b69ad0
fix: update salvaged tests to relocated feishu adapter path
teknium1 eab208d
feat(hooks): spill oversized hook-injected context to disk (#20468)
teknium1 5a5e7e2
fix(nix): follow root pyproject inputs
WadydX 9d2ff58
fix(yuanbao): skip resource resolve on cache hits
heathley 04d732d
fix(gateway): re-check every stacked skill against the platform-disab…
srojk34 f10851e
fix(computer-use): sanitize subprocess env in cua-driver CLI fallback…
srojk34 1e2914b
fix(telegram): redact bot token from connect/disconnect/send_document…
srojk34 3817ff1
security(raft): enforce body-size limit on chunked requests
srojk34 cdcbc3a
fix(gateway): clear last-resolved-model cache on 3 more conversation-…
srojk34 2e2212b
fix(discord): dedup saturated mid-stream overflow previews to stop ed…
srojk34 a573066
fix(redact): skip env-lookup exception for JSON/YAML config field red…
srojk34 0b67ff2
fix(agents): bound streaming error-response body reads
teknium1 747386e
refactor: consolidate gateway session metadata into state.db (#58899)
teknium1 74cc9ee
Revert "Merge pull request #58698 from kshitijk4poor/feat/pre-tool-ca…
kshitijk4poor c9a150d
Merge pull request #59131 from kshitijk4poor/revert/58698-pre-tool-ap…
kshitijk4poor e3203e4
fix(config): invalidate load_config cache when referenced ${VAR} env …
falkoro e985e34
chore: add falkoro to AUTHOR_MAP
teknium1 9ad912a
fix(agent): honor auxiliary.<task>.base_url/api_key when provider is …
falkoro cd2b360
feat: add Docker terminal network toggle
teknium1 3167dba
fix(docker): widen docker_network to file/code-exec paths + guard con…
teknium1 1197d2b
fix(mattermost): accept leading-space slash commands
2f2e608
chore: add l0h1nth to AUTHOR_MAP for PR #32210 salvage
teknium1 25f0cec
Port from nearai/ironclaw#5029: graceful char-budget truncation for r…
teknium1 f514132
fix: disclose mid-line clamp in truncation hint
teknium1 6511767
fix(gateway): apply platform-disabled skill gate to bundle invocation…
teknium1 0823230
fix(computer-use): sanitize env on the 4 remaining cua-driver spawn s…
teknium1 8986981
security(gateway): set explicit client_max_size on 3 uncapped aiohttp…
teknium1 e2fe529
feat(approvals): user-defined deny rules that block commands even und…
teknium1 de7e0a8
fix(docker): heal pairing-dir ownership after `docker exec` writes (#…
teknium1 1f2a33f
fix(mcp): gate probe prompts/resources on config + advertised capabil…
HexLab98 c9adbaf
test(mcp): cover probe capability + config gating for prompts/resources
HexLab98 b57fe5c
fix(setup): exclude posture toolsets from blank-slate disabled_toolsets
liuhao1024 e5636da
fix(toolsets): preserve core tools when a posture toolset is in disab…
bbopen a05b64d
test(setup): blank-slate disabled list must not overlap kept tools
HexLab98 6fad6f1
fix(whatsapp): contain and surface inbound media download failures (p…
teknium1 8e09afd
fix(auxiliary): inherit model.api_key for custom endpoint when per-ta…
Tranquil-Flow ede7e31
fix(auxiliary): gate main api_key inheritance on same-host aux base_url
teknium1 3cd93f6
fix(photon): auto-reinstall stale sidecar deps before start
127d2ee
fix(photon): bound the sidecar dep self-heal npm run with a timeout
teknium1 c5a8df3
chore(release): map jashlee+microsoft@microsoft.com -> s905060 (PR #5…
teknium1 940b69b
fix(sms): bound Twilio webhook body reads to prevent OOM
Alix-007 3dd5ce2
fix(sms): set client_max_size on the Twilio webhook Application
teknium1 4f4cbff
fix(msgraph): enforce webhook body limits
binhnt92 deae37e
fix(tests): add missing json import in msgraph webhook test fixture
teknium1 eec92a9
Enforce WhatsApp Cloud webhook body limit while reading
ooiuuii e82d71d
fix(whatsapp): set client_max_size on the webhook Application
teknium1 a26680e
Enforce Feishu webhook body limit while reading
ooiuuii 2bcb893
fix(feishu): set client_max_size on the webhook Application
teknium1 6133285
chore(release): map Alix-007 author email for PR #54620 salvage
teknium1 6865645
feat(computer-use): draw self-localization action marker on follow-up…
trac3r00 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| """Bounded reads of HTTP error response bodies. | ||
|
|
||
| When a provider returns a non-OK status on a *streaming* request, Hermes reads | ||
| the response body to build a useful diagnostic error. A bare ``response.read()`` | ||
| on a streaming httpx response is unbounded in two dangerous ways: | ||
|
|
||
| 1. A server can declare (or stream) an arbitrarily large body, so the read can | ||
| balloon memory. | ||
| 2. A server can open the body and then stall forever (no ``Content-Length``, | ||
| no further bytes), so the read hangs the agent indefinitely. | ||
|
|
||
| Both are realistic against a misbehaving proxy, a hijacked endpoint, or a | ||
| provider having a bad day. The diagnostic body is only ever shown to the user | ||
| truncated to a few hundred characters, so reading megabytes — or blocking | ||
| forever — buys nothing. | ||
|
|
||
| ``read_streaming_error_body`` bounds the read to a byte cap and enforces a | ||
| hard wall-clock deadline, returning the decoded text snippet. Callers pass the | ||
| returned text into their existing error builders instead of touching | ||
| ``response.text`` (which would be unbounded / would raise after a partial | ||
| stream read). | ||
|
|
||
| A subtlety the implementation must respect: ``httpx``'s ``iter_bytes()`` blocks | ||
| *inside* the C/socket read while waiting for the next chunk. A wall-clock check | ||
| placed only between yielded chunks cannot interrupt a server that opens the | ||
| body and then stalls mid-chunk — control never returns to Python until httpx's | ||
| own (often 30s+) read timeout fires. To guarantee a bounded stop regardless of | ||
| socket behavior, the read runs on a daemon worker thread and the caller waits | ||
| on it with a hard deadline; on timeout we close the response (which unblocks / | ||
| cancels the read) and return whatever partial bytes were collected. | ||
|
|
||
| Ported and adapted from openclaw/openclaw#95108 ("bound Anthropic error | ||
| streams"), generalized to cover Hermes's three streaming error-body sites | ||
| (native Gemini, Gemini Cloud Code, Antigravity Cloud Code). | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import logging | ||
| import threading | ||
| from typing import List, Optional | ||
|
|
||
| import httpx | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| # Defaults chosen to comfortably hold any real provider error envelope (Google | ||
| # RPC error JSON, Anthropic error JSON) while rejecting pathological bodies. | ||
| DEFAULT_ERROR_BODY_MAX_BYTES = 64 * 1024 | ||
| # Hard wall-clock deadline for the whole bounded read. A streaming error body | ||
| # that does not finish within this window is abandoned and the connection is | ||
| # closed; we keep whatever partial bytes arrived. | ||
| DEFAULT_ERROR_BODY_TIMEOUT_S = 10.0 | ||
|
|
||
|
|
||
| def read_streaming_error_body( | ||
| response: httpx.Response, | ||
| *, | ||
| max_bytes: int = DEFAULT_ERROR_BODY_MAX_BYTES, | ||
| timeout_s: float = DEFAULT_ERROR_BODY_TIMEOUT_S, | ||
| ) -> str: | ||
| """Read a non-OK streaming response body with a byte cap and a hard deadline. | ||
|
|
||
| Returns the decoded body text (UTF-8, errors replaced), truncated to | ||
| ``max_bytes``. Never raises: any transport error, stall, or oversize | ||
| condition is swallowed and the best-effort partial text (or an empty | ||
| string) is returned, because this runs on the error path and must not | ||
| mask the original HTTP failure with a read error. | ||
|
|
||
| The byte cap protects against huge bodies; the wall-clock deadline (enforced | ||
| via a worker thread so it can interrupt a socket read that stalls mid-chunk) | ||
| protects against bodies that open and then hang. | ||
| """ | ||
| chunks: List[bytes] = [] | ||
| state = {"truncated": False} | ||
| done = threading.Event() | ||
|
|
||
| def _drain() -> None: | ||
| total = 0 | ||
| try: | ||
| for chunk in response.iter_bytes(): | ||
| if not chunk: | ||
| continue | ||
| remaining = max_bytes - total | ||
| if remaining <= 0: | ||
| state["truncated"] = True | ||
| break | ||
| if len(chunk) > remaining: | ||
| chunks.append(chunk[:remaining]) | ||
| total += remaining | ||
| state["truncated"] = True | ||
| break | ||
| chunks.append(chunk) | ||
| total += len(chunk) | ||
| except Exception as exc: # noqa: BLE001 - error path must not raise | ||
| logger.debug("bounded error-body read failed: %s", exc) | ||
| finally: | ||
| done.set() | ||
|
|
||
| worker = threading.Thread( | ||
| target=_drain, name="bounded-error-body-read", daemon=True | ||
| ) | ||
| worker.start() | ||
| finished = done.wait(timeout=timeout_s) | ||
|
|
||
| if not finished: | ||
| logger.debug( | ||
| "bounded error-body read: hard timeout after %.1fs (%d bytes so far)", | ||
| timeout_s, | ||
| sum(len(c) for c in chunks), | ||
| ) | ||
| # Closing the response cancels the in-flight socket read, letting the | ||
| # worker thread unwind. We do not join (it is a daemon and may be | ||
| # blocked in C); the partial `chunks` collected so far are returned. | ||
| _safe_close(response) | ||
| else: | ||
| _safe_close(response) | ||
|
|
||
| if state["truncated"]: | ||
| logger.debug( | ||
| "bounded error-body read: capped at %d bytes (max=%d)", | ||
| sum(len(c) for c in chunks), | ||
| max_bytes, | ||
| ) | ||
| return b"".join(chunks).decode("utf-8", errors="replace") | ||
|
|
||
|
|
||
| def _safe_close(response: httpx.Response) -> None: | ||
| try: | ||
| response.close() | ||
| except Exception: # noqa: BLE001 | ||
| pass | ||
|
|
||
|
|
||
| def read_error_body_or_default( | ||
| response: httpx.Response, | ||
| *, | ||
| max_bytes: int = DEFAULT_ERROR_BODY_MAX_BYTES, | ||
| timeout_s: float = DEFAULT_ERROR_BODY_TIMEOUT_S, | ||
| ) -> Optional[str]: | ||
| """Like ``read_streaming_error_body`` but returns ``None`` on empty body. | ||
|
|
||
| Convenience for callers that distinguish "no body" from "empty string". | ||
| """ | ||
| text = read_streaming_error_body( | ||
| response, max_bytes=max_bytes, timeout_s=timeout_s | ||
| ) | ||
| return text or None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Auxiliary credential inheritance can now send the main API key to a different service on the same hostname but different port. The new same-host check uses hostname-only matching, so tightening this to host+effective-port (or full origin) would avoid cross-service credential leakage.
Prompt for AI agents