Commit Graph

14915 Commits

Author SHA1 Message Date
Teknium bcef8d66d3 fix: retain reasoning effort on named custom provider routes
Apply the narrow registry fallback proposed in PR #68458 without unrelated case normalization or dead legacy flags. Preserve dedicated named profiles before using CustomProfile. This corrects existing reasoning loss only; per-model dialect configuration remains a product decision.

Co-authored-by: saotu <160758706+saotu@users.noreply.github.com>
2026-09-07 06:06:46 -07:00
Teknium 8d4b7414a0 test(recovery): distinguish the profile home from the full backup root 2026-09-07 06:06:20 -07:00
liuhao1024 342967058c fix(agent): interpolate the live backups dir into corruption recovery guidance
The corrupt-cause recovery guidance hardcoded `~/.hermes/backups/` while
every other path in the same message follows the active HERMES_HOME
(`{db_path}` is already interpolated). A custom-home or named-profile
deployment was told to restore from a directory that may not exist at all,
mid data-loss incident. Both sites (turn-completion explainer and gateway
startup broadcast) now interpolate `<hermes_root>/backups` via
get_default_hermes_root(), matching hermes_cli/backup.py's real backup
location.

Fixes #104250
2026-09-07 06:06:20 -07:00
Teknium 57c60f2e0c fix: explain the launchctl registration restriction without inventing KeepAlive 2026-09-07 06:05:51 -07:00
Teknium 4fbb253904 fix: mirror successful memory alias writes to providers 2026-09-07 06:05:13 -07:00
Teknium 7ef4187e11 test: pin memory alias persistence without dispatch mocks 2026-09-07 06:05:13 -07:00
liuhao1024 fb0fc7e140 fix(agent): forward the new_text alias in the memory inline executor
The memory_tool schema advertises new_text as an alias for content, and
memory_tool resolves it when content is None. But the table-driven inline
executor's arg_specs (agent/inline_tool_executors.py) did not list new_text,
so _call_tool's allowlist silently dropped it: a replace call using the
documented alias reached memory_tool with both fields None and failed with
"content is required for 'replace' action." — even though the caller
supplied the value. Forward new_text alongside content/old_text so the
documented alias fires and content still wins when both are set, matching
what the batch path (op.get("content") or op.get("new_text")) already
accepts.
2026-09-07 06:05:13 -07:00
Teknium 11082f603e test: consolidate video rejection variants into one invariant 2026-09-07 06:04:44 -07:00
fangliquanflq 00b4c49939 test(agent): cover all rejected video part types
Co-authored-by: crazyief <8566250+crazyief@users.noreply.github.com>
2026-09-07 06:04:44 -07:00
fangliquanflq 2b7b940046 fix(agent): reject unsupported Codex video input 2026-09-07 06:04:44 -07:00
Teknium 7e73ef4676 test: preserve batched context ties and duplicate hits 2026-09-07 06:04:23 -07:00
Teknium 20af238599 perf: batch search context using indexed neighbor seeks
Keep projections query-free and timestamp/id neighbor ordering. Bound parameter batches at 500 and avoid scanning complete sessions with LAG/LEAD. Based on the N+1 analysis in #104296; no additional YAML cache or durability/freshness changes.

Co-authored-by: DevvGwardo <25094504+DevvGwardo@users.noreply.github.com>
2026-09-07 06:04:23 -07:00
Teknium a1fdf5556e fix(kanban): clarify that watch names its initial board 2026-09-07 06:04:06 -07:00
Teknium d0c0f2c576 test(kanban): initialize isolated boards for watch resolution 2026-09-07 06:04:06 -07:00
Teknium 8cffac608e fix(kanban): name the resolved board in watch startup
Slim adaptation of anombyte93/hermes-agent@d06d2a49c5; use the canonical board resolver instead of inferring the slug from a path. Live isolated CLI probe confirms current-file, env and explicit board banners; event delivery remains live.

Co-authored-by: Hayden (Atlas agents) <212644172+anombyte93@users.noreply.github.com>
2026-09-07 06:04:06 -07:00
Teknium 746b14b900 test: use explicit UTF-8 in file sync fixtures 2026-09-07 06:02:41 -07:00
liuzikaii b4e0f4a7bb fix(file-sync): hash the uploaded snapshot instead of mutable host files 2026-09-07 06:02:41 -07:00
Teknium ed3b9920ad test: model token flushes in the persistence race fixture 2026-09-07 06:02:22 -07:00
Teknium f9523c20e7 test: preserve reusable localhost provider wire A/B probe 2026-09-07 06:02:22 -07:00
Teknium ebe4e7bb44 fix: sanitize resolved auxiliary chat requests before dispatch
Extend the destination-boundary approach from PR #87840 to synchronous, asynchronous and streaming auxiliary dispatch, including prepared MoA requests. Keep native adapter replay intact.

Co-authored-by: siyoon <siyoon@friendli.ai>
2026-09-07 06:02:22 -07:00
fangliquanflq e24c8499f2 fix(cron): isolate ledger helpers from stale execution modules 2026-09-07 06:01:31 -07:00
Teknium f8c9e93dad fix: round-trip checkpoint path bytes without text translation 2026-09-07 06:00:46 -07:00
liuzikaii d77df6674a fix(checkpoints): preserve literal paths in Git filename output 2026-09-07 06:00:46 -07:00
Teknium ea22528630 fix: reject blank unknown delivery destinations too 2026-09-07 06:00:05 -07:00
Teknium 33c1bb885c fix: reject unknown delivery targets and allow API session preflight
Salvage only the demonstrated delivery and session-header fixes. Leave queue admission, other CORS expansion and unrelated optimizations out of this bug pass.

Co-authored-by: DevvGwardo <25094504+DevvGwardo@users.noreply.github.com>

Co-authored-by: Frowtek <frowte3k@gmail.com>
2026-09-07 06:00:05 -07:00
Teknium a3ad585fd9 fix: limit skill update change to unusable local installs 2026-09-07 05:59:43 -07:00
Teknium 6798a9b8a4 fix: bound skill update wait budget and lingering fetch workers 2026-09-07 05:59:43 -07:00
Teknium 2079e4f08d fix: skip lock entries replaced by non-directory files 2026-09-07 05:59:43 -07:00
Teknium 36b0b6c9f2 fix: enforce complete fetch deadlines and inherit request context 2026-09-07 05:59:43 -07:00
liuhao1024 47887693c6 fix(skills): skip orphaned hub entries and bound per-fetch time in update checks
check_for_skill_updates() fetched every lock-file entry remotely, even
when the entry's install directory no longer existed, and each fetch had
no wall-clock bound — a few dead sources turned a routine
`hermes skills update` into a multi-minute stall (#104291).

- Entries whose recorded install_path resolves but does not exist are
  reported as "orphaned" and skipped without a remote fetch;
  unresolvable paths keep the previous fetch behavior.
- Each fetch now runs under a daemon helper thread with a hard timeout
  (default 30 s) and degrades to "unavailable" when abandoned.
- `hermes skills check` prints a removal hint for orphaned entries.

Fixes #104291
2026-09-07 05:59:43 -07:00
Teknium bf169bef77 fix: preserve false bypass values and single hook invocation 2026-09-07 05:59:08 -07:00
Teknium e566026a44 test: reproduce legacy summary-hook keyword failure
Regression coverage from PR #104214. Live inherited-compress probe reproduces the same failure on main; serial unit runner lock is busy.

Co-authored-by: fangliquanflq <fangliquan@qq.com>
2026-09-07 05:59:08 -07:00
Teknium b43d865f81 test: preserve late retry supersession and isolate profile fixtures 2026-09-07 05:58:52 -07:00
Teknium 80b3346eee fix: publish deferred room retries after discussion cleanup
Resolve task sources and committed member messages from the durable log,
not disposable policy projections. Record late outcome receipts without
reactivating settled discussions; retain frozen prompts and retry behavior.

Slim redo of the durable-log and late-publication portions of #104020.
Unlike that proposal, retain retries and do not hide reconstruction errors.
Also retain the source after the bounded thread transcript ages it out.

Refs #104007
Co-authored-by: Halldrix <12357213+Halldrix@users.noreply.github.com>
2026-09-07 05:58:52 -07:00
liuzikaii 5b2c417db8 fix(cron): serialize delivery deduplication with terminal retention 2026-09-07 05:58:24 -07:00
Teknium 76af5ebf09 test: release notification fixtures without writable stdin 2026-09-07 05:57:26 -07:00
Teknium 231828cdac test: synchronize child exit with notification admission 2026-09-07 05:57:26 -07:00
Teknium 567d53db23 test: use an isolated real ledger for Chronos claim rearming 2026-09-07 05:57:26 -07:00
Teknium 96a903c9d2 fix: keep ambiguous cron occurrence snapshots nullable
Canonicalize the accepted raw next_run_at value before fast-forward rather
than its timezone-interpreted datetime. Legacy naive values remain runnable
but cannot establish an exact UTC identity. Preserve repaired aware slots.

Extend the existing identity invariant with the naive-slot control, and use
real ledger creation in the provider ordering test instead of an invented
execution ID that cannot pass the owner-fenced occurrence setter.

Live validation: actual builtin script run was RED (invented UTC identity)
and is now GREEN (NULL identity). Repeated builtin/provider/worker rollback
A/B remains 2 writes on base versus 1 on head, with distinct/manual controls.
Canonical cron regression rerun is queued under the campaign lock.
2026-09-07 05:57:26 -07:00
Teknium 8aa7ae4f23 test(cron): exercise scheduled identity through the worker entry point 2026-09-07 05:57:26 -07:00
Teknium 7d6d0709cd fix(cron): skip completed scheduled occurrences after snapshot rollback
Capture the exact UTC scheduled instant before either due scanning or the
external fire claim advances jobs.json. Bind it to the durable attempt
before worker handoff; manual and unclassified direct attempts stay null.
Consult any retained completed matching row, independently of stale stamps,
claim-time windows, and newer failed attempts. Preserve unknown and legacy
attempt eligibility rather than guessing that a side effect completed.

Real isolated restart probes reproduce duplicate script writes on base and
suppress them on the fix for builtin tick and provider fire. Distinct and
manual occurrences still execute. The campaign-serialized cron suite is
queued; this progressive commit preserves the verified integration step.

Credit holny's issue #104790 and guard proposal #104323; exact identity
replaces the approximation rather than importing its legacy heuristic.

Co-authored-by: holny <holny@foxmail.com>
2026-09-07 05:57:26 -07:00
Teknium c0c6b31543 fix(update): stream build progress without concealing silent stalls
Retain partial-line output, UTF-8 decoding, failure output and cancellation cleanup. Based on streaming investigations by Artemonim (#101850) and lEWFkRAD (#104843); gateway tee adapted from fangliquanflq (#97402). Live Linux child/tee probe: withheld or dropped on base, visible in 0.02 seconds after. Campaign-locked tests and native Windows proof are pending.
2026-09-07 05:56:50 -07:00
Teknium d0c90039a7 fix(messaging): keep profile status truthful without credential inheritance
Preserve the two contributor fixes, slim them to two behavioral invariants, and enter explicitly requested homes even inside a nested scope. Real native remote Desktop changes Disabled to gateway_stopped for default and named profiles; direct API controls preserve explicit disable and empty-profile isolation. Unit A/B and regression suites remain queued under the shared campaign lock.
2026-09-07 05:56:33 -07:00
vectorcontext e24f07239f fix(dashboard): reclassify profile=default as current when it resolves to the process home
The desktop app always sends profile=default on GET /api/messaging/platforms.
_is_current_profile() recognized only None/""/"current" as the dashboard's
own profile — NOT the string "default" — so a single-profile install (the
standard `hermes gateway setup` flow: token in .env, no platforms: section in
config.yaml) entered the profile-scoped branch of _config_profile_scope().
That branch derives platform enablement from config.yaml only and never calls
load_gateway_config()'s env-override pass (which enables the platform when the
token is in the environment). Result: a platform connected via .env reported
enabled=false, state="disabled" while it was actually running. The unscoped
GET (no profile param) correctly reported enabled=true, state="connected".

Fix: classify by resolved path, not by string. After _is_current_profile()
fails, _config_profile_scope() now resolves the requested profile dir and
compares it against get_process_hermes_home().resolve() — the same comparison
_is_other_profile() already uses. When they match (profile=default on a
default-home process), yield None (no override), taking the unscoped path that
calls load_gateway_config(). A named-profile process (`-p worker`) has a
different HERMES_HOME, so its profile=default resolves to a different directory
and still scopes correctly — cross-profile secret isolation is preserved.

The scoped branch's config.yaml-only enablement is DELIBERATE:
load_gateway_config()'s env pass reads os.environ and would leak the root
install's tokens into a genuinely different profile's state. This fix only
reclassifies requests that name the process's OWN home; it does not touch the
scoped branch or gateway/config_env.py.

Refs #104614
2026-09-07 05:56:33 -07:00
liuhao1024 9098c9a65a fix(dashboard): guard empty-required_env platforms in the scoped enablement fallback
all() over an empty tuple evaluates True, so the scoped credential
fallback reported platforms with required_env == () (whatsapp, yuanbao,
api_server, webhook, a2a, msgraph_webhook, relay, whatsapp_cloud) as
enabled=True with no config entry and no credentials. Add the
bool(required) guard to the enabled computation (per review suggestion)
and to the configured field, which came from the same all()-over-empty
expression and reported configured=True for the same shape — the
unscoped branch reports enabled=False / configured=False there, so the
scoped branch now agrees.

Adds tests/hermes_cli/test_web_server_scoped_enablement.py covering the
empty-required_env shapes, the explicit-enabled precedence, and the
credentials-present path.

Co-authored-by: crazyief <8566250+crazyief@users.noreply.github.com>
2026-09-07 05:56:33 -07:00
liuhao1024 5dfa2f8374 fix(dashboard): env credentials enable a platform on the profile-scoped messaging status path
The scoped branch of _platform_enablement consulted only config.yaml's
platforms: section, but the `hermes gateway setup` wizard writes .env
credentials and never a platforms: entry. The desktop always sends
?profile=default (normalizeProfileKey maps the primary profile to
`default`), so the Settings - Messaging page showed a working bot as
"Disabled" while /api/status reported it connected (#104614).

Mirror _enable_from_env (gateway/config_env.py): env credentials alone
enable a platform, an explicit enabled: false still wins. Only the
profile's own .env (env_on_disk) is consulted, so the root install's
os.environ credentials still never leak into a profile's state.

Fixes #104614
2026-09-07 05:56:33 -07:00
Teknium f4fa6bf2dc fix(desktop): validate packaged archive and renderer before Windows success 2026-09-07 05:55:26 -07:00
Teknium 8d24bc24e1 fix: wait sixty seconds before provider silence notices 2026-09-07 05:24:15 -07:00
Teknium 44a583fcc8 fix: retain profile idle activity after session removal 2026-09-07 04:56:38 -07:00
Teknium 2f090fbdec fix(serve): run idle skill maintenance on the existing timer
Desktop-only backends now poll curator and personal/org skill sync without another long-lived loop. Respect active turns, the actual idle threshold, and messaging gateway ownership. Credit Jackal991 for the report and candidate #95453.
2026-09-07 04:56:38 -07:00