Commit Graph

7126 Commits

Author SHA1 Message Date
kshitijk4poor 16fe50b1a2 refactor(gateway): inline the user-bus adoption gate at the run_gateway call site
Drop the 3-line facade wrapper (hermes_cli/gateway.py is already 3x the facade
threshold) and call the existing _ensure_user_systemd_env() directly under
`is_linux() and INVOCATION_ID` — the same Linux gate the process_registry seam
uses, instead of os.name == "posix". The fail-closed test now targets
_ensure_user_systemd_env() itself. Hedge the scope-unavailable error text: the
probe also returns False when systemd-run is missing or times out, so the
D-Bus diagnosis is the usual cause, not the only one.
2026-09-08 02:28:21 +05:30
HexLab98 802f0f97ad fix(gateway): adopt the user D-Bus session when systemd starts the gateway
A system-level unit (/etc/systemd/system, User=<someone>) is exec'd with neither
XDG_RUNTIME_DIR nor DBUS_SESSION_BUS_ADDRESS, and a process environment is fixed
at exec time. 'systemd-run --user --scope' therefore fails for the whole lifetime
of that gateway even after the user manager is up and /run/user/<uid>/bus is
reachable. That is the seam every restart-safe worker crosses
(restart_safe_gateway_child_argv), and it fails closed by design — so on headless
systemd installs every agent-driven cron job and every Kanban dispatch died at
launch, ~26ms in, with nothing but 'error' on the job row.

_ensure_user_systemd_env() already derives both values from our own uid and adopts
them only when the runtime dir is really ours and the socket really exists; it was
just wired exclusively to the systemctl management paths, never to the gateway's
own boot. Call it from run_gateway() — the single in-process boot every entry point
goes through — so the adoption precedes every worker-environment snapshot (cron
builds its env after the scope check, Kanban before it, so fixing this at the
dispatch seam would only fix one of them).

The fail-closed posture is unchanged: with no user manager at all the probe still
reports unavailable and dispatch still refuses. That refusal now names the remedy
in the message the operator actually reads (it is stored as the cron execution's
error), instead of only the symptom.

Fixes #104893
2026-09-08 02:28:21 +05:30
Ayush Nangia 3204bfa5e2 docs+defaults: declare delegation.fallback_providers in config surfaces
Adopted from PR #80421 with the author's explicit go-ahead on #80450
('Please proceed!'): config_defaults entry, cli-config.yaml.example
block, and user-guide docs for the delegation-scoped fallback chain.

Co-authored-by: Andrex Ibiza, MBA <84248988+andrexibiza@users.noreply.github.com>
2026-09-08 02:26:05 +05:30
kshitijk4poor f850bc58ed refactor(inventory): build the gated-Astra warning tail instead of string-replacing a sentence
`warning.replace("Showing the saved model only.", ...)` silently no-ops the day that sentence is
reworded. Pick the tail sentence first, format once.
2026-09-07 21:43:54 +05:30
kshitijk4poor e583d68c14 perf(models): stop revalidating a fresh provider cache just because it lists Astra
``gated_cache`` bypassed both the fresh-hit and the stale-while-revalidate branches of
``cached_provider_model_ids`` whenever the disk entry contained Astra. For an entitled
account that is every entry: live discovery rewrites the entry with Astra → next call is gated
again → a blocking /models round-trip on every picker open, for exactly the providers the user
is most likely on. The parallel prefetch's staleness check didn't know about the gate either, so
it skipped the slug and the blocking call landed in the serial picker loop the prefetch exists to
avoid.

Gate on provenance, not contents: only live discovery ever writes Astra into a same-credential
entry (the static/offline paths filter it out), so a fresh entry IS the entitlement record. The
one filter that matters stays — a stale entry served because the refresh failed drops Astra, and
the entry itself is left intact so the next successful fetch restores it.

The regression test now pins both halves: fresh entry served with Astra and zero live calls;
failed refresh past the fresh window serves the entry minus Astra.
2026-09-07 21:43:54 +05:30
kshitijk4poor b6852995ed refactor(openai): one is_astra_model predicate; gate Astra at the untrusted Codex inputs
The slug pair {"gpt-6-astra", "gpt-6-astra-900k"} was spelled out five times
(reasoning_effort, transports/codex, models.py x2, codex_models) with five hand-rolled
``.strip().lower().rsplit("/", 1)[-1]`` normalisations. ``is_astra_model`` in
agent/reasoning_effort.py (the module the other four already import) is now the only home, so a
new Astra alias is one edit.

``_finalize_codex_models(..., allow_astra=)`` was a control-coupling flag set True by the two
live callers and left False by the two static ones. The filter now lives where the untrusted
inputs are — ``_drop_undiscovered_astra`` over config.toml default + models_cache.json in
``get_codex_model_ids`` — and ``_finalize_codex_models`` is back to its one-line original.
DEFAULT_CODEX_MODELS never contains Astra, so the static catalog needs no gate.

``_openai_catalog`` appends whatever Astra ids live discovery returned instead of a name-keyed
``if "gpt-6-astra" in live_lower`` branch with a literal fallback that could never fire.
2026-09-07 21:43:54 +05:30
Eva fdb76ce643 fix(openai): include canonical API picker identity in Astra discovery gate
(cherry picked from commit de57e601193a955a69201e1a274d5ccab83a7634)
2026-09-07 21:43:54 +05:30
Eva 328542d807 fix(openai): revalidate Astra at cached and saved-model picker boundaries
(cherry picked from commit f46e2f4c0609c1543d5636c780c6da0d5ce09a56)
2026-09-07 21:43:54 +05:30
Eva 299d86851c fix(openai): keep Astra 900K alias gated and wire-compatible
(cherry picked from commit c7cd27d7f050598b9dc052c73fa1dc78c045d3c6)
2026-09-07 21:43:54 +05:30
Eva c990017482 test(openai): close Astra baseline review gaps
(cherry picked from commit 8c27b7c9316ba675e4d9ebcc7a659754f37f18ef)
2026-09-07 21:43:54 +05:30
Eva 2c315ff59b feat(openai): add GPT-6 Astra baseline support
(cherry picked from commit a8c53d20c6b16cc35745e364e16bb7259166a1d3)
2026-09-07 21:43:54 +05:30
Teknium 93af3db01d fix: checkpoint Kanban completion before tool access expires
Give dispatcher-owned workers a tool-capable reporting opportunity before the
hard iteration cap, without accepting arbitrary diffs or weakening failure
counting. Add opt-in per-turn iteration checkpoints for ordinary agents.
Persist checkpoint text with the fresh tool result, never rewrite cached rows.

Salvages the opt-in ratio and per-turn reset implementation from #104683;
credits the earlier default-off signpost proposal in #92438.

Local fixture wire A/B: Kanban ready/1 failure -> done/0; deliberately stuck
workers still reach blocked/2 after two runs. Default-off control unchanged.
Targeted and affected-directory suites queued behind campaign test lock.

Co-authored-by: fangliquanflq <fangliquan@qq.com>
Co-authored-by: C. Michael Gibbs <252231331+MikeGibbsOnyx@users.noreply.github.com>
2026-09-07 08:28:43 -07:00
Teknium 39ed610f8c feat(cron): create paused jobs without a scheduling race
Persist paused state, timestamp, reason and no first trigger in the original
locked creation write. Forward the same boolean contract across CLI, tool,
gateway API and dashboard API, validating at the store boundary. Preserve
explicit operator force-run behavior and normal enabled creation.

The live CLI probe also caught the command shim dropping failure return codes;
forward them so invalid creation reports exit 1 rather than success.

Credit earlier atomic-creation work in #78935 and #94952 and the focused
implementation in #104578. The broader manifest staging layer is not imported.

Co-authored-by: Konstantin Khlopkov <konstantin.khlopkov93@gmail.com>
Co-authored-by: Chloé DuPont <321112755+misschloedupont@users.noreply.github.com>
2026-09-07 08:27:50 -07:00
Teknium 9af6e9fc8b fix: coalesce interactive completion backlogs without losing identity
Based on the earliest batching proposal by BrunoBza (#104686) and JoaoMarcos44 structured correction (#104703). Slim redo into topical siblings and shared TUI poller/post-turn routing. Reported by Xipong (#104671). Local shell-to-loopback probes demonstrate 12 to 1 turn dispatches; suites await the campaign test lock.

Co-authored-by: joaomarcos <joaomarcosdias444@gmail.com>
2026-09-07 08:27:07 -07:00
Teknium 92f4246aa2 fix(cli): hide the console window for banner/update git probes
`hermes_cli/banner.py::_git_run` is the shared spawn path for every banner and
passive update-check git probe (rev-parse, rev-list, remote get-url, ls-remote).
It carried the UTF-8 text contract but not `creationflags=windows_hide_flags()`,
so on Windows each probe run from a GUI-hosted backend (desktop-spawned
`hermes serve`, `tui_gateway` import kicking off `prefetch_update_check`) flashes
a console window. Every other short-lived helper in `hermes_cli/` already passes
the flag; this brings the banner path in line.

Surfaced by CI on this PR: the stray `git ... origin` spawn from the prefetch
daemon landed in `test_env_probe_run_hides_console_window`'s process-wide
`subprocess.run` capture and tripped its call-count assertion. The test now
scopes its assertion through the module's `_spawns` helper like its siblings,
so an unrelated daemon spawn cannot fail it (the production fix is what makes
that stray spawn carry the flag in the first place).

A/B: base `_git_run` -> no `creationflags` kwarg; fixed -> 0x08000000.
2026-09-07 08:23:08 -07:00
Teknium f5afe8bd40 feat: authorize MCP servers with device codes from the CLI
Add explicit RFC 8628 device login and oauth.flow selection while keeping
browser PKCE and the SDK runtime refresh path. Reuse issuer/resource
validation, configured client authentication and profile-scoped storage.
Only persist an approved, validated grant; never echo endpoint error bodies.

Slim redo of #104752 by @wjorgensen, replacing duplicate HTTP/storage
wrappers with the existing SDK and two real-wire invariant tests.

Refs #104742
Co-authored-by: Wes Hermes <weshermes@Wess-Mac-mini.localdomain>
2026-09-07 08:22:35 -07:00
Teknium 3a42722c84 test: verify SSH update checks with real PTY authentication controls 2026-09-07 08:21:24 -07:00
liuhao1024 9f0bf22ce2 fix(cli): pin core.sshCommand to BatchMode ssh in the noninteractive git env
ssh bypasses stdin=DEVNULL and GIT_TERMINAL_PROMPT: when a git child
dials an SSH remote whose host key is unknown, ssh opens /dev/tty
directly and its yes/no prompt steals the caller's terminal — exactly
what noninteractive_git_env exists to prevent. Pin core.sshCommand to
"ssh -o BatchMode=yes" at the config-injection layer so the ssh child
fails instead of prompting; an agent-authenticated ssh still succeeds,
and an explicit user GIT_SSH_COMMAND env var still takes precedence
(#104591).
2026-09-07 08:21:24 -07:00
liuhao1024 03c20babba fix(cli): probe update-check origin URL under the fetch's isolated git env
The startup update check resolved `git remote get-url origin` with the
user's global config in scope while the subsequent fetch runs under
noninteractive_git_env (GIT_CONFIG_GLOBAL=/dev/null). A global
url.<https>.insteadOf rewrite therefore made an SSH origin masquerade as
HTTPS, the SSH-avoiding fast path was skipped, and the fetch dialed the
raw SSH origin — whose host-key prompt opens /dev/tty directly and
steals the CLI's keystrokes (#104591).

Probe the origin URL under the same isolated env so both sides observe
the URL the fetch will actually dial.
2026-09-07 08:21:24 -07:00
Teknium 89c85b8466 fix(update): settle stale receipt warnings from matching live gateways
Reconcile receipt-only restart obligations at the shared warning/catch-up
predicate, requiring every historical runtime/profile identity to have a
current live gateway successor. Preserve missing and unknown obligations,
non-gateway identities, and independently authoritative pending markers.

Keep failed receipts unchanged instead of recording an unverified success.
Live isolated two-process A/B reproduces the warning on base and settles
it after the fix; stale, unknown, and missing-profile controls still warn.

Reported-by: duanzhiwei0315
Inspired-by: zengzheqing (#104295), RootZ3n (#100249)
2026-09-07 08:20:46 -07:00
Teknium 08f2c78d92 fix(update): cover catch-up restart clients with the unit budget 2026-09-07 08:20:09 -07:00
doryani-agent 2a980fbcbd fix(update): let systemd clients outwait legitimate unit transactions
Salvage the unit-budget implementation from #104745, replacing its test
matrix with two invariant tests and covering the sibling graceful start.
Keep unprivileged property reads, finite fallbacks, real manager errors,
and post-restart health verification.

Native disposable user unit: old client timed out after 15.03 seconds;
new client completed the same 16-second stop transaction in 16.13 seconds.
The unit stayed active with a new PID; missing-unit errors stayed errors.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
2026-09-07 08:20:09 -07:00
Teknium e1a161538a fix(cron): make failed runs diagnosable without verbose delivery errors
Persist a redacted chained traceback in the private run output and expose
redacted last_error in tool and slash listings, including historical errors.
Keep the run_job concise error return unchanged for delivery classification.

Slim redo of liuhao1024's earliest #104545; adds forced redaction and keeps
formatting in a topical sibling. Local SDK/socket A/B verifies diagnosis
visibility plus healthy-script, clearing, and private-file controls.
Canonical tests queued under the campaign lock at commit time.

Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
2026-09-07 08:18:56 -07:00
Teknium 549e6aab38 fix(bot-mode): preserve refusal reasons across local delivery
Emit the one-shot reason marker outside the CLI facade; parse whole codes before falling back to legacy prose. Explicit coordination and unknown codes cannot be labeled target_busy.

Fixes #104784
Co-authored-by: William Echo <2054936695@qq.com>
2026-09-07 08:15:32 -07:00
Teknium 04767e7aaa fix(display): distinguish estimated context from provider usage 2026-09-07 08:13:01 -07:00
Teknium 1491342661 style: remove blank line left by snapshot setting removal 2026-09-07 08:08:41 -07:00
Teknium 7a5fc1b2a9 fix: remove automatic session JSON snapshots 2026-09-07 08:08:41 -07:00
Teknium bbbccd3935 fix: failed probe credentials cannot fall through to configured auth 2026-09-07 08:08:04 -07:00
Teknium 7d44fe9c74 fix: capability probes send minted credentials instead of callable representations
Extend #104477 to the native thinking, vision, metadata, and local header paths identified by #87641. Materialize only at probe boundaries; leave the chat callable and cache ownership untouched. Local-wire A/B: thinking and vision show requests change from 403 to 200, while static credentials and callable chat retain success. Target suites queued.

Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
2026-09-07 08:08:04 -07:00
Teknium 134b173efa fix: reject independent Nous account refresh without clearing cooldown 2026-09-07 08:06:48 -07:00
Teknium de25786dc7 fix: place reauthenticated credentials by their saved identity 2026-09-07 08:06:48 -07:00
Brian Le 32a59f3bf7 feat: refresh one pooled OAuth grant from the CLI 2026-09-07 08:06:48 -07:00
Brian Le 1a4bb74a40 feat: choose pooled credential priority from the CLI 2026-09-07 08:06:48 -07:00
Brian Le 53221df05f feat: reset one pooled credential without clearing sibling cooldowns 2026-09-07 08:06:48 -07:00
Konstantin Khlopkov af212103b0 feat(cli): show entry id and priority in hermes auth list (#104636) 2026-09-07 08:06:11 -07:00
Teknium 478d772f2c fix(desktop): resolve artifact downloads in their originating session 2026-09-07 07:11:36 -07:00
Edizzier 2d52ddc07c fix(cli): planned systemd restarts no longer trigger failure alerts
Salvaged from #104272. Preserve restart and fatal-exit policy while classifying the planned restart code as success. Earlier analysis in #13604 by Justin Kausel.
2026-09-07 07:11:06 -07:00
Teknium b578261584 fix: keep Kanban worker scope out of descendant processes
Carry the existing write fence across Hermes-owned spawn boundaries without
dropping board routing or changing credential policy. Grant dispatcher and
managed tool runtimes explicit task scope; align CLI task mutations with tools.

Verify real shell/CLI descendants, dispatcher startup, and supervised stdio
transport against isolated SQLite boards. This is cooperative runtime scoping,
not OS confinement.

Refs #103974, #104058, #104904
2026-09-07 07:10:28 -07:00
Teknium 258fa9741c fix: retain Kanban decomposition identity and inherit parent tenants 2026-09-07 07:09:59 -07:00
Teknium 5dfea72f75 refactor: extract Kanban graph persistence into topical sibling 2026-09-07 07:09:59 -07:00
Teknium f17f18cd11 fix(desktop): release Windows app locks at staged promotion
Salvage #101887 after native Actions 34097643131 reproduced WinError 32 using a ready Electron app with its cwd inside the live release. Reuse the existing install-scoped process cleanup before promotion and wait after forced termination, preserving rollback.

Co-authored-by: fangliquan <fangliquan@qq.com>
2026-09-07 06:55:13 -07:00
Teknium c89f3b8800 fix(delegation): one completion per call by default; queued units no longer stalled; tell the model results land between turns
Three orchestrator failures traced through the Sep 7 gpt-6-astra campaign sessions:

1. delegation.independent_completions (new, default false). #104299 made every
   ungrouped task its own completion message, so a 15-task call woke the
   orchestrator up to 15 times; one chain received 132 notices and answered
   130 of them with "already incorporated". A multi-task call now returns as
   ONE consolidated message unless the flag is on; `group` is inert until then.

2. Queued units were killed before they started. Units of one call share a
   pool slot but the executor was still sized by slots, so with 15 units live
   a new unit queued behind a full pool; the stale monitor's clock ran from
   dispatch, interrupted it at 450 s, and the child exited `interrupted 0.02s`
   when its thread finally came up (13 such lanes in one session). The
   executor now grows to the number of live units and the stall clock arms
   when the runner actually starts.

3. The tool text said "do not wait or poll — just continue" without saying
   that completions are delivered only BETWEEN turns. A model that never ends
   its turn (one 203-minute turn, 717 API calls) never received 40 finished
   results. Tool description, dispatch note and completion header now say to
   finish independent work, give a one-line status, and end the turn.
2026-09-07 06:46:54 -07:00
Teknium fd3565deec fix: remove dedicated user-facing output cap controls 2026-09-07 06:15:43 -07:00
Teknium eb027a8802 fix(cli): preserve explicit dashboard update checks
Opt the two passive consumers into the config gate; retain default explicit checks and the existing dashboard caller contract.
2026-09-07 06:13:16 -07:00
Teknium 4dcdb5e896 fix(cli): allow pinned installs to disable passive update checks
Adapt the config-only portion of #104347; omit its environment flag and unrelated docs. Explicit update commands remain independent.

Co-authored-by: Rohith Pariki <rohithpariki@gmail.com>
2026-09-07 06:13:16 -07:00
Teknium 65f033a1a2 fix(execute-code): teach the working helper import contract
Slim adaptation of #83772 to the current schema and failure-hint table.
Generated helpers are module exports on every execution path, not globals.
Correct schema, recovery hints and CLI tip rather than injecting names or
changing the execution boundary. Two registry-driven invariants reproduce
both misleading instructions on main and execute the corrected guidance.

Additional tool fix discovered during campaign #104904.
Original diagnosis and correction: @yuzilongleif-collab (#83772).

Co-authored-by: yuzilongleif-collab <235949691+yuzilongleif-collab@users.noreply.github.com>
2026-09-07 06:12:24 -07:00
Teknium 34e512ae58 fix(sessions): remove remaining timer migration and guidance 2026-09-07 06:10:54 -07:00
Teknium 1d5d059410 fix(gateway): stop time-triggered conversation rotation 2026-09-07 06:10:54 -07:00
Teknium 7798241eab fix: retain pending fleet restarts until supervisors recover
Discover systemd targets before stopping old processes, restart even when
there are no gateway PIDs, and require successful scope listings plus active
verification. Pending launchd recovery also retains failures for inaccessible
listings and installed jobs without supervision. Keep existing PID cleanup
intact but before recovery so it cannot kill freshly verified workers.

Slim redo informed by #104274, #104283, and #104285.

Co-authored-by: fangliquanflq <fangliquan@qq.com>
Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
2026-09-07 06:10:49 -07:00
Teknium f83ff89780 fix(desktop): reveal complete slash help across the window
Preserve producer descriptions without identity wrappers and size the existing themed tooltip to the viewport. Replace skipped and structural tests with two behavioral invariants. Native Electron before/after hover, click and keyboard verification passed; campaign suite validation remains queued.
2026-09-07 06:10:15 -07:00