Commit Graph
3325 Commits
Author SHA1 Message Date
6ce4f52972 fix(channels): repair Discord & Telegram messaging end-to-end (#3712, #3763) (#3794)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 12:17:21 -07:00
9198444ffd fix(agent): halt on first permanent inference failure to stop agent cascade (#3104) (#3779)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 12:16:59 -07:00
333d1bb282 fix(agent): actionable error when system prompt exceeds local model context (TAURI-RUST-6V0) (#3771)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 12:16:24 -07:00
9dc2127710 fix(inference): persist Gemini thought_signature on tool-call history (TAURI-RUST-4PK/4PJ) (#3770)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 12:16:05 -07:00
b065e1728a fix(voice): classify lapsed-session TTS-reply 401s as session-expiry (TAURI-RUST-8X1) (#3750)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 12:15:43 -07:00
48eca1505e feat(shell): add hide_window option to suppress Windows console window (#3747)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 12:14:36 -07:00
Steven EnamakelandGitHub 751267392d chore(ci): prune remaining superseded/redundant GitHub Actions workflows (#3935) 2026-06-22 11:51:24 -07:00
6d0f67a09a fix: gate local voice provider activation until installed (#3861)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 11:41:49 -07:00
f7a71fea6b fix(chat): render GFM markdown tables in agent output (#3857)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 11:40:47 -07:00
Steven EnamakelandGitHub 04175ad78c chore(ci): prune superseded/redundant GitHub Actions workflows (#3934) 2026-06-22 11:36:30 -07:00
Darshan PoudelandGitHub fc02e47505 fix: parse FILE markers in attachment fallback (#3795) 2026-06-22 11:23:29 -07:00
obchainandGitHub fd1b4e6f3f feat(skills): retract uninstalled skills from mid-session catalogue (#3745) 2026-06-22 23:47:30 +05:30
ce7e61f1f3 fix(inference): classify OpenAI OAuth token_expired 401 as user-state, demote from Sentry (#3801) (#3803)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 11:17:01 -07:00
oxoxDevandGitHub 9cbf023750 fix(memory): stop SQLITE_FULL flood from mem_tree_jobs worker (#3909) (#3911) 2026-06-22 11:09:52 -07:00
676c3c04cb fix(routines): stop next-run label showing "in 0 hours" near an hour (#3758)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 11:09:10 -07:00
4347e579c1 fix(inference): classify list_models 404 at source + actionable hint (TAURI-RUST-8X3) (#3769)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 11:08:55 -07:00
8fca02a22f fix(integrations): drive re-login on session-JWT 401 + demote tool-execute noise (TAURI-RUST-84E) (#3749)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 11:08:24 -07:00
Steven EnamakelandGitHub 4a65691cea [codex] add harness cache audit script (#3895) 2026-06-22 10:54:56 -07:00
f4a090dd91 fix(appimage): sanitize build-machine RPATHs + guard libxdo bundling (#3224) (#3776)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 10:16:09 -07:00
801a5bbf4f fix(subagent): resolve truncated near-miss Composio tool slugs (#3152) (#3774)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 10:15:58 -07:00
c09b118cbe fix(app): surgical broken-pipe stderr panic guard (TAURI-RUST-F) (#3772)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 10:15:24 -07:00
bd3e3eab00 fix(agentworld): explain missing DM key bundle (#3919)
Co-authored-by: MackJack023 <141124084+MackJack023@users.noreply.github.com>
2026-06-22 10:15:06 -07:00
oxoxDevandGitHub bc49ef3e60 fix(cron): stop cron billing-state Sentry floods — 402 credits + 400 budget (TAURI-RUST-514 / -BMW) (#3913) 2026-06-22 10:14:19 -07:00
500822300c fix(skill-registry): resolve community skill downloads via sourceUrl (#3741) (#3844)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 10:12:21 -07:00
1545d4b297 fix(ptt): allowlist PTT hotkey + overlay commands (#3724) (#3842)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 10:11:58 -07:00
56f9dac91b feat: add in-app feedback board (#3834)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 10:11:34 -07:00
0f853748d7 feat(briefing): extend 24h task-window to Todoist; fix stale Todoist slugs (#3921) (#3923)
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 10:11:04 -07:00
oxoxDevandGitHub e407796582 fix(settings): call registered openhuman.tool_registry_diagnostics RPC (#3917) (#3930) 2026-06-22 10:10:24 -07:00
oxoxDevandGitHub ace295aaf6 fix(agentbox): call core via openhuman.agentbox_status (#3914) (#3928) 2026-06-22 10:09:56 -07:00
sanil-23andGitHub e95c892dba refactor(memory_sync): convert Slack to the generic sync orchestrator (#3924) 2026-06-22 10:09:34 -07:00
HüsamandGitHub 43e2a01f88 fix(settings): call canonical RPC name in Tool Policy diagnostics panel (#3927) 2026-06-22 10:08:53 -07:00
HüsamandGitHub c39f18d9df fix(settings): call openhuman.agentbox_status from the AgentBox panel (#3914) (#3926) 2026-06-22 10:07:52 -07:00
3e13767096 fix(chat): make approval prompt opaque (#3790)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 22:02:32 +05:30
f61e416aae feat(subconscious): event-driven trigger pipeline + orchestrator (#3650)
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 19:36:09 +05:30
0792550078 feat(agent): give the agent a brand voice when OpenHuman is criticized (#3640)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 19:22:48 +05:30
1dc7f68ea0 perf(memory_tree): HashSet for order-irrelevant dedup in chunk scoring (#3638)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 19:22:41 +05:30
3d0b045601 fix(memory): restore query-sensitive semantic recall (#3608)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 19:22:33 +05:30
sanil-23andGitHub e1f5fd7c4a fix(chat): keep morning-brief heading+body in one chat bubble (#3807) (#3851) 2026-06-22 19:16:22 +05:30
obchainandGitHub 44ff81642b i18n(sync-audit): localize the memory sync-audit panel (#3706) 2026-06-22 19:15:57 +05:30
62fb5beab1 perf(memory): drop O(n^2) position scan in episodic relevance (#3782)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 19:10:33 +05:30
b0fa43c89d fix(auth): handle legacy /auth web callback route (#3800)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 19:10:10 +05:30
68c8c5ce2d perf(subconscious): bound-concurrent calendar connection fan-out (#3472)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 18:52:48 +05:30
c835ffd1dd perf(github): bound-concurrent batch summarise, keep ingest serial (#3434)
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 18:52:13 +05:30
2e254262e9 perf(memory_tree): concurrently seal document-subtree sibling batches (#3416)
Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 18:31:54 +05:30
490de0cd17 fix(chat): drop "local provider" misdirect from empty-response copy + log empty 2xx streams (#3335) (#3415)
## Summary

- Replace the misleading **"Try a different model or check your local provider in Settings → AI → LLM"** copy on the empty-response classifier — that sent **Managed-route users toward a remedy that doesn't exist for them**, because there is no local provider on the Managed route. The new copy explicitly names the credits / billing remedy alongside the model / provider-config remedies (chat surface), and a tighter ≤120-char form for the cron notification drawer.
- Add a forensic `warn`-level log in `stream_native_chat` for the exact upstream shape that triggers `AgentError::EmptyProviderResponse` — a streaming chat call that returns **HTTP 2xx with zero text, zero thinking, and zero tool calls**. Captures `elapsed_ms`, `sse_chunks_parsed`, `raw_bytes_received`, `has_usage`, `has_openhuman_meta` so production data can disambiguate the three plausible upstream root causes (credit exhaustion served as 200 + empty body, upstream provider stall, real degenerate model output).
- Strictly additive — no behavioural change to request paths, no new Sentry suppression. The diagnostic log fires only on the empty-2xx case (otherwise the existing aggregated log carries the same fields at `info`).

## Problem

Issue #3335 (`iamrhn`): on Managed settings, every chat turn surfaces:

> *"The model returned an empty response. Try a different model or check your local provider in Settings → AI → LLM."*

The "local provider" remedy is nonsensical for Managed users. The Sentry data confirms this is real and broad:

- **TAURI-RUST-4JX**: 2,633 events, 55 distinct clients in 14 days. Releases include current `0.57.13` (PR #2790's Sentry suppression silenced the events but the underlying user-visible bug remains).
- Latest event breadcrumbs (Managed route, `reasoning-v1`, web channel):

  ```
  [provider:OpenHuman] outbound chat/completions -> https://api.tinyhumans.ai/openai/v1/chat/completions
  [stream]   OpenHuman POST … (stream=true, tools=21)
  …~7 s gap, no [stream] error breadcrumb, no [llm_provider] api_error breadcrumb…
  [agent]    provider responded — parsed tool_calls=0 text_chars=0
  [agent_loop] provider returned an empty final response (i=1, no text, no tool calls) — surfacing as error
  ```

  HTTP status was 2xx (no `streaming API error` line), so none of the existing classifiers (`is_budget_exhausted_http_400`, `is_provider_access_policy_denied_http_403`, …) at `compatible.rs:1028-1060` fire. The streaming aggregator builds a `ChatResponse` with `content: None`, the agent loop returns `AgentError::EmptyProviderResponse`, and the chat surface renders the wrong-remediation copy.

This is exactly the shape #3386 (team-filed) identifies as path **(b)**: the OpenHuman managed backend returns 200 + empty SSE under credit exhaustion / upstream stall instead of a typed 400 + `Insufficient budget`. The deeper fix lives in `tinyhumansai/backend`; this PR addresses the **two client-side wins that don't require the server change**.

## Solution

**(1) Copy fix — chat surface (`web_errors.rs::classify_inference_error` empty_response arm).** Replace the `"Try a different model or check your local provider"` text with a three-remedy form that's accurate for **all** providers: *"This usually means your inference credits are exhausted (Settings → Billing), the upstream model is temporarily unhealthy, or your provider configuration is rejecting the request (Settings → AI → LLM). Try one of those, or pick a different model."* New regression test `classify_inference_error_empty_response_copy_names_billing_remedy_and_drops_local_provider_misdirect` locks in: contains `Settings → Billing`, contains `Settings → AI → LLM`, contains `different model`, does NOT contain `local provider`, and `provider` stays `None`. Existing test `classify_inference_error_empty_response_is_actionable_and_retryable` continues to pass.

**(2) Copy fix — cron drawer (`cron/scheduler.rs::agent_error_to_user_message`).** Shorter form for the drawer's ≤120-char convention: *"Empty model response. Out of credits (Settings → Billing) or try a different model in Settings → AI → LLM."* New regression test `agent_error_to_user_message_classifies_empty_provider_response_for_3335` mirrors the chat-side assertions; `EmptyProviderResponse` is added to the existing `agent_error_to_user_message_canned_strings_are_short` variants list to lock in the ≤120-char contract (was previously absent — fit incidentally, but nothing enforced it).

**(3) Diagnostic log — `compatible.rs::stream_native_chat`.** Right after the existing aggregated `info` log, emit a `warn` when `text_accum.is_empty() && thinking_accum.is_empty() && tool_call_count == 0`:

```
[stream] {name} empty 2xx stream — model={..} elapsed_ms={..} sse_chunks={..} raw_bytes={..} has_usage={..} has_openhuman_meta={..}
```

`stream_started_at: Instant`, `sse_chunks_parsed: usize`, and `raw_bytes_received: usize` are added as append-only counters (never read by the request path). The signal disambiguates:

- `elapsed_ms` small + `sse_chunks=0` + `raw_bytes` small → backend closed the SSE near-immediately (credit reject or auth)
- `elapsed_ms` large + `sse_chunks=0` + `raw_bytes=0` → upstream stall / timeout
- `sse_chunks>0` + `has_usage=true` + accumulators empty → backend streamed metadata-only chunks (tokens counted, no content delivered)

**(4) Deliberately deferred — the in-session budget correlator from #3386.** `EmptyProviderResponse`'s flattened Display carries no `" API error"` infix for `extract_provider_name` to anchor on, so the classifier here cannot tell which provider was used without plumbing the typed `provider: Option<String>` through the AgentError. That plumbing affects ~10 string-match test/observability sites and balloons the scope. The diagnostic log is the cheapest path to the production data that decides whether the plumbing is worth doing — once we have evidence on which path is dominant (200+empty under credit exhaustion vs. upstream stall vs. true degenerate output), the next iteration of the empty-response arm can be provider-aware.

## Submission Checklist

> If a section does not apply to this change, mark the item as `N/A` with a one-line reason. Do not delete items.

- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — three new tests: `classify_inference_error_empty_response_copy_names_billing_remedy_and_drops_local_provider_misdirect` (web chat copy), `agent_error_to_user_message_classifies_empty_provider_response_for_3335` (cron drawer copy), plus `EmptyProviderResponse` added to `agent_error_to_user_message_canned_strings_are_short` variants (locks in the ≤120-char contract that was previously unenforced).
- [x] **Diff coverage ≥ 80%** — every new/changed line in `web_errors.rs` and `cron/scheduler.rs` is exercised by the three new regression tests; the `compatible.rs` diagnostic log is observability-only (no behavioural branching) and covered by the existing streaming-chat test surface that drives it. Run `pnpm test:rust` locally to verify.
- [x] Coverage matrix updated — `N/A: behaviour-only change` (error-message copy + observability log, no new feature ID).
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — `N/A: behaviour-only change, no matrix rows touched`.
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) — `N/A: tests are pure unit-level over the classifier and the AgentError variant; no provider HTTP exercised`.
- [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — `N/A: error-copy + log only, no UI flow or release-cut surface affected`.
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section.

## Impact

- **Desktop (chat surface)**: Managed-route users hitting empty-response failures now see an actionable, non-misleading message that names `Settings → Billing` as the most likely fix (per Sentry / #3386 evidence) without losing the existing `Settings → AI → LLM` and model-switch remedies. Self-hosted users see the same three-remedy framing — strictly more accurate than the prior "local provider" claim for users on cloud providers.
- **Desktop (cron notifications)**: Same behavioural change, shorter copy to fit the ≤120-char drawer-render budget. Now enforced by the existing length test.
- **Observability**: Net +1 `warn` log per streaming chat turn that returns 2xx-with-empty-body. This is the failure case being investigated; non-empty streams are unaffected. Lands in Sentry breadcrumbs even after `AgentError::skips_sentry()` (#2790) silences the parent event, unblocking the data needed to decide whether the in-session budget correlator from #3386 is the right next move or whether the fix has to be server-side.
- **Performance / security**: No request-path behaviour change. The added counters are stack-local `usize` increments. The diagnostic log redacts nothing new — provider name, model name, and counts are all already in the existing aggregated `info` log; only the byte total and elapsed ms are net-new and both are content-free.
- **Migration / compatibility**: None. Pure string + observability change.

## Related

- Closes: #3335
- Related: #3386 (the team-filed deep-dive that this PR addresses without requiring the per-session budget correlator), #3104 (cascade-error reports likely sharing the same empty-stream root cause), #2790 (the Sentry suppression that silenced TAURI-RUST-4JX without fixing the user-visible bug), #3199 (the empty-response arm being modified), #3121 (the budget-exhausted copy whose remedy this copy now points users toward), #3092 (closed parent issue for the chat-error cluster).
- Follow-up PR(s)/TODOs: Once the diagnostic log produces 24–48 h of production data, decide between (a) opening a backend issue against `tinyhumansai/backend` to start returning `400 + Insufficient budget` on streaming under credit exhaustion (the right server-side fix), and (b) plumbing `provider: Option<String>` through `AgentError::EmptyProviderResponse` so the classifier can be provider-aware (the #3386 in-session correlator approach).

---

## AI Authored PR Metadata (required for Codex/Linear PRs)

> Keep this section for AI-authored PRs. For human-only PRs, mark each field `N/A`.

### Linear Issue

- Key: N/A — GitHub issue #3335, not Linear-tracked.
- URL: N/A

### Commit & Branch

- Branch: `fix/3335-managed-empty-response-diagnostic-and-copy`
- Commit SHA: `7064cbfee`

### Validation Run

- [x] `pnpm --filter openhuman-app format:check` — `N/A: no frontend / TS files changed`
- [x] `pnpm typecheck` — `N/A: no frontend / TS files changed`
- [x] Focused tests: `cargo test --lib empty_response` (10 pass), `cargo test --lib empty_provider` (5 pass), `cargo test --lib cron::scheduler::tests::agent_error` (11 pass), `cargo test --lib compatible::tests` (153 pass).
- [x] Rust fmt/check (if changed): `cargo fmt --manifest-path Cargo.toml` + `cargo check --manifest-path Cargo.toml --lib` — both clean (only pre-existing unrelated warnings).
- [x] Tauri fmt/check (if changed): `N/A: no app/src-tauri files changed`

### Validation Blocked

- `command:` N/A
- `error:` N/A
- `impact:` N/A

### Behavior Changes

- Intended behavior change: User-facing error copy for `AgentError::EmptyProviderResponse` no longer claims a "local provider" exists; new copy names `Settings → Billing` (credits) alongside `Settings → AI → LLM` (provider config) and the model-switch fallback.
- User-visible effect: Managed-route users who hit empty-response failures now receive remedy text that matches the most likely actual cause (credit exhaustion, per #3386 evidence). Self-hosted users see the same three-remedy framing, which remains accurate for their configurations.

### Parity Contract

- Legacy behavior preserved: `AgentError::EmptyProviderResponse` Display, `classify_inference_error` error_type / source / retryable / provider fields, `agent_error_to_user_message` dispatch matrix, the `Settings → AI → LLM` deep-link reference. Existing test `classify_inference_error_empty_response_is_actionable_and_retryable` continues to pass unchanged.
- Guard/fallback/dispatch parity checks: The empty-response arm in `web_errors.rs` keeps the same `error_type: "empty_response"`, `source: "agent_loop"`, `retryable: true`, `retry_after_ms: None`, `provider: None`, `fallback_available: None` — only the message string changes. The cron `agent_error_to_user_message` dispatch matrix is unchanged; only the `EmptyProviderResponse` branch's returned string changes.

### Duplicate / Superseded PR Handling

- Duplicate PR(s): None — no other open PR references #3335.
- Canonical PR: This one.
- Resolution: N/A (no prior PR to supersede).


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

## Release Notes

* **Bug Fixes**
  * Improved error messaging when model returns an empty response, now guiding users to check inference credits (Settings → Billing), try a different model, or verify LLM provider configuration (Settings → AI → LLM).

* **Improvements**
  * Added enhanced diagnostic logging for empty response scenarios to better support troubleshooting.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Closes #3335

Co-authored-by: M3gA-Mind <megamind@mahadao.com>
2026-06-22 18:25:06 +05:30
0db261dcc2 feat(inference): make compatible-provider HTTP timeouts configurable (#3856) (#3864)
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 17:29:28 +05:30
b8b69da776 fix(agentworld): sort Tiny Place feed newest first (#3868)
Co-authored-by: MackJack023 <141124084+MackJack023@users.noreply.github.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 17:29:23 +05:30
bc59bb9307 i18n(ai-routing): localize workload labels, descriptions, and hints (#3870)
Co-authored-by: OpenHuman <package@openhuman.org>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
2026-06-22 17:28:24 +05:30
Steven EnamakelandGitHub c3d86a4ea7 fix(chat): decouple provider webviews from thread routes (#3896) 2026-06-22 17:24:32 +05:30
sanil-23andGitHub d4db739b22 fix(billing): gate credits per selected chat-mode tier (BYO) (#3767) (#3775) 2026-06-22 16:08:46 +05:30