feat(skills): add youtube learnings - home-ai-lab, ai-game-studio, price-watch - #2
Merged
Conversation
(cherry picked from commit 1fded70)
(cherry picked from commit 97fabc2)
(cherry picked from commit a2bbe56)
(cherry picked from commit a4188a3)
…escendant _session_latest_descendant fetched EVERY sessions row and built the parent->children tree in Python on each call. Replace with a recursive CTE that loads only the target session's descendant branch. Hand-applied from PR NousResearch#39140 (the schema-init cache and Rust PTY bridge parts of that PR are intentionally NOT salvaged here); main's function signature gained a db parameter since the PR was cut. (cherry picked from commit 8ed5e54)
Flip the handler from async def to sync def so FastAPI executes it in its threadpool: the SessionDB open + list_sessions_rich query no longer block the single uvicorn event loop. Residual hunk from PR NousResearch#53966 — that PR's get_profiles_sessions flip already landed via NousResearch#54523/1bb7b59c5, and its get_status offload is superseded by NousResearch#58238's read_only + timeout variant in this branch. (cherry picked from commit 414c12a)
The NousResearch#39140 CTE used UNION ALL, which recurses forever if a corrupted parent chain loops (a -> b -> a) — reproduced: query never returns. The old Python walk was cycle-safe via a seen-set. UNION dedups the working set and terminates. Regression test added and mutation-verified (UNION ALL hangs the test, UNION passes).
Review finding: SessionDB(read_only=True) requires the DB file to exist (its documented contract says callers guard on db_path.exists()); on a fresh install every /api/status poll paid an OperationalError until the first session was written. Short-circuit to 0 when state.db is absent. Tests: fresh-install guard + existing read_only test adjusted.
…ests get_status now probes via get_running_pid_cached() (NousResearch#53511 salvage); these tests were added on main after that PR was cut and still patched web_server.get_running_pid, so their fakes were bypassed and CI slice 5/8 failed. Patch the name the handler actually calls.
The session messages endpoint returned ALL messages in a single response with no limit/offset. Sessions with 500+ messages produced 1.2-1.6 MB JSON payloads, causing GIL starvation and WebSocket timeouts on the Desktop client (NousResearch#60155). Add optional limit/offset query params to both the API endpoint and SessionDB.get_messages(). Limit clamped to 500 max per page. Response now includes a pagination object with limit/offset/returned count. Backward compatible: callers that omit limit get the old behavior (all messages). Closes NousResearch#60155 (cherry picked from commit d58396b)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 1e70eaa)
…ist queries list_sessions_rich and _get_session_rich_row previously used SELECT s.*, pulling the system_prompt TEXT blob on every row even for dashboard and picker callers that never display it. On large databases this blob routinely runs to tens of kilobytes per session, causing unnecessary B-tree I/O. Add compact_rows=False param to both functions. When True, an explicit column list omitting system_prompt is substituted for s.* in both the simple and the recursive-CTE (order_by_last_active) query paths. Default is False so all existing callers are unaffected. Update dashboard and session-picker callers in web_server.py and tui_gateway/server.py to pass compact_rows=True. Add seven regression tests covering: omission of system_prompt, presence of all metadata fields, both query paths, _get_session_rich_row, and backward-compat default. (cherry picked from commit c470cbd)
…sResearch#47437 - derive the compact_rows projection from SCHEMA_SQL (parse once, cache) instead of a hardcoded column list: the original NousResearch#47437 list was cut against a June schema and silently dropped session_key/chat_id/chat_type/ thread_id/display_name/origin_json/expiry_finalized/git_branch/ git_repo_root/compression_failure_* — including desktop sidebar fields. Schema-derived means declaratively reconciled new columns are included automatically; only system_prompt is excluded. - guard test pinning the schema<->projection contract (mutation-verified: dropping a column from the projection fails it) - wire compact_rows=(not full) into /api/sessions and /api/profiles/sessions so the SQL projection pairs with the API-level field strip (?full=1 still returns complete rows end-to-end) - pass compact_rows at the remaining hot list callers: /api/status active count, _session_latest_descendant fallback, /api/sessions/stats by-source - thread compact_rows through the compression-tip projection (_get_session_rich_row) so projected tips can't reintroduce the blob - add pagination tests for get_messages (NousResearch#60347 shipped none): paging order, offset-past-end, active-flag interaction; add tip-projection compact test - AUTHOR_MAP entries for mahdiwafy + CodeForgeNet (plain emails)
Review finding: get_messages(offset=N) with no limit dropped the OFFSET entirely. SQLite requires a LIMIT clause for OFFSET, so emit LIMIT -1 (unbounded) when only offset is given. Regression test added.
tui_gateway session.list/most_recent now pass compact_rows=True (NousResearch#47437 salvage); the keyword-only fake signatures in test_tui_gateway_server.py rejected the new kwarg and CI slice 6/8 failed with TypeError. Other list_sessions_rich fakes use **kwargs and are unaffected.
Rebase reconciliation with NousResearch#60884: _count_status_active_sessions (from NousResearch#58238) now passes compact_rows=True (this branch's NousResearch#47437 projection), so the fake asserts both.
…t httpx.ResponseNotRead When an API error carries an httpx.Response whose body was consumed via iter_bytes() during streaming error handling (e.g. GeminiAPIError from agent/gemini_native_adapter.py), accessing .text raises httpx.ResponseNotRead. The secondary exception replaced the real, already-computed provider error (429 free-tier quota guidance) with the generic 'Attempted to access streaming response content' message on every turn. Guard the .text access so it degrades to an empty snippet and falls through to the str(error) fallback, which carries the full original message. Mirrors the existing guards in agent/error_classifier.py::_extract_error_body() and agent/gemini_native_adapter.py::gemini_http_error(). Fixes NousResearch#59769 Salvaged from PR NousResearch#59868 (guard + regression test); the unrelated desktop Ctrl-C fix bundled in that PR was intentionally dropped and is triaged separately.
Gateway froze the fallback chain at process start while cron reloads it per job, so a chain configured after hermes gateway was running never reached messaging sessions. Refresh from disk on agent create and when reusing a cached agent. Fixes NousResearch#60955. (cherry picked from commit b64e715)
Pin reload + cached-agent apply helpers for NousResearch#60955 so a mid-uptime fallback chain change reaches messaging sessions without a restart. (cherry picked from commit fafb341)
Follow-ups on the NousResearch#60987 salvage (review pass): - _refresh_fallback_model: keep last known-good chain on transient config.yaml read/parse failure (user mid-edit, torn write) — only a successful read that lacks the key clears the chain. Previously a refresh error wiped a cached agent's working fallback for the turn. - Move the cached-agent refresh+apply OUTSIDE the agent-cache lock: config.yaml read is disk I/O and the idle-sweep watcher contends on that lock (same reasoning as NousResearch#52197). Per-session turn serialization keeps the post-lock apply safe. - _apply_fallback_chain_to_agent: clear _unavailable_fallback_keys when chain content actually changes, so an entry re-configured mid-uptime (e.g. credentials added) is retried instead of staying suppressed for the cached agent's lifetime; no-op refreshes keep the memo. - Tests: cwd-independent source pin (Path(__file__) anchor), pin the reuse-path apply call, + regression tests for last-known-good, memo clear-on-change, memo keep-on-unchanged (mutation-verified).
Fixes NousResearch#3356 Build the skills snapshot manifest in one directory walk, avoid importing gateway session context during CLI prompt startup, and reuse direct platform-list matching for snapshot entries. (cherry picked from commit 1a64c2e)
(cherry picked from commit 3e82a86)
Deep review of the cherry-picked NousResearch#16454 found the ad-hoc flush thread raced new_session()'s inline on_session_switch(reset=True): memory providers key off internal _session_id state (MemoryManager.on_session_end takes no session id), so a late off-thread extraction ran against post-rotation bindings — misattributing the old transcript to the new session id, double-ingesting the old turn buffer (supermemory), or double-committing (openviking already async-finalizes in on_session_switch). Redesign: new MemoryManager.commit_session_boundary_async queues on_session_end + on_session_switch as ONE task on the manager's existing single-worker background executor (the same worker sync_all already uses). This preserves the strict end→switch ordering providers depend on, serializes against per-turn syncs FIFO, keeps /new non-blocking, and degrades to inline (pre-NousResearch#16454 behavior) when the executor is unavailable. No ad-hoc threads; no per-provider changes needed. The context-engine on_session_end half stays synchronous in _launch_session_boundary_memory_flush (cheap, must land before reset_session_state rebinds the engine). Exit durability: _run_cleanup calls the manager's existing flush_pending(timeout=10) barrier before shutdown, so '/new then quit' doesn't drop the queued extraction (shutdown_all's own drain is ~5s and cancels queued tasks). Bounded well inside the 30s exit watchdog. Tests: ordering invariant with slow (LLM-like) extraction, FIFO serialization vs sync_all, switch-fires-even-if-end-raises, no-provider no-op, CLI snapshot handoff + inline-switch fallback, sync engine boundary, cleanup flush_pending.
- Return the boundary snapshot from _launch_session_boundary_memory_flush as a local value instead of staging it on self._session_boundary_snapshot. The instance-attr handoff could leak (no memory manager configured) or mis-fire a stale snapshot on a later /new if an exception hit between staging and consumption. A local variable eliminates the class; the helper also returns None when no memory manager is configured so new_session takes the inline-switch path. - Drop the now-dead session_id kwarg from commit_memory_session: after the redesign no production caller passes it (gateway, TUI, compression all use the default), and speculative params are rejected per AGENTS.md. The explicit-old-session need is served by cli.py's direct engine call + commit_session_boundary_async. - Drop the dead providers snapshot in commit_session_boundary_async (only the emptiness check used it). - Tests updated accordingly (dead-kwarg test removed, snapshot assertion now covered by return-value contract). Phase-2 gates: 2a tests/cli 1048 passed + 6 memory files 137 passed; 2b programmatic live smoke 0.38ms non-blocking caller, end→switch→sync ordering verified; 2c structured 4-angle review — no Criticals, these warnings fixed.
The model often emits a follow-up batch of tool calls as its own assistant message with no prose or reasoning. On screen those rows look like one continuous run, but assistant-ui only groups tool calls within a single message, so the auto-scrolling tool window never triggered on them (e.g. two batches of two searches read as 2 + 2, never reaching the threshold). Coalesce each settled tool-only assistant message into the preceding assistant message in the render pipeline so its calls join that message's tool group. Render-only (never touches the $messages store) and settle-only (pending messages are skipped) so a live turn is never merged/un-merged mid-stream; merged results are cached by source identity so a stable turn yields stable objects with no re-render churn.
…ol-window-merge feat(desktop): group tool calls across text-less assistant messages
Keep empty-tail recovery scoped to the current stream segment and bound fallback flood retries. Preserve Telegram's server retry hint without blocking final delivery through a long cooldown.
…ions Copilot (api.githubcopilot.com/responses) binds replayed assistant codex_message_items ids to a specific backend "connection". Credential- pool rotation, a gateway restart, or routine load-balancer churn between turns all invalidate that binding, and Copilot rejects the stale id with HTTP 401 "input item ID does not belong to this connection" — even for short ids well under the NousResearch#27038 64-char length cap, since this is a connection-scope problem, not a length problem. Once a session captures one of these ids it is persisted and replayed forever, permanently bricking the session. Thread an is_github_responses flag from build_kwargs/convert_messages into _chat_messages_to_responses_input and drop the id unconditionally on that path, mirroring how reasoning items already strip id on replay. phase/status/content are still replayed so cache-relevant signal isn't lost — only the connection-scoped id is unsafe to reuse. Written to apply independently of the NousResearch#27038 length-cap fix so the two PRs don't block each other; they touch adjacent conditions in the same block and merge cleanly in either order. Fixes NousResearch#32716 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_CodexCompletionsAdapter (agent/auxiliary_client.py) is a second, independent producer of Codex Responses input — used by auxiliary calls (context compression, flush_memories, MoA aggregation, session_search) that route through CodexAuxiliaryClient instead of the main agent's ResponsesApiTransport.build_kwargs. It calls _chat_messages_to_responses_input() directly without is_github_responses, so the previous commit's fix didn't cover it: an auxiliary call made against a Copilot-backed session could still replay a connection-scoped codex_message_items id and hit the same HTTP 401. Detect the Copilot host from the adapter's own client.base_url (same check the adapter already does further down for prompt_cache_key opt-out) and pass is_github_responses through, closing the gap. Still NousResearch#32716. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Require literal booleans for backend-specific replay policy and pin non-default status and content preservation through both response paths.
Reapply the endpoint-aware preflight after request and execution middleware so no override can reintroduce a connection-scoped ID.
Exercise request and execution middleware replacements through the real conversation loop and assert the provider payload is sanitized.
… in fetch_models fetch_models() sends Authorization: Bearer <api_key> plus any default_headers (x-api-key etc.) via urllib.request.urlopen, and urllib's redirect handler forwards every header when following a 3xx — including to a different host. A catalog endpoint (or a compromised/misconfigured proxy in front of it) answering with a redirect to another origin therefore received the provider API key. Install an HTTPRedirectHandler that drops authorization, x-api-key, api-key, x-goog-api-key and cookie when the redirect target hostname differs from the original request, mirroring the pattern already used in skills/creative/comfyui/scripts/_common.py. Same-host redirects keep credentials so legitimate path-level redirects still work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…g credentials Review feedback: a same-host redirect to a different port can land on a different service, which must not inherit the provider API key. Compare (scheme, hostname, effective port) — with 80/443 defaults — instead of hostname alone, and add a two-server regression test for the same-host/different-port case. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ice-watch Distilled from: https://youtu.be/eHZ14afnDZ0 - home-ai-lab: local model discovery, MLX/Ollama loading, HF hub search - ai-game-studio: autonomous 3D game generation with Hermes as game director - price-watch: automated GPU/CPU price monitoring with Telegram alerts Also updates reasoning_effort to medium per video guidance.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
🚨 CRITICAL Supply Chain Risk DetectedThis PR contains a pattern that has been used in real supply chain attacks. A maintainer must review the flagged code carefully before merging. 🚨 CRITICAL: Install-hook file added or modifiedThese files can execute code during package installation or interpreter startup. Files: Scanner only fires on high-signal indicators: .pth files, base64+exec/eval combos, subprocess with encoded commands, or install-hook files. Low-signal warnings were removed intentionally — if you're seeing this comment, the finding is worth inspecting. |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Distilled from https://youtu.be/eHZ14afnDZ0 - Hermes Agent + ChatGPT 5.6 Setup & Use Cases.
Skills added
Config update
reasoning_effort: medium - per video guidance
Nexus artifacts
Source: https://youtu.be/eHZ14afnDZ0