Commit Graph

32546 Commits

Author SHA1 Message Date
ethernet
1c729b39f7 fix(icons): commit linux-truth regenerated icons; drop harvest temp
Refresh the 35 generated targets from the ubuntu freshness lane (the
windows regen compresses PNG differently per host zlib; CI checks
against linux bytes). Girl marks + masters are host-stable (stored
deflate blocks / plain text). Removes the temporary artifact-harvest
step now that the committed set matches the check lane.
2026-09-06 21:18:23 -04:00
ethernet
1fa5fea74f feat(icons): derive every icon from nous-girl SVGs + platform backgrounds
The icon pipeline now composes all 35 targets from two source axes instead
of a single hand-edited master:
- girl art: assets/nous-girl-black.svg / nous-girl-white.svg (brand kit)
- backgrounds: assets/backgrounds/ (squircle light/dark, logo frames,
  BrandMark tiles)

assets/icon-master*.svg are generated artifacts (squircle background + girl
nested in the 824px HIG content safe zone). New dark-appearance artifacts
(icon-dark.* containers, appx *-dark logos, logo-dark wordmark,
nous-logo-dark) land everywhere a surface consumes them: docusaurus navbar
srcDark, BrandMark dark tile (keyed off renderedMode).

nous-girl.jpg jpgs are replaced by lossless 8-bit palette PNGs saved with
compress_level=0 (stored deflate blocks, byte-identical across hosts for
the CI freshness lane).

Includes the temp linux-truth harvest step in icons-freshness-check.yml so
the committed compressed bytes can be refreshed from the ubuntu regen.
2026-09-06 21:12:44 -04:00
ethernet
0b30c2484d merge: integrate termux cli bundles into pm-clean
Merge ethie/cli-bundles at 0765ad689b.
Keep PM runtime publication, install identity, TLS policy, and module
boundaries from pm-clean.

Resolve the Node version-discovery method in its owning class. Preserve
staged tools if a repin download or publication fails. Carry extra-only
memory-provider setup through PM and retain restart-required reporting.
Keep target-specific TUI path assertions and discard obsolete self-lock
fixtures and the orphaned Windows service handler.

Verified locally with the canonical Python runner, root JS checks, TUI
checks/build, shell parsing, and workflow YAML parsing. Existing platform
pins and executable modes are unchanged. No full-suite CI, new bionic
bundle, or phone acceptance is claimed for this merge.
2026-09-06 20:13:45 -04:00
ethernet
0765ad689b fix(termux): publish immutable APT indexes and verify the CDN path
Cloudflare cached Packages.gz while serving a new signed Release. Advertise standard Acquire-By-Hash, publish SHA256/SHA512 index objects first, mark mutable APT metadata no-store, and run a real public APT install after upload.
2026-09-06 17:23:16 -04:00
ethernet
c1bb7116c0 test(updater): measure pipe abandonment after fixture startup
Record the child-ready monotonic timestamp before it exits. The leak arm keeps the same drain bound and live-descendant assertion without timing cold PowerShell initialization. The stall arm retains its short watchdog.
2026-09-06 17:12:53 -04:00
ethernet
0d07b5af2a test(tui): keep prior-turn activity recent in the fencing test
The sample must be older than this turn but younger than the staleness threshold, or freshness alone could hide a missing generation fence.
2026-09-06 17:07:18 -04:00
ethernet
495ebb83d3 docs(pm): refresh non-E2E closeout evidence 2026-09-06 17:06:11 -04:00
ethernet
3b9c76b88a test(termux): reap the full TUI process tree before cleanup
Real CLI, ffmpeg, pm, APT refusal and TUI startup passed. A detached gateway child still wrote pycache after SIGTERM; use the existing tree terminator and wait for all descendants before deleting the test home.
2026-09-06 17:05:34 -04:00
ethernet
04182813cf fix(tui): read compute-host control frames from the byte stream
Real Windows child tests sent an interrupt but the text reader never delivered it. Keep caller-supplied streams intact and use the stdin buffer for JSONL. Exercise the real child on all native OS lanes and limit Windows nested-process oversubscription.
2026-09-06 17:04:27 -04:00
ethernet
e6527b2a34 fix(termux): use the current CLI version predicate before dispatch
A stale helper reference aborted every non-chat Termux subcommand before APT ownership could be checked. Verify update, pm doctor and gateway status fall through to normal dispatch.
2026-09-06 16:57:41 -04:00
ethernet
a27cd5902a merge: integrate upstream prompt and plugin fixes
Keep the upstream legacy Bot Mode protocol cleanup and BOM-safe reads. Pin integration at 5bd439d3ed. Scoped Bot Mode tests pass.
2026-09-06 16:48:32 -04:00
ethernet
52b5ea4e7f test: distinguish worker scheduling from protocol completion
Begin compression timeout observation after engine entry. Join hosted-room durable transitions rather than treating a concurrent routing snapshot as a final receipt.
2026-09-06 16:46:25 -04:00
ethernet
c4cad9c89d test: synchronize nonblocking and teardown assertions
Observe worker entry and unfinished work instead of subsecond elapsed-time bounds. Release workers in finally blocks. Verify the resume lock with nonblocking acquire while teardown remains parked.
2026-09-06 16:42:35 -04:00
ethernet
b0c7d0eb47 test(termux): verify upgrades from successful package artifacts
Use a successful admitted release run as the upgrade source. Install its actual deb, upgrade through the signed APT repository, and check user data retention before publishing.
2026-09-06 16:39:54 -04:00
ethernet
a7edeeb1d8 fix(browser): accept BOM-prefixed surviving Chrome metadata
The surviving-profile lookup rejected a valid DevToolsActivePort after a BOM. Extend the existing identity-match regression across BOM and BOM-less files; the BOM case fails before the read fix.
2026-09-06 16:37:34 -04:00
Teknium
5bd439d3ed refactor(plugins): own dual-kind hook fallback in the ledger mixin
Move the general-vs-memory hook ownership logic out of the memory collector into
PluginLedgerMixin (_drop_fallback_hooks / _register_fallback_hook) so the collector
and the loader each call one manager method instead of reaching into manager privates.
Hoist hashlib to module scope. Trim the new suite to the three invariant cases
(run-once across load orders, distinct sources not suppressed, re-exported register).
2026-09-06 13:36:12 -07:00
Joey
684a2cfbd7 fix(plugins): give dual-kind memory hooks a single owner 2026-09-06 13:36:12 -07:00
Teknium
857218e6da ci(lint): deepen the shallow checkout before the public-surface diff; the step is advisory and never fails the job
The round-2 change made check_public_surface refuse to report a clean diff
without a merge-base (exit 2). That correctly exposed that the lint job's
depth-1 checkout plus a depth-1 fetch of the base has NO merge-base, so the
advisory step had been silently reporting 0 drops on every PR. The step now
deepens both sides until a merge-base exists and carries continue-on-error so
an advisory check can never block the Windows-footguns job it rides in.
2026-09-06 13:27:48 -07:00
Teknium
09f2a7c036 fix(ci): check_public_surface refuses unresolvable refs and does not flag methods extracted into an in-module base class
Independent review: a nonexistent base ref under --strict reported zero
drops and exited 0 (a mis-fetched CI job would look clean); the script now
verifies both refs and the merge-base and exits 2 otherwise. And a method
moved from a class into a mixin/base defined in the same module that the
class still derives from was reported as removed although the attribute
still resolves; public_methods now collects the methods REACHABLE on each
class through its in-module bases. Replay of #102117 at open: 1,703 names /
341 modules and 126 test defs / 52 files unchanged; methods 1,000 -> 951
(the 49 were in-module mixin extractions, i.e. the false positives).

Test: unresolvable ref -> exit 2 in both modes; a method extracted into an
in-module base is not reported.
2026-09-06 13:27:48 -07:00
Teknium
8cbb2ce764 feat(ci): public-surface diff vs base (dropped public names, methods, test defs), advisory on PRs
The Sep 2026 whole-codebase refactor (PR #102117) opened with 1,703 public
top-level names dropped across 341 modules, 1,000 public/dunder methods in
166, and 126 `def test_` deleted in 52 files. Reviewers found ~30 of the
names by hand; the rest surfaced as post-merge rework: 10 commits restoring
symbols and facade re-exports, 6 restoring tests, and a qwen OAuth break
that passed import smoke because the caller used `module.attr`. Every one
was catchable in seconds; nothing ran the check because it did not exist.

scripts/ci/check_public_surface.py: AST diff of modules present on both
sides of merge-base..HEAD. Public top-level names (defs, classes,
assignments, imported/re-exported names), public and dunder methods of
top-level classes, and `def test_` counts per tests/ file. Deleted modules
and deleted test files are visible decisions and are not flagged; private
names are not flagged. Advisory (exit 0, prints the report) by default;
--strict exits 1 so a refactor brief or a CI lane can gate on it. Wired
into lint.yml as an advisory PR step next to the compat-pointer check.

Replayed on the refactor PR at open (63279301bcb..022785a541) it reports
exactly the figures above in 18 s; on this branch vs main it reports 0.

Test: a throwaway git repo with drops, private drops, a move-with-re-export,
a lost test def and a changed non-source module; asserts the exact report
and the advisory/strict exit codes.
2026-09-06 13:27:48 -07:00
Teknium
2ed33fb38e refactor(memory): keep the spill, drop registration-trust rework
The prefetch spill is the fix; the is_builtin registration flag and duplicate-
instance rejection defended against a provider naming itself "builtin", which no
live path can do (only a test fixture does). Restore the name-based check and the
four test files that only changed for the new kwarg; keep two spill invariants.
2026-09-06 13:25:48 -07:00
Joey
d932fa5929 fix(memory): spill oversized external prefetch 2026-09-06 13:25:48 -07:00
Teknium
1d06f7a95a docs+evals(compression): token-accounting replay harness and developer-guide section (#104462)
evals/token_accounting/replay_gates.py runs the REAL AIAgent turn loop against a local fake
chat-completions server with scripted usage.prompt_tokens, in three shapes (CLI same-object
history, gateway JSON-reloaded history, SessionDB close/reopen + fresh agent) x two arms
(transcript 3x threshold by bytes/4 while real usage is under; transcript tiny while real usage is
over). Acceptance: no gate fires when real usage is under threshold regardless of estimate
inflation; every gate fires once real usage is over.

origin/main 5f406d88ea: cli/gateway/restore inflated all FAIL (1 local compaction each on the
estimate). This branch: 6/6 PASS, anchor restored in the fresh process.
2026-09-06 13:21:17 -07:00
Teknium
562e6e4824 fix(compression): opaque encrypted_content costs 0 in every local token estimate
Codex Responses reasoning and compaction items carry ciphertext the provider prices by its own
token count, never by bytes; a single native compaction checkpoint is ~5M chars, which the
bytes/4 estimator turned into ~1.29M "tokens" against a 204K threshold (#100611). #104192 deferred
that decision for one request; this removes the mis-pricing at the source so the preflight
estimator and the tail-budget walk agree (a mismatched size class protects blob-heavy rows as
"small" and compaction re-fires). Only real usage prices these items, and the usage anchor carries
that price forward.

evals/native_compaction/ab_checkpoint_preflight.py: preflight estimate after checkpoint
1,292,413 -> 58 rough tokens; the over-threshold negative arm still compresses.
2026-09-06 13:21:17 -07:00
Teknium
0f4587e336 refactor(compression): every compaction gate asks real usage first; rough estimates only decide whether to wait
Two parallel "real usage" mechanisms fought each other: the usage anchor (real + delta) and the
compressor's rough/real projection (should_defer_preflight_to_real_usage with
last_rough_tokens_when_real_prompt_fit / _pending_request_rough_tokens / note_request_rough_estimate
baselines). The projection stored an anchored, real-scale figure as its "rough" baseline, so a
rewind that invalidated the anchor produced phantom growth and a spurious compaction (#103391).

Now there is one authority:

- Post-tool gate (turn_preflight.compress_after_tool_results): anchored figure first (the raw
  last_prompt_tokens ignored the tool results just appended), then real, then rough.
- Gateway hygiene (run_turn._hmwa_hygiene_plan): real session count, else the anchor persisted on
  the session row, else rough.
- Preflight / pre-API gates: an anchored figure is never deferred. A whole-context rough estimate
  over threshold waits ONE request for the provider's real count instead of compressing on a guess
  (first request, rewind/edit-resend, reloaded history without a persisted anchor).
- The wait is one request, never a disable: a provider that omits usage
  (note_usage_less_response, #2153 class), a real reading already over threshold, a rough figure
  past the whole window, and provider-proven overflow all compress immediately; the post-compaction
  latch (#36718 / #104192) is unchanged.
- Projection baselines and their bookkeeping deleted (-101 LOC in context_compressor); the fixtures
  that scripted whole-history estimates now state the fact they relied on (provider omits usage).

Fixes #103391 (closes #103397 by construction — the baseline it repaired no longer exists).
2026-09-06 13:21:17 -07:00
686f6c61
c0aaa238f6 feat(compression): usage anchor survives DB reloads and process restarts (salvage #99585)
The usage anchor (real usage.prompt_tokens + delta estimate of what was appended since)
identified the priced transcript by id() of the last message, so it was None on EVERY
gateway turn (history is re-read from the DB each turn) and in every fresh process
(--resume, desktop per-turn serve). Those are exactly the surfaces where the bytes/4
estimate then fired local compression against payloads the provider priced far under
threshold (#99421, #104462).

- agent/usage_anchor.py owns the anchor: content fingerprint instead of id(), persisted on
  the session row (model_config._usage_anchor) via set_usage_anchor(), restored on the first
  resumed turn while the durable transcript still matches, cleared with the row on
  compaction / codex-native rewrite / session reset.
- Callers repointed from model_metadata (the compat table follows).

Design and persistence slot from #99585 by @686f6c61; re-authored against the Sep 2026
layout (the branch predates the model_metadata / agent_init split).
2026-09-06 13:21:17 -07:00
liuhao1024
a9e56c048a fix(compression): anchor codex app-server preflight on reported usage
The codex_app_server runtime bypasses the conversation loop, so the
usage-anchored context accounting captured there never ran: agent._usage_anchor
stayed None forever. Every preflight estimate therefore fell back to the rough
mirror-transcript heuristic, which is deliberately never compacted on this
runtime (_record_codex_app_server_compaction preserves the mirror), so it grows
monotonically while the real thread may be tiny or freshly compacted. With
compression.codex_app_server_auto=hermes that estimate alone tripped the
threshold and fired thread/compact/start on nearly every turn of a long-lived
session (#100381).

Mirror the main loop's post-response capture: _record_codex_app_server_usage
now snapshots the reported thread usage into agent._usage_anchor (base prompt
+ completion exactly as the provider counted them, with estimation confined to
messages appended since). A usage-less turn keeps the previous anchor, and the
post-compaction invalidation site is unchanged.
2026-09-06 13:21:17 -07:00
ethernet
fe40130d62 test(termux): keep durable runtime checks and verify the prebuilt TUI
Remove the one-run linkage diagnostic and its expiring artifact dependency. The production wheel import gate and real ELF regression remain. Check the TUI in isolated CI and assert pm exports by behavior, not reloaded function identity.
2026-09-06 16:19:59 -04:00
Teknium
1cd9106eff chore: map contributor email for @Joeywrz 2026-09-06 13:18:19 -07:00
Teknium
0d8a1575c5 refactor(mcp): keep the passive status RPC, drop the SDK contract and reason codes
mcp.servers.status now rides the shared _mcp_rpc decorator (profile scope, 4064,
5024 with the real message) instead of a hand-rolled try/finally with a blanket
except. Drop the _MCPConnectErrorText str subclass and reason taxonomy: the
existing status/error fields already carry the state, and a whitelist on the RPC
keeps error text out of the wire. The Desktop connections.health contribution
contract is held back until its consumer plugin is public. Tests trimmed to the
scope invariants (per-profile runtime visibility, scoped shutdown clears only its
own status, launch runtime never leaks into another profile).
2026-09-06 13:18:19 -07:00
Joey
a6699d60f4 feat(mcp): expose profile-scoped cached connection health 2026-09-06 13:18:19 -07:00
ethernet
dd4bcda813 fix(termux): rebuild cached runtime notices with their libraries
A changed runtime table must discard all prior package-owned files, including copyright symlinks. Also isolate updater tests from previously collected native modules and exercise the post-merge deferral ordering instead of inspecting retired source symbols.
2026-09-06 16:10:09 -04:00
Teknium
b167e81750 fix: legacy Bot Mode section in SOUL.md no longer taxes every session or shadows the live roster
Older desktop builds appended a frozen "## Messaging other agents" section (roster
included) to SOUL.md. Since the server started injecting the live section into Bot Chat
sessions, that copy did two wrong things: every CLI/TUI/messenger session paid ~600 tok
for a bot-only protocol, and in Bot Chat itself the probe went silent when SOUL carried
the heading, so bots saw the stale roster instead of the live one.

- load_soul_md strips the legacy section at read time (covers un-migrated profiles and
  the ambient-home edge cases the same way the SOUL isolation fix does)
- bot_mode_probe drops the SOUL-carries-heading suppression; a SOUL-era stored Bot Chat
  prompt now counts as legacy and is upgraded once (stamped, so it cannot loop)
- config migration v41 rewrites SOUL.md across the default + every profile once
2026-09-06 13:08:31 -07:00
Teknium
dec1e87833 Merge pull request #103553 from NousResearch/fix/goal-set-no-repaste
fix(goal): /goal <text> kicks with a pointer when the last user message already carries the goal (11-call replay turn in one run)
2026-09-06 13:03:01 -07:00
ethernet
d2c14f4bec merge: reconcile upstream bounded search with literal patterns
Merge d86627a7f3 into pm-clean. Keep the shared bounded ripgrep transport and preserve translate_path=False for probe patterns. Targeted canonical search tests: 19 passed, 3 POSIX-only skips on Windows. Full integrated CI has not been run for this merge.
2026-09-06 16:00:55 -04:00
Teknium
7551168262 ci: redispatch after zero-job run on the main merge 2026-09-06 12:57:21 -07:00
ethernet
f73ae58f5f test(termux): install from the signed APT repository before publishing 2026-09-06 15:56:35 -04:00
ethernet
e9dfe6f7d8 fix(pm): retain chained library aliases on no-symlink hosts
Resolve deferred relative file links until no further alias can be materialized. Keep containment checks and leave unresolved cross-package copyright links alone.
2026-09-06 15:49:41 -04:00
Teknium
6b2d4faf36 Merge pull request #103549 from NousResearch/fix/async-batch-task-failure-notice
feat(delegation): a failed child of a running detached fan-out is surfaced immediately, as a non-durable notice (66 min dead wave; review-found final-result loss closed)
2026-09-06 12:44:28 -07:00
ethernet
203c0a96aa fix(termux): carry the Vulkan loader and finish runtime diagnostics
The clean non-root install passed native imports but ffmpeg needed libvulkan.so. Bundle Termux's real generic loader and exercise media conversion in the bare runtime. Restore doctor imports, pm-venv recognition, and current diagnostics seams.
2026-09-06 15:41:56 -04:00
kshitijk4poor
8b9a9f8c23 refactor(desktop): one sessionBucketId for the filter rule and the overview overlay; shorter resolver header 2026-09-07 01:09:00 +05:30
kshitijk4poor
758e33c28c chore: map contributor emails for the #96269/#102465 salvage 2026-09-07 01:09:00 +05:30
kshitijk4poor
88d0a740c9 refactor(desktop): one live-filter resolver; keep the Home row rule from #102465
#96269 and #102465 fixed the same blank-sidebar symptom with the same
"narrow the persisted filter to ids the live tree names" mechanism.
resolveLiveProjectFilter (the earlier PR) is the single resolver; the
duplicate sanitizeProjectFilter is removed. What #102465 adds beyond it stays:
detached rows file under NO_PROJECT_ID, so filtering to Home keeps Home's rows.
2026-09-07 01:09:00 +05:30
finn763
28c508cce0 fix(desktop): restore sidebar sessions Closes #97762 2026-09-07 01:09:00 +05:30
liuhao1024
fd54282678 fix(desktop): a cross-profile or stale project filter no longer empties the sidebar (#96246)
The sidebar's persisted project filter is a membership whitelist over tree node
ids. Ids that the active profile's tree does not resolve (picked in another
profile, or left over after a project was deleted / an update rebuilt the tree)
used to filter every row out — headers rendered, zero sessions, until Local
Storage was cleared. Narrow the persisted filter to ids the live tree resolves;
dead ids are inert, never fatal. Memo-only, never written back.

Salvage of #96269 (three commits: fix + two lint passes, folded).
2026-09-07 01:09:00 +05:30
Teknium
c6bf8fd95c chore: retrigger CI (zero-job dispatch failure, auto-heal) 2026-09-06 12:37:59 -07:00
ethernet
ec59854d2f docs(pm): record verified closeout and remaining acceptance 2026-09-06 15:36:54 -04:00
kshitijk4poor
d86627a7f3 docs(desktop): trim the ssh token comments to the WHY 2026-09-07 00:58:49 +05:30
joaomarcos
690bd8af09 fix(desktop): keep the ssh session token in the v2 connection registry (#103795)
`persistSshConnectionToken()` writes the per-serve session token adopted for
an SSH connection onto its v2 registry entry, but the registry never read it
back: `normalizeRegistry()` rebuilt an `kind === 'ssh'` entry from
`normalizeSshConfig()` alone, which describes only the DIAL (host, user, port,
keyPath, remoteHermesPath, remoteProfile). The sibling remote/cloud branch
preserves `entry.token`; the ssh branch did not.

The token therefore survived only in the mtime-keyed in-process cache. On the
next cold read — an app restart, or any process that re-parses
connections.json — it was silently dropped, so `resolveRemoteBackend()`
decrypted an empty value and dialed with `reuseToken = ''`. That fails the
`Boolean(reuseToken)` clause of remote-lifecycle's `reusable` gate, so a
HEALTHY owned backend was classified not-reusable, reaped by `cleanupStale()`
and respawned on a new port behind a new tunnel — while the renderer kept
dialing its cached `wsUrl?token=` at the old credential and got 403 forever.

`normalizeConnectionInput()` had the same omission: `saveRegistryConnection()`
resolves the surviving envelope via `resolvePersistedRemoteToken()` and passes
it in, but the ssh branch dropped it, so a plain label rename wiped the live
backend's reuse credential and re-armed the same loop.

Both branches now carry the token exactly the way the remote branch does.
There is no auth-mode choice on an ssh entry that could invalidate the
envelope, so no drop condition is needed.

Fixes #103795
2026-09-07 00:58:49 +05:30
kshitijk4poor
df4c786279 docs(gateway): say WHY the replay sidecar survives a timestamp-only render 2026-09-07 00:53:06 +05:30