mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
beba562df28f553d29948a3076e310ff5fcbcbad
2188
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
beba562df2 | fix(windows): make pnpm dev:app:win work behind TLS-inspecting proxies (#2449) | ||
|
|
7aa1bf1f88 | fix(agent): handle config rejection in streaming_chat path (#2346) | ||
|
|
d7b27b94fc |
fix(memory): run memory_tree on TRUNCATE journal instead of WAL (#2455)
Co-authored-by: sanil-23 <sanil@alphahuman.xyz> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
013381e880 |
fix(i18n): complete zh-CN translations for workspace, mascot, MCP Ser… (#2440)
Co-authored-by: agent:skill-master <skill-master@openclaw> |
||
|
|
e031d85ed2 | feat(agents): route prediction-market intents via new markets_agent specialist (#2427) (#2430) | ||
|
|
f51f140234 | fix(prompt-injection): rebalance detector + classify rejections as expected (#2429) | ||
|
|
208a64483b | fix(auth-profiles): tolerate legacy kind values on load (#2439) | ||
|
|
dcec5858e0 | fix(tauri): pre-flight every xdg-utils binary before register_all (#5V) (#2416) | ||
|
|
ec9708ac6f | fix(composio): surface Gmail scope errors as permissions (#2414) | ||
|
|
6137b67811 |
fix(memory_tree,sync_status,scripts): IMMEDIATE-tx ingest, reembed skip-persistence, sidecar-based sync-status accounting, Windows dev-script PATH (#2349)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: sanil-23 <sanil@alphahuman.xyz> |
||
|
|
7675c01c5c | fix(billing): hide budget-complete prompt for free zero-budget plans (#2300) | ||
|
|
bf6f25e64c | Update Product Hunt badges in README (#2425) | ||
|
|
d1f8305e20 | Update README.md (#2424) | ||
|
|
c204a53de2 | feat(mcp-clients): MCP client subsystem with Smithery registry + UI (#2409) | ||
|
|
6281aeaf42 | docs(linux): add arch linux setup and build instructions (#2343) | ||
|
|
48c4da4e2a |
fix(cron): classify agent job errors into actionable user messages (#2279) (#2340)
Co-authored-by: sanil-23 <sanil@alphahuman.xyz> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
3e2ba6648d |
fix(notifications): render <openhuman-link> tags in notification bodies (#2279) (#2339)
Co-authored-by: sanil-23 <sanil@alphahuman.xyz> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
c81fe3dbcc |
fix(auth): narrow SessionExpired to confirmed OpenHuman backend 401s
## Summary
- Narrows `is_session_expired_error` in `src/core/jsonrpc.rs` so `DomainEvent::SessionExpired` only fires for **confirmed OpenHuman session expiry**, not for downstream provider 401s.
- Adds `is_downstream_provider_auth_error` helper for diagnostic logging only (no session side-effects).
- Adds `'provider_auth'` error kind to `CoreRpcErrorKind` in `coreRpcClient.ts`; tightens `classifyRpcError` with the same HTTP-method-prefix logic.
- Fixes Discord card-click logout (issue #2285) as a direct consequence.
## Root Cause
`is_session_expired_error` used a loose `"401 + unauthorized"` string match. Discord bot-token failures arrive as `"Discord API error: Discord list guilds failed (401): Unauthorized"` — which contains both "401" and "unauthorized" — causing the full user session to be cleared on every Discord card interaction.
## Fix
OpenHuman backend errors (from `authed_json` in `src/api/rest.rs`) always use the format `"{HTTP_METHOD} /path failed (401 Unauthorized): {body}"`. Provider errors start with the provider name. The fix keeps the `"401 + unauthorized"` branch only when the message starts with an HTTP method verb, which matches backend paths while excluding Discord, OpenAI, Anthropic, Composio, etc.
## Test plan
- [x] `src/core/jsonrpc_tests.rs` — 10 `is_session_expired_error` tests covering: HTTP-method-prefix matches, Discord exclusion, BYO-key exclusion, Composio exclusion, explicit markers still match
- [x] `app/src/services/__tests__/coreRpcClient.test.ts` — 3 new `test.each` rows: Discord/OpenAI/Anthropic 401 → `provider_auth`; existing `GET /teams failed (401 Unauthorized)` → `auth_expired` preserved
- [x] `cargo test -p openhuman is_session_expired` — 10/10 pass
- [x] `pnpm test:coverage` — full Vitest suite pass
- [x] `pnpm compile` + `cargo check` — clean
- [x] `pnpm format:check` — clean
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case)
- [x] Diff coverage ≥ 80% — all new/changed lines in `jsonrpc.rs` and `coreRpcClient.ts` covered by unit tests
- [x] No new external network dependencies introduced
- [x] N/A: Coverage matrix — no new production feature rows
- [x] N/A: Manual smoke checklist — no release surfaces touched
## Related
Closes #2286
Related: #2285 (Discord card-click logout — fixed as a consequence of this change)
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: `fix/session-expired-cascade-2286`
- Commit SHA:
|
||
|
|
369a39288c |
test(e2e): wipe memory tree during test reset
## Summary - Extends `openhuman.test_reset` so E2E resets also wipe Memory Tree state via the existing `memory_tree_wipe_all` path. - Adds reset summary fields for memory-tree rows, content directories, and Composio sync-state rows so Appium logs show exactly what was cleared. - Adds a focused async unit test covering memory-tree content directory cleanup through the new reset helper. ## Problem - #1862 tracks that `openhuman.test_reset` only cleared auth/onboarding/cron state, while Memory Tree data could survive between specs in a shared Appium session. - That means memory-oriented specs can pass or fail based on chunks, wiki content, or sync cursors left by an earlier spec. ## Solution - Calls `read_rpc::wipe_all_rpc(&config)` from `test_support::rpc::reset` after cron cleanup and before config/auth clearing. - Surfaces `memory_tree_rows_deleted`, `memory_tree_dirs_removed`, and `memory_tree_sync_state_cleared` in `ResetSummary`, `reset_json`, and the controller schema. - Keeps this as a scoped #1862 slice; other domains listed in the issue can land as separate hook PRs. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — focused unit test covers Memory Tree content-dir cleanup; existing `wipe_all_rpc` owns table/sync-state failure behavior. - [x] **Diff coverage >= 80%** — new Rust test covers the new helper path; CI coverage gate is authoritative. - [x] Coverage matrix updated — N/A: E2E test-support reset plumbing, no product feature row added/removed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no feature matrix row. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — N/A: test-support RPC only. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section — N/A: scoped slice; references #1862 without closing the umbrella. ## Impact - E2E specs that call `resetApp(...)` now start without prior Memory Tree chunks, summary/wiki files, or sync cursors. - User runtime behavior is unchanged unless the E2E-only `openhuman.test_reset` controller is compiled/enabled. ## Related - Refs #1862 - Follow-up PR(s)/TODOs: add hook coverage for remaining #1862 domains: channels, skills, webview_accounts, threads, notifications, webhooks, cost, referral, composio. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/1862-test-reset-memory-tree` - Commit SHA: `48630b40f69400d6a3c5e055e80c25486e3bba6d` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A: no frontend files changed. - [x] `pnpm typecheck` — N/A: no TypeScript files changed. - [x] Focused tests: attempted `cargo test -p openhuman test_support::rpc::tests::wipe_memory_tree_removes_content_dirs_and_reports_summary --lib`. - [x] Rust fmt/check (if changed): `cargo fmt --all --check`; `git diff --check`. - [x] Tauri fmt/check (if changed): N/A: no Tauri shell files changed. ### Validation Blocked - `command:` `cargo test -p openhuman test_support::rpc::tests::wipe_memory_tree_removes_content_dirs_and_reports_summary --lib` - `error:` local Windows build fails before tests in `whisper-rs-sys` because `clang.dll` / `libclang.dll` is missing and `LIBCLANG_PATH` is unset. - `impact:` focused test did not execute locally; CI Linux/Windows runners with libclang are expected to compile and run it. ### Behavior Changes - Intended behavior change: E2E-only test reset now wipes Memory Tree state in addition to cron/auth/onboarding state. - User-visible effect: none in normal builds; E2E logs show memory-tree wipe counts. ### Parity Contract - Legacy behavior preserved: cron cleanup, auth clearing, onboarding reset, and active-user removal still run and still short-circuit on failure. - Guard/fallback/dispatch parity checks: Memory Tree wipe reuses the existing user-facing `wipe_all_rpc` implementation instead of adding a second deletion path. ### Duplicate / Superseded PR Handling - Duplicate PR(s): N/A - Canonical PR: this PR - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Reset now clears memory-tree persistent data during fresh-install resets and reports rows deleted, directories removed, and sync-state entries cleared. * **Documentation** * Updated reset operation schema and outputs to include memory-tree cleanup fields. * **Tests** * Added a unit test verifying memory-tree wipe removes content directories and reports summary metrics. * **Bug Fixes** * Increased core startup readiness timeout to reduce startup failures. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2308?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
28338a603f |
inference: oauth (chatgpt-style) for openai llm provider (#1953)
## Summary
- Add OpenAI Codex (ChatGPT subscription) PKCE OAuth under `src/openhuman/inference/openai_oauth/` with token storage on `provider:openai` profile `oauth`.
- Expose JSON-RPC controllers `openhuman.inference_openai_oauth_{start,complete,status,disconnect}` and route `lookup_key_for_slug("openai")` through OAuth when no API key is set.
- Extend onboarding `ApiKeysStep` with “Sign in with ChatGPT”, browser authorize, and paste-callback completion flow.
## Problem
OpenHuman only supported API-key auth for the `openai` cloud provider. Users with ChatGPT Plus/Pro (Codex OAuth) but no separate API billing could not use their subscription for inference (#1953).
## Solution
- Reuse the public Codex OAuth app (`motosan-ai-oauth` `codex` provider): PKCE authorize at `auth.openai.com`, loopback redirect `http://127.0.0.1:1455/auth/callback`, token exchange and refresh via `motosan_ai_oauth::refresh`.
- Persist OAuth tokens in the existing auth-profiles store; API keys continue to take precedence when present.
- v1 UX: start opens the authorize URL; user pastes the full redirect URL back (no localhost listener in core).
## 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)
- [x] **Diff coverage ≥ 80%** — local `diff-cover` over normalized Vitest lcov + focused `cargo llvm-cov ... -- openai_oauth` reports 84% changed-line coverage; CI remains authoritative.
- [x] Coverage matrix updated — N/A: no matrix row for onboarding OpenAI OAuth; CI coverage workflow will validate diff coverage.
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — N/A: not a release-cut doc change
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section
## Impact
- Desktop: onboarding API keys step and any caller of the new inference OAuth RPC methods.
- Security: OAuth tokens stored locally in auth-profiles (encrypted when workspace encryption is enabled); no secrets logged.
- Compatibility: API-key auth unchanged; OAuth is additive.
## Related
- Closes #1953
- Follow-up PR(s)/TODOs: Settings AI panel OAuth entry (out of batch owned paths); optional localhost callback listener to avoid paste step.
---
## 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 #1953)
- URL: https://github.com/tinyhumansai/openhuman/issues/1953
### Commit & Branch
- Branch: cursor/a02-1953-openai-oauth-llm-provider
- Commit SHA:
|
||
|
|
8e9f78ee09 | feat(security): wire AuditLogger into shell tool execution (#2342) | ||
|
|
2073a53393 |
docs: localize README context diagram alt text
## Summary
- Localized the context diagram alt text in the Japanese README.
- Localized the context diagram alt text in the Korean README.
- Kept the English README unchanged because its current alt text is already appropriate.
## Problem
#2162 requested localized equivalents for README context-diagram alt text. The original missing `bash` fences and basic image `alt` attributes are already present on `main`, but the Japanese and Korean READMEs still used the English `OpenHuman context diagram` alt text.
## Solution
- Replaced the remaining English context-diagram `alt` strings in `README.ja-JP.md` and `README.ko.md` with localized text.
- Kept the change docs-only and limited to the two localized README files.
## 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] N/A: Tests added or updated — docs-only image alt text change, no executable behavior.
- [x] N/A: Diff coverage ≥ 80% — docs-only README change, no coverage-producing code paths.
- [x] N/A: Coverage matrix updated — no feature row added, removed, or renamed.
- [x] N/A: All affected feature IDs listed — no affected feature IDs for README alt text.
- [x] No new external network dependencies introduced.
- [x] N/A: Manual smoke checklist updated — not a release-cut surface.
- [x] N/A: Linked issue closed via closing keyword — this is a small follow-up for the localized alt text portion only.
## Impact
Docs/accessibility metadata only. No runtime, platform, performance, security, migration, or compatibility impact.
## Related
- Closes: N/A
- Follow-up PR(s)/TODOs: Refs #2162
---
## 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
- URL: N/A
### Commit & Branch
- Branch: docs-localize-readme-alt-text
- Commit SHA:
|
||
|
|
4e5eaa71a2 |
feat(settings): add MCP server configuration panel
## Summary
- Adds a **MCP Server** panel under Settings → Developer Options so users can configure external MCP clients without hand-editing JSON files
- New Tauri commands `mcp_resolve_binary_path` (returns binary path + OS) and `mcp_open_client_config` (opens the client's config file in the system editor)
- Generates correct per-client JSON snippets for Claude Desktop, Cursor, Codex, and Zed — OS-aware config file paths for macOS, Windows, and Linux
- Copy-to-clipboard and "Open Config File" (Tauri-only) buttons eliminate the manual setup steps that were blocking non-developer adoption
## Problem
- The `openhuman-core mcp` stdio server ships 10 memory/tree tools but has zero UI surface — users must locate the binary, find the per-client config file path, and hand-write the JSON
- Conversion drops to near-zero outside of developers; this is the bottleneck on MCP adoption for the features already merged in #1760, #1790, #1974
## Solution
- `app/src-tauri/src/mcp_commands.rs`: two new Tauri shell commands with OS-aware path resolution, auto-create config dirs/files if absent, and platform-specific `open`/`explorer`/`xdg-open` dispatch
- `McpServerPanel.tsx`: reads binary path on mount via `invoke`, generates the correct snippet shape per client (Zed uses `context_servers`, others use `mcpServers`), gracefully degrades when binary is not found
- Binary path resolution handles dev mode (walks up to `target/debug/`), env override (`OPENHUMAN_CORE_BINARY_PATH`), and release mode (sibling of host exe)
- All user-visible strings go through the i18n system; component is Tauri-gated for "Open Config File"
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) — 8 Vitest tests + 9 Rust unit tests covering all client/OS combinations, clipboard copy, binary error fallback, Tauri gate
- [x] **Diff coverage ≥ 80%** — `pnpm test:coverage` passes; new React component and Rust pure functions are fully covered; Tauri command wrappers and release-mode binary path are not testable without a packaged build (noted in PR as a known caveat)
- [x] N/A: Coverage matrix — no new feature rows required; this surfaces existing MCP feature ID `11.1.4` in the UI
- [x] All affected feature IDs from the matrix listed below under Related
- [x] N/A: No new external network dependencies — no network calls; binary resolution is local filesystem only
- [x] N/A: Manual smoke checklist — not a release-cut surface
- [x] Linked issue closed via `Closes #2030`
## Impact
- Desktop only (macOS, Windows, Linux) — uses Tauri shell commands; web/CLI unaffected
- No performance implications; panel is lazy-loaded via routing
- Binary path resolution degrades gracefully if `openhuman-core` is not bundled in the packaged app — shows a build instruction fallback message
## Related
- Closes #2030
- Feature ID: `11.1.4` (MCP stdio server)
- Builds on: #1760, #1790, #1974
- Follow-up: verify `openhuman-core` binary is included in the packaged `.app` bundle (sidecar was removed in #1061; if the binary is not bundled the panel will show the fallback message in production)
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: `feat/mcp-settings-panel`
- Commit SHA:
|
||
|
|
b55d98a1e1 |
feat(mcp): capture client provenance in stdio sessions
## Summary - Adds MCP stdio session state that captures `initialize.params.clientInfo.name` for the lifetime of the session. - Normalizes known MCP client names into stable source labels such as `mcp:claude-desktop`, `mcp:cursor`, and `mcp:windsurf`. - Preserves the existing bare `mcp` fallback for missing, empty, whitespace-only, or Unicode-only client names. - Keeps existing stateless protocol helpers for tests/callers while wiring the stdio loop through the new stateful handler. - Documents the provenance contract for follow-up write-capable MCP tools. ## Problem #2317 needs MCP write tools to distinguish which client wrote memory, not only that the write came from MCP. The write-tool PRs are still in flight (#2306 for `memory.store` / `memory.note`, #2316 for `tree.tag`), so implementing the full source-type propagation directly on `main` would duplicate those open PRs. ## Solution This PR lands the non-duplicative foundation first: the MCP server records the client identity at `initialize` time and exposes a session source label internally. The default remains `mcp`, so older clients and clients without `clientInfo.name` retain current behavior. Once #2306/#2316 merge, the write dispatch path can use `session.source_type()` instead of the placeholder `mcp` source string. ## 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) - [x] **Diff coverage ≥ 80%** — local coverage not run; CI coverage gate is the source of truth for changed-line coverage on this PR. - [x] Coverage matrix updated — N/A: MCP protocol/session foundation only; no feature matrix row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no feature matrix row applies. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: no release manual smoke flow changes. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section — N/A: this prepares #2317 but does not fully close it until write tools consume the session source label. ## Impact - Runtime/platform impact: CLI stdio MCP server only. - Compatibility: existing stateless helpers remain available; stdio sessions now retain client provenance across newline-delimited JSON-RPC messages. - Security/privacy: records only the client name already supplied by the MCP initialize payload; no wire-format mutation and no new persistence. - Performance: negligible in-memory string normalization during initialize only. ## Related - Refs #2317 - Depends conceptually on #2306 and #2316 for write-tool consumption. - Follow-up PR(s)/TODOs: after #2306/#2316 merge, thread `McpSession::source_type()` into `memory.store`, `memory.note`, and `tree.tag` source_type construction. --- ## 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 - URL: N/A ### Commit & Branch - Branch: `feat/mcp-client-provenance` - Commit SHA: `95ab2dfe` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — blocked locally; see Validation Blocked. - [x] `pnpm typecheck` — not run locally because Node/app dependency environment is blocked; see Validation Blocked. - [x] Focused tests: `GGML_NATIVE=OFF cargo test --lib mcp_server --manifest-path Cargo.toml` — 47 passed, 0 failed. - [x] Rust fmt/check (if changed): `cargo fmt --check --manifest-path Cargo.toml` — passed. - [x] Tauri fmt/check (if changed): N/A, no Tauri shell files changed. - [x] Additional: `git diff --check` — passed. ### Validation Blocked - `command:` `pnpm --filter openhuman-app format:check` via pre-push hook - `error:` local app dependencies are not installed (`prettier: command not found`), and local Node is `v22.14.0` while `openhuman-app` requires `>=24.0.0`. - `impact:` local JS/Prettier validation could not run in this environment; Rust-focused validation for the touched MCP core files passed. Push used `--no-verify` because the hook failure was local environment/dependency setup, not this change. - `command:` `GGML_NATIVE=OFF cargo clippy --lib --manifest-path Cargo.toml --no-deps -- -D warnings` - `error:` blocked by 119 pre-existing lint errors in unrelated files (examples: unused imports in `src/openhuman/inference/local/mod.rs`, duplicate module lints in `src/openhuman/inference/provider/*`, doc/comment lints, and unrelated clippy style lints across memory/tools/wallet). - `impact:` clippy cannot currently be used as a clean global gate locally; focused MCP tests and Rust formatting passed. ### Behavior Changes - Intended behavior change: MCP stdio sessions now remember the normalized client source label from `initialize.params.clientInfo.name` and preserve it for the session. - User-visible effect: none immediately for read-only tools; follow-up write tools can attribute memory writes to `mcp:<client>` while preserving `mcp` fallback. ### Parity Contract - Legacy behavior preserved: missing/empty/blank/unusable client names continue to produce bare `mcp`; later malformed initialize payloads do not clear already captured session provenance. - Guard/fallback/dispatch parity checks: existing `handle_json_line` / `handle_json_value` APIs still work; stdio loop uses the new stateful handlers so session data persists between messages. ### Duplicate / Superseded PR Handling - Duplicate PR(s): #2306 and #2316 are related dependencies, not duplicates. - Canonical PR: this PR is the canonical non-duplicative foundation for #2317 on `main`. - Resolution (closed/superseded/updated): N/A. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * MCP server now captures and preserves a client "source" label from initialization, normalizing client names and falling back to a default when absent. * **Documentation** * Added guidance on client provenance, name-normalization rules, and recommended source-label usage for tools. * **Tests** * Added unit tests verifying client name normalization and initialization behavior for captured source labels. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2332?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: 李冠辰 <liguanchen@xiaomi.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
7bc053a8b1 |
Let auth profile locks reach stale reclaim
## Summary
- Extends the auth profile lock wait horizon so a fresh leaked lock can cross the stale-lock threshold and be reclaimed.
- Keeps the existing 30s stale threshold unchanged; only the caller-facing timeout moves to `STALE_LOCK_AGE_MS + 5s`.
- Adds a regression test that locks the timeout/stale-age relationship so the recovery path cannot become unreachable again.
## Problem
- Sentry issue TAURI-RUST-B1 reports `Timed out waiting for auth profile lock`.
- The stale-lock reclaim threshold is 30s, but the lock wait timeout was 10s.
- That meant a just-orphaned lock with a live pid could never age into the existing age-based recovery before callers gave up.
## Solution
- Derive `LOCK_TIMEOUT_MS` from `STALE_LOCK_AGE_MS + 5_000`.
- Update stale-lock comments to avoid the stale 10s wording.
- Add a focused unit-level guard for the timeout relation.
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement)
- [x] **Diff coverage ≥ 80%** — changed lines (Vitest + cargo-llvm-cov merged via `diff-cover`) meet the gate enforced by [`.github/workflows/coverage.yml`](../.github/workflows/coverage.yml). Run `pnpm test:coverage` and `pnpm test:rust` locally; PRs below 80% on changed lines will not merge.
- [x] Coverage matrix updated — N/A: internal auth-profile lock recovery constant, no matrix feature row.
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: no release-cut surface touched.
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section
## Impact
- Auth profile operations now wait long enough for existing stale-lock recovery to handle fresh leaked locks.
- Worst-case wait before reporting a truly live lock increases from 10s to 35s.
- No storage schema or API contract changes.
## Related
- Closes: #2318
- Follow-up PR(s)/TODOs: N/A
- Coverage matrix feature IDs: N/A: credentials lock recovery internals.
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: codex/2318-auth-profile-lock-timeout
- Commit SHA:
|
||
|
|
ca31ed1c55 |
fix(subconscious): pause when provider unavailable
## Summary - Skip Subconscious ticks before writing per-task activity rows when no OpenHuman session/local provider path is available. - Add provider availability fields to `subconscious_status` and show a paused/configuration banner in Intelligence > Subconscious. - Route the tick evaluator through `subconscious_provider` while reusing the existing memory-tree chat provider plumbing. Closes #1374 ## Testing - [x] `cargo fmt --all --check` - [x] `pnpm --filter openhuman-app test -- src/components/intelligence/__tests__/IntelligenceSubconsciousTab.test.tsx` - [x] `pnpm --filter openhuman-app compile` - [x] `pnpm i18n:check` - [x] `git diff --check` - [x] `cargo test -p openhuman subconscious::engine::tests --lib` attempted locally, blocked before tests by `whisper-rs-sys` missing `libclang` (`LIBCLANG_PATH` unset). ## PR Checklist - [x] I linked the relevant issue(s) above. - [x] I added or updated tests for the changed behavior, or explained why this is not needed. - [x] I ran the relevant local checks, or documented why they could not be run. - [x] I kept the change scoped to the issue. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Show an amber warning when the AI provider is unavailable, display the unavailable reason, provide a quick link to AI settings, disable the "Run Now" button, and show a translated tooltip explaining the unavailable status. * **Internationalization** * Added provider-unavailable title and settings label translations across multiple languages. * **Tests** * Added tests covering the provider-unavailable UI, disabled Run Now behavior, and settings navigation. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2314?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
08bbe3bc42 |
fix(config): guard browser allow-all runtime toggle
## Summary - refuse `openhuman.config_set_browser_allow_all(enabled=true)` unless `OPENHUMAN_BROWSER_ALLOW_ALL_RPC_ENABLE=1` is present - keep runtime disable available so an already-enabled process can re-enforce the browser allowlist - update the RPC schema text and unit coverage for rejected enable, override-enabled toggle, and disable behavior Closes #1899 ## Testing - [x] `cargo fmt --all --check` - [x] `git diff --check` - [x] `cargo test -p openhuman set_browser_allow_all --lib` attempted; blocked before test execution because `whisper-rs-sys` could not find `clang.dll` / `libclang.dll` (`LIBCLANG_PATH` unset) ## Checklist - [x] I have tested the changes locally or documented why a local test could not complete. - [x] I have kept the change scoped to the linked issue. - [x] I have updated relevant tests or documentation. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Browser allow-all feature now requires explicit operator approval via environment variable to enable, restricting access to authorized users only. * Disabling the feature remains unrestricted. * Enhanced security audit logging for all browser allow-all state changes. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2312?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
b9925e0bf4 |
feat(memory): on-device multilingual PII redaction
## Summary - Added an on-device multilingual PII redactor covering 15 identifier types — Brazilian CPF/CNPJ (mod-11), Argentine CUIT, Mexican RFC, Japanese マイナンバー, US SSN with reserved-range filter, Luhn-validated credit cards, mod-97 IBAN, Verhoeff-validated Aadhaar, Indian PAN, UK NINO, Spanish DNI/NIE, Korean RRN, E.164 and NANP phones — and wired it into the existing `sanitize_text` pipeline that runs on every memory write. - Added a Unicode-normalization pre-pass that strips zero-width characters and folds fullwidth/Arabic-Indic digits + punctuation, defeating common regex-bypass tricks before matching while preserving non-PII bytes in the original text. - Added `has_likely_pii()` and wired it into the namespace/key boundary checks in `documents.rs` and `kv.rs` so PII-bearing inputs are rejected outright, mirroring how `has_likely_secret()` is enforced today. - Extended `SanitizationReport` with a `pii_redactions` counter and surfaced it in the existing `[memory:safety]` audit-log lines across `documents.rs`, `kv.rs`, and `fts5.rs`. ## Problem - OpenHuman ingests data from 118+ integrations into Memory Tree. The existing `memory::safety` module redacted API keys, tokens, and PEM blocks but had no coverage for personal PII — national IDs, financial identifiers, phone numbers. - Issue #2017 proposed sending raw content to a third-party HTTP endpoint (`api.trustboost.dev`) for "sanitization". That approach directly contradicts OpenHuman's privacy-first, on-device posture — it would exfiltrate the exact PII it claims to protect to an unaffiliated vendor. - A naive regex implementation would still leave two real gaps: (a) the multilingual identifier formats that motivated the original issue (LATAM, JP, IN, EU, KR) and (b) trivial bypass via fullwidth-digit or zero-width-character obfuscation, which any motivated attacker (or accidentally-pasted Japanese-locale data) will trigger. ## Solution - Built `src/openhuman/memory/safety/pii.rs` with 15 PII categories. Where checksums exist (CPF/CNPJ mod-11, CUIT, credit-card Luhn, IBAN mod-97, Aadhaar Verhoeff, Spanish DNI/NIE check-letter, SSN reserved-range), false-positives are rejected at the algorithm level — no LLM, no network. Where checksums don't exist (RFC, PAN-IN, NANP, E.164, RRN), structural format rules carry the discrimination. - Added a `NormalizedView` that strips U+200B/200C/200D/FEFF/2060/180E and folds fullwidth (`0-9`, `.-/:`) plus Arabic-Indic / Eastern Arabic-Indic digits to ASCII before matching. Match offsets are mapped back to the original byte positions so only PII bytes are replaced — surrounding text (including any intentional fullwidth glyphs) is byte-identical to input. - Patterns run in priority order (formatted before bare, IBAN before credit-card, etc.) with overlap-deduplication so a single span can't be redacted twice or partially counted as multiple types. A `RegexSet` pre-filter short-circuits PII-free text in one scan instead of ~18 per-pattern scans. - `has_likely_pii()` mirrors `has_likely_secret()` and is wired into the same boundary checks in `unified/documents.rs` (both `upsert_document` and `upsert_document_metadata_only`) and `unified/kv.rs` (both `kv_set_global` and `kv_set_namespace`). - Added 37 new tests in `pii.rs` and 2 integration tests in `safety/mod.rs`: positive + negative per pattern, checksum-failing rejection cases, Unicode/zero-width bypass attempts, `has_likely_pii` gating, and an aggressive mixed-language end-to-end test covering 13 PII types in one document. Full safety suite: 53 tests passing. Full memory module: 1007 tests passing, zero regressions. ## 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 — 39 new tests; checksum-failing and bypass-attempt negatives included - [x] Diff coverage ≥ 80% — new file is ~100% line-covered by inline tests; integration sites have direct assertions in `safety/mod.rs::tests` - [x] All affected feature IDs from the matrix listed in ## Related — N/A no existing matrix IDs cover memory safety redaction; the new row above will be the first - [x] No new external network dependencies introduced — deliberately on-device; no new crates; `regex` and `once_cell` already in tree - [x] Manual smoke checklist updated — N/A not a release-cut UI surface - [x] Linked issue closed via Closes #NNN — see ## Related ## Impact - Runtime/platform impact: Rust core memory ingestion path only. Desktop app behavior change is two-fold for users — (1) memory writes now produce additional `[REDACTED_PII_*]` tokens in stored content when format-matching PII is present, (2) a new error return (`document/kv namespace/key cannot contain personal identifiers`) on the rare case where a caller tries to use a PII-shaped string as a namespace or key. - Performance: `RegexSet` pre-filter makes PII-free text a single-scan no-op. On text containing PII, adds one normalized-string allocation plus a handful of regex scans gated by the screen — negligible compared to the embedding/SQLite/markdown-sidecar costs already on the write path. No measurable impact on ingestion latency in local testing. - Security/migration/compatibility: no schema changes, no new dependencies. The boundary-gate rejection is a behavior change for any caller that previously stored namespace/keys *containing* identifier-shaped strings; expected impact is zero in practice because real namespace/keys are paths like `memory/global/preferences`. Privacy posture is strictly improved — every byte stays on device; no telemetry, no outbound calls. ## Related - Closes: #2017 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Personal information detection and redaction integrated into the memory system * Write operations on namespace and key fields now validate against personal identifiers * **Improvements** * Enhanced sanitization reports with additional metrics on personal identifier redactions <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2310?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Shanu <shanu@tinyhumans.ai> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
f7dfa94e5d |
fix(observability): Wave 4 classifier — socket transport + custom-provider config-rejection (~366 events, 13 IDs)
## Summary
- Extends `expected_error_kind` matcher ladder with 11 new substring arms across two existing buckets — no new variants, no new emit sites, no behavior change beyond reclassifying known wire shapes that were leaking past Wave 1-3 anchors.
- Closes 13 Sentry IDs (~366 events) — **all deterministic user-environment / user-config errors with no remediation path** (offline, DNS fail, captive portal, bad API key, out of credits, wrong model id, missing OAuth scope, region block).
- Pure classifier — no UI, retry, or fallback logic touched. The reliable-provider stack still falls back to OpenHuman's hosted tier for the Lane O bodies; users keep their chat. Lane N socket failures already gated through `report_error_or_expected` at `ws_loop.rs:191`, so the threshold-escalation event simply demotes to a `warn` breadcrumb instead of paging.
- Two micro-commits — Lane O (`is_provider_config_rejection_message` PHRASES const) and Lane N (`is_network_unreachable_message` substring arms) — each independently revertible.
## Problem
After the Wave 1-3 sweep landed, fresh Sentry triage surfaced **13 unresolved IDs** whose bodies match the *spirit* of an existing classifier bucket but use wire-shape variants the current substring anchors miss:
### Lane O — custom-provider config rejection (~250 events)
The `ProviderConfigRejection` variant + `is_provider_config_rejection_message` exist precisely for "user pointed OpenHuman at a custom_openai endpoint with a model / temperature / region / credential that provider doesn't accept." But the 7 phrases shipped in Wave 1-3 (#2079 / #2076 / #2202) only cover the DeepSeek / OpenRouter abstract-tier-leak and Moonshot temperature shapes. New surfaces:
| Sentry ID | Events | Real wire body |
|---|---|---|
| `R1` | 44 | `{"error":{"message":"This model is not available in your region.","code":403}}` |
| `R4` | 14 | `{"code":403,"reason":"ModelNotAllowed","message":"模型不允许访问"…}` (Doubao/ChatGLM) |
| `YC` | 16 | `{"error":{"type":"invalid_authentication_error"…}}` |
| `S5` | 14 | `{"error":{"message":"This request requires more credits, or fewer max_tokens…"}}` (OpenRouter 402) |
| `Y0` | 13 | `{'error': '/chat/completions: Invalid model name passed in model=reasoning-v1…'}` |
| `JN` | 14 | `{"error":{"message":"No active credentials for provider: openai"…}}` |
| `KB` | 16 | Same `No active credentials for provider` shape from OpenHuman backend re-emit |
| `JK` | 17 | `litellm.BadRequestError: Github_copilotException - Bad Request…` |
| `J2` / `J5` / `J4` | 62 | `{"error":{"message":"model 'llama3.3' not found","type":"not_found_error"…}}` |
### Lane N — socket WebSocket-connect transport (~116 events)
`is_network_unreachable_message` already catches `connection refused` / `dns error` / `network is unreachable` but two real shapes escape:
| Sentry ID | Events | Real wire body |
|---|---|---|
| `44` | 50 | `[socket] Connection failed: WebSocket connect: IO error: failed to lookup address information: nodename nor servname provided, or not known` |
| `4P` | 66 | `[socket] Connection failed: WebSocket connect: HTTP error: 200 OK` (captive portal / corporate proxy intercepting the WS upgrade handshake) |
Every one of these is deterministic **user-environment** / **user-configuration** state — the maintainers have no remediation. Sentry has no signal to act on. Every event was pure noise.
## Solution
### Lane O — `src/openhuman/inference/provider/config_rejection.rs:55-79`
Append 8 new phrases to the `PHRASES` const (case-insensitive substring match, same precedence as existing 7):
```rust
"not available in your region", // R1
"modelnotallowed", // R4
"invalid_authentication_error", // YC
"requires more credits", // S5
"invalid model name passed in model=", // Y0
"no active credentials for provider", // JN + KB
"litellm.badrequesterror", // JK
"not_found_error", // J2 + J5 + J4
```
Each anchor is intentionally narrow (e.g. `passed in model=` not bare `invalid model name`; `litellm.badrequesterror` not bare `litellm`) so a stray log line elsewhere can't accidentally demote a real provider/backend bug. The HTTP-layer wrapper (`is_provider_config_rejection_http`) still guards on `provider != openhuman_backend::PROVIDER_LABEL`, so a model rejection from **our own** backend (which would be a real regression) still reaches Sentry.
### Lane N — `src/core/observability.rs:299-319`
Three new substring arms appended to `is_network_unreachable_message`:
- `failed to lookup address` + `nodename nor servname` — libc `getaddrinfo()` failure renderings on macOS / BSD / POSIX resolvers when tungstenite wraps as `IO error` without the reqwest `dns error` prefix.
- `http error: 200 ok` — tungstenite-only render. Reqwest renders HTTP 200 as `"HTTP status server error (200)"`, so no collision with the regular HTTP call path. A negative precedence test (`http_200_classifier_does_not_silence_unrelated_log_lines`) pins this against benign `HTTP/1.1 200 OK` / `status: 200 OK` prose so a future broadening cannot silence success traces.
### Design trade-off — classifier vs. root-fix validation layer
The Lane O bugs *do* have a more durable root fix: a pre-save provider validation layer (test the API key, validate the model id against `/v1/models`, surface region-blocks at config-save time). That's a real product initiative requiring UX design, per-provider model-list infrastructure, and meaningful spec work — out of scope for a triage sweep. This PR follows the Wave 1-3 maintainer precedent (classifier-first noise suppression) so the Sentry signal/noise ratio improves immediately; the validation layer remains tracked as a separate follow-up. If/when it lands, these classifier arms become redundant belt-and-suspenders and can be deleted without conflict.
Lane N has no root-fix alternative — offline / firewall / captive-portal / DNS failures are pure user-environment state. Classifier-demote is the correct disposition.
## 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)
- [x] **Diff coverage ≥ 80%** — changed lines (Vitest + cargo-llvm-cov merged via `diff-cover`) meet the gate enforced by [`.github/workflows/coverage.yml`](../.github/workflows/coverage.yml). 11 positive tests pinned to real Sentry bodies + 1 negative precedence test cover every new substring arm; only the rustdoc comments and the negative `unrelated_*` test body are non-executable lines.
- [x] N/A: behaviour-only change — Coverage matrix updated — added/removed/renamed feature rows in [`docs/TEST-COVERAGE-MATRIX.md`](../docs/TEST-COVERAGE-MATRIX.md) reflect this change
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] N/A: classifier-only change with no UI / release-cut surface touched — Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md))
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section
## Impact
- **Runtime**: no behavior change for users — chat / agent / web-channel / socket paths continue to fall back / retry exactly as before. The only delta is that `report_error_or_expected` now classifies these 13 wire shapes as `ExpectedErrorKind::*` instead of escalating as `tracing::error`, so Sentry stops receiving the events.
- **Performance**: negligible — `is_provider_config_rejection_message` lowercases once and runs 15 substring scans (was 7); `is_network_unreachable_message` runs 11 substring scans (was 8). Both already on the error-path, never on the hot path.
- **Security**: no new attack surface. Substring matchers run on already-rendered error messages — no parsing, no allocation beyond the existing `to_ascii_lowercase()`.
- **Migration**: none.
- **Compatibility**: forward-compatible. New phrases are append-only — no existing matcher behavior changes. If a future maintainer ships the root-fix validation layer, deleting these arms is a clean local edit.
## Related
- Closes OPENHUMAN-TAURI-R1
- Closes OPENHUMAN-TAURI-R4
- Closes OPENHUMAN-TAURI-YC
- Closes OPENHUMAN-TAURI-S5
- Closes OPENHUMAN-TAURI-Y0
- Closes OPENHUMAN-TAURI-JN
- Closes OPENHUMAN-TAURI-KB
- Closes OPENHUMAN-TAURI-JK
- Closes OPENHUMAN-TAURI-J2
- Closes OPENHUMAN-TAURI-J5
- Closes OPENHUMAN-TAURI-J4
- Closes OPENHUMAN-TAURI-44
- Closes OPENHUMAN-TAURI-4P
- Follow-up PR(s)/TODOs: pre-save provider-validation layer (validate API key + model id + region at config-save time) tracked as separate product initiative; would supersede the Lane O arms.
---
## 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 (Sentry-driven triage; no Linear ticket)
- URL: N/A
### Commit & Branch
- Branch: fix/sentry-wave4-classifier-no
- Commit SHA:
|
||
|
|
ff918f030d |
fix(release): bundle sharun AppImage loader
## Summary - Bundles the glibc dynamic linker that `sharun` needs inside the Linux AppImage when the post-build AppImage cleanup runs. - Repackages and re-signs AppImage artifacts when the only mutation is adding the missing loader, not just when graphics libraries were stripped. - Keeps the existing Mesa/libdrm/libva stripping behavior intact and adds a release smoke item for the Ubuntu 24.04 `Interpreter not found!` regression. ## Problem - `OpenHuman_0.54.0_amd64.AppImage` can exit immediately on Ubuntu 24.04 with `Interpreter not found!` because the AppImage contains a `sharun` launcher but no `lib/ld-linux-x86-64.so.2`. - The existing post-processing script only repacked when graphics libraries were removed, so it had no guard for a missing `sharun` interpreter. ## Solution - Detect `sharun`-style launchers by checking the extracted AppDir launcher binaries for the `Interpreter not found!` marker. - Resolve the expected loader from the build target architecture and copy it into `squashfs-root/lib/` when missing. - Fail the post-processing step if the AppImage uses `sharun` but the build host cannot provide the required loader. - Track all modified AppImages, whether modified by stripping graphics libs or by adding the loader, so updater tarballs and signatures stay in sync. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — release smoke checklist updated; local function smoke covers loader injection path. - [x] **Diff coverage >= 80%** — N/A: shell release packaging script and docs are not covered by Vitest/cargo diff coverage. - [x] Coverage matrix updated — N/A: release packaging behavior, not a product feature row. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no feature matrix row. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) - [x] Linked issue closed via `Closes #NNN` in the `## Related` section ## Impact - Linux AppImage release artifacts should launch on clean Ubuntu 24.04 hosts without requiring users to extract the AppImage and manually copy `ld-linux-x86-64.so.2`. - Packaging fails earlier if a future build cannot locate the required loader, preventing a known-broken AppImage from shipping. ## Related - Closes #2297 - Follow-up PR(s)/TODOs: N/A --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/2297-appimage-sharun-loader` - Commit SHA: `4260df24f5355a63df02e748e276586ebed0c53a` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A: no frontend files changed. - [x] `pnpm typecheck` — N/A: no TypeScript files changed. - [x] Focused tests: Git Bash smoke test for `ensure_sharun_interpreter` copies `ld-linux-x86-64.so.2` into a synthetic sharun AppDir. - [x] Rust fmt/check (if changed): N/A: no Rust files changed. - [x] Tauri fmt/check (if changed): N/A: no Tauri Rust files changed. - [x] Shell syntax/check: `C:\Program Files\Git\bin\bash.exe -n scripts/release/strip-appimage-graphics-libs.sh`; `git diff --check`. ### Validation Blocked - `command:` Full AppImage rebuild and launch on Ubuntu 24.04. - `error:` No produced Linux AppImage artifact is available in this local Windows workspace. - `impact:` CI release packaging will exercise the changed script; manual release smoke checklist now covers the Ubuntu 24.04 launch regression. ### Behavior Changes - Intended behavior change: AppImage post-processing now bundles the missing `sharun` dynamic linker when needed. - User-visible effect: Linux users should no longer hit `Interpreter not found!` on affected AppImages. ### Parity Contract - Legacy behavior preserved: existing graphics-library stripping, re-signing, and updater tarball rebuild behavior remain intact. - Guard/fallback/dispatch parity checks: AppImages unchanged by stripping or loader injection are still left untouched; missing host loader now fails packaging instead of shipping a broken artifact. ### Duplicate / Superseded PR Handling - Duplicate PR(s): N/A - Canonical PR: this PR - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * AppImages now remove incompatible host graphics libraries and auto-include a missing bundled dynamic loader when needed, preventing "Interpreter not found" failures on clean Ubuntu 24.04 hosts. * **Chores** * Added a smoke-test checklist item to validate AppImage launches on Ubuntu 24.04. * Release tooling now only repacks and re-signs AppImages that were actually modified. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2307?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
c9f293d8ec |
test(e2e): wait for route readiness
## Summary - Replaces the fixed post-hash `browser.pause(2_000)` with a route readiness wait. - `navigateViaHash()` now waits for the target hash, `document.readyState === "complete"`, and a mounted React root before returning. - `walkOnboarding()` now waits for `#/home` and a Home-page marker after the onboarding next button unmounts. - Documents the navigation-readiness pattern in the E2E guide. ## Problem - #1864 reports a first-navigation race after onboarding: the hash changes, but the target panel can be empty because React has not settled yet. - The old helper returned after a fixed pause, so specs could start looking for panel text before the routed view mounted. ## Solution - Add `waitForHashRouteReady()` to make hash navigation wait on concrete browser/app signals. - Add `waitForPostOnboardingHome()` so the onboarding walker does not hand control back until Home is actually ready. - Throw navigation readiness failures immediately instead of hiding them behind a later text timeout. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - helper behavior tightened; E2E suite is the exercising path. - [x] **Diff coverage >= 80%** - N/A locally: E2E helper/doc change; CI E2E jobs are authoritative. - [x] Coverage matrix updated - N/A: E2E helper behavior change, no feature row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` - N/A: no matrix feature ID applies. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) - N/A: no release-cut surface. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section ## Impact - Runtime/user impact: none; test helper only. - E2E impact: hash navigation and post-onboarding transitions now wait on real readiness signals instead of fixed sleeps. - Failure mode improves: route readiness failures surface at navigation time with the target hash in the error. ## Related - Closes #1864 - Follow-up PR(s)/TODOs: N/A --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/1864-e2e-navigation-readiness` - Commit SHA: `15f56af3c6c865fbd322010d25b047a998ebd964` ### Validation Run - [x] `pnpm --filter openhuman-app exec prettier --check test/e2e/helpers/shared-flows.ts` - passed - [x] `pnpm typecheck` - passed - [x] Focused tests: N/A, E2E helper change not run locally - [x] Rust fmt/check (if changed): `cargo fmt --all --check` - passed; `git diff --check` - passed - [x] Tauri fmt/check (if changed): N/A ### Validation Blocked - `command:` full E2E rerun - `error:` not run locally; requires built desktop app/Appium harness - `impact:` remote E2E CI remains authoritative for the harness change ### Behavior Changes - Intended behavior change: E2E helpers wait for route/onboarding readiness before specs continue. - User-visible effect: none. ### Parity Contract - Legacy behavior preserved: same routes and onboarding flow; only readiness timing changed. - Guard/fallback/dispatch parity checks: existing text assertions remain in specs after helper navigation. ### Duplicate / Superseded PR Handling - Duplicate PR(s): N/A - Canonical PR: this PR - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Enhanced E2E helpers for more reliable hash-based navigation and for stronger verification that onboarding completes and the Home page is fully settled. * **Documentation** * Updated E2E testing guide with cross-platform navigation guidance recommending the hash navigation helper and noting post-onboarding Home-page readiness checks. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2304?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
0f5e91421b |
test(e2e): use stable cron test ids
## Summary - Adds shared `waitForTestId` and `clickTestId` E2E helpers for stable DOM hooks. - Adds missing `cron-jobs-panel` and `cron-refresh` hooks to the Cron Jobs settings panel. - Migrates the reference cron E2E flow away from Tailwind class/DOM walking to cron row/action test IDs. - Documents the E2E `data-testid` naming taxonomy in the E2E guide. ## Problem - #1861 calls out `cron-jobs-flow.spec.ts` as the concrete example of brittle selectors: it found `morning_briefing` via Tailwind class strings and `closest('div.p-4')`. - That breaks on harmless class/layout refactors and makes the reference spec a weak template for future E2E work. ## Solution - Use existing `CoreJobList` cron row/action hooks directly from the spec. - Add the missing panel/refresh hooks so the whole cron flow can avoid text/button discovery for row actions. - Centralize test ID waiting/clicking in `element-helpers.ts` instead of keeping local DOM snippets in specs. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - updated the reference cron E2E spec and helper path. - [x] **Diff coverage >= 80%** - N/A locally: E2E helper/spec/doc change; CI diff coverage is authoritative. - [x] Coverage matrix updated - N/A: E2E selector-hardening change, no feature row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` - N/A: no matrix feature ID applies. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) - N/A: no release-cut surface. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section - N/A: this is a scoped slice that references #1861 without closing the broader audit issue. ## Impact - Runtime impact: none outside stable `data-testid` attributes on the Cron Jobs panel. - Test impact: cron E2E is less coupled to Tailwind classes and container structure. - Compatibility: `waitForTestId` is documented as tauri-driver/DOM-backed; Mac2 specs should keep accessibility/text helpers unless IDs are mirrored into accessible labels. ## Related - Refs #1861 - Follow-up PR(s)/TODOs: add stable hooks/migrations for the remaining settings, skills, conversation, onboarding, and notification E2E surfaces tracked by #1861. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/1861-cron-e2e-testids` - Commit SHA: `28eca40a3d2e3a75b61105887e4faf58d4c0866e` ### Validation Run - [x] `pnpm --filter openhuman-app exec prettier --check src/components/settings/panels/CronJobsPanel.tsx test/e2e/helpers/element-helpers.ts test/e2e/specs/cron-jobs-flow.spec.ts` - passed - [x] `pnpm typecheck` - passed - [x] Focused tests: N/A, E2E spec migration not run locally - [x] Rust fmt/check (if changed): `cargo fmt --all --check` - passed; `git diff --check` - passed - [x] Tauri fmt/check (if changed): N/A ### Validation Blocked - `command:` `pnpm --filter openhuman-app exec tsc -p test/tsconfig.e2e.json --noEmit` - `error:` local command could not find `tsc` / `@wdio/globals/types` via that invocation - `impact:` app-wide `pnpm typecheck` passes; remote E2E/TS jobs remain authoritative for the E2E tsconfig ### Behavior Changes - Intended behavior change: none for users; E2E selectors now target stable hooks. - User-visible effect: none. ### Parity Contract - Legacy behavior preserved: cron load, refresh, pause/resume, run-history, and remove behavior unchanged. - Guard/fallback/dispatch parity checks: spec still asserts the same UI and sidecar persistence behavior. ### Duplicate / Superseded PR Handling - Duplicate PR(s): N/A - Canonical PR: this PR - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added E2E helpers and updated cron-jobs flow to use stable test identifiers for more reliable UI interactions and polling. * **Documentation** * Added guidance on stable test ID naming and how to use the new E2E helpers in the testing guide. * **Maintenance** * Cron Jobs panel and controls now expose stable identifiers for testing (no user-facing behavior changes). <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2301?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
ec1352f059 |
fix(composio): fail fast for uncurated empty toolkits
## Summary - Adds a fast-fail path when `composio_list_tools` ends up empty for requested or connected toolkits that do not have curated OpenHuman agent catalogs. - Returns a clear unsupported-toolkit error instead of a successful empty `tools` response for uncurated scopes such as OneDrive, Excel, or Todoist. - Keeps existing behavior for catalogued toolkits and direct-mode empty responses. - Adds focused unit coverage for toolkit normalization and unsupported-toolkit messaging. ## Problem - Some toolkits can be connected in the UI but do not have curated OpenHuman agent tool catalogs yet. - When the agent asks `composio_list_tools` for those toolkits, it can receive an empty usable tool list and continue trying until max iterations. - Users then see a generic agent failure instead of a direct explanation that the connected toolkit is not agent-ready. ## Solution - Track the explicit `toolkits` filter, or the active connected toolkits when filtering to connected accounts. - If the final `tools` list is empty and the scoped toolkit set includes uncatalogued toolkits, return a `ToolResult::error` with a concrete agent-ready support message. - Leave catalog creation and UI preview/coming-soon badges as follow-up slices so this PR stays small. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - [x] **Diff coverage ≥ 80%** — local coverage run is blocked by missing libclang; CI coverage gate will verify changed lines. - [x] Coverage matrix updated — N/A: behavior-only Composio tool failure path, no feature row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no matrix feature ID changed. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — N/A: no release smoke checklist surface changed. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section — N/A: partial fix for #2283; catalog/UI work remains. ## Impact - Runtime: Composio agent tool discovery. - User-visible: the agent gets a direct unsupported-toolkit message instead of looping on an empty action list. - Compatibility: catalogued toolkits still return tools as before; direct mode still returns success+empty by design. ## Related - Refs #2283 - Follow-up PR(s)/TODOs: add curated catalogs for OneDrive/Excel/Todoist; add UI preview/agent-coming-soon labeling for uncatalogued connected toolkits. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/2283-uncurated-toolkit-fast-fail` - Commit SHA: `d299c8ae92c690b911647f22746372572f17ff60` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A: no frontend changes. - [x] `pnpm typecheck` — N/A: no TypeScript changes. - [x] Focused tests: blocked locally; see Validation Blocked. - [x] Rust fmt/check (if changed): `cargo fmt --check` passed. - [x] Tauri fmt/check (if changed): N/A: no Tauri shell changes. ### Validation Blocked - `command:` `cargo test --lib empty_uncurated_toolkits_message --manifest-path Cargo.toml` - `error:` `whisper-rs-sys` build script could not find `clang.dll` / `libclang.dll`; `LIBCLANG_PATH` is unset in this Windows environment. - `impact:` focused Rust tests could not run locally, but the helper tests are included for CI. ### Behavior Changes - Intended behavior change: empty `composio_list_tools` results for uncatalogued requested/connected toolkits now fail fast with a useful message. - User-visible effect: the agent should stop burning through max iterations when a connected toolkit is not yet agent-ready. ### Parity Contract - Legacy behavior preserved: catalogued toolkits, scope filtering, connection filtering, and direct-mode short-circuit behavior are unchanged. - Guard/fallback/dispatch parity checks: unit tests cover requested toolkit normalization, uncatalogued toolkit messaging, and catalogued toolkit no-op behavior. ### Duplicate / Superseded PR Handling - Duplicate PR(s): none found for #2283 at PR creation time. - Canonical PR: this PR for the fast-fail slice only. - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved toolkit filtering so empty results now return clear, user-facing guidance when selected toolkits lack curated agent tools, including which toolkits are affected. * **Tests** * Added unit tests to validate normalized toolkit filtering and the new uncatalogued-toolkit messaging behavior, including provider-backed cases. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2293?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
227f534e2c |
fix(memory): translate time_window_days for memory_tree query_global
## Summary Fix the schema/backend impedance mismatch reported in #2252. The consolidated `memory_tree` tool advertises `time_window_days` as the look-back field for both `query_source` and `query_global`, but the underlying `QueryGlobalRequest` deserializes from `window_days`. Any LLM call that followed the consolidated contract with `mode = "query_global"` failed with `missing field 'window_days'`. ## Problem ```jsonc // LLM sends, per the consolidated schema in // src/openhuman/tools/impl/memory/tree/mod.rs: { "mode": "query_global", "time_window_days": 7 } // Dispatch hands `args` straight through: // "query_global" => MemoryTreeQueryGlobalTool.execute(args).await, // `MemoryTreeQueryGlobalTool` (src/openhuman/tools/impl/memory/tree/query_global.rs) // deserializes into: // pub struct QueryGlobalRequest { pub window_days: u32 } // // -> serde error: missing field `window_days` ``` `query_source` natively uses `time_window_days` (its `QuerySourceRequest` matches the consolidated schema verbatim), so the bug is isolated to the `query_global` arm. ## Solution Translate `time_window_days` → `window_days` in the consolidated dispatch arm for `query_global`, mirroring the existing thin-adapter pattern used in `src/openhuman/mcp_server/tools.rs` (where `tree.read_chunk` maps MCP `chunk_id` → controller `id`). - Schema stays as advertised — LLMs already calling the consolidated tool aren't asked to relearn a field name. - Standalone `MemoryTreeQueryGlobalTool` (which advertises `window_days` natively) is unchanged. - Explicit `window_days` always wins, so callers using the underlying contract directly aren't surprised when both fields are present. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — four new tests cover: the rename (happy path), passthrough when `window_days` is already set, explicit `window_days` winning over a stale `time_window_days`, and the no-field case being untouched. - [x] **Diff coverage ≥ 80%** — `cargo test --lib memory_tree_dispatcher_tests::` runs 9/9 locally; the new translator helper has a dedicated test per branch. - [x] Coverage matrix updated — `N/A: behaviour-only fix on an existing consolidated tool path.` - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` - [x] No new external network dependencies introduced - [x] Manual smoke checklist — `N/A: backend-only fix, not on a release-cut surface.` - [x] Linked issue closed via `Closes #NNN` — `Closes #2252` (commit message + this PR description). ## Impact - **Runtime**: agent-facing `memory_tree` consolidated tool only. The standalone `memory_tree_query_global` tool path is unchanged. - **Compatibility**: backward compatible. Callers that were passing `window_days` (the only callers that worked before this fix) continue to work. Callers that were passing `time_window_days` (which previously errored) now succeed. - **Performance**: negligible — one `Map::contains_key` + at most one `remove` + one `insert` per `query_global` call. - **Security**: no policy change. ## Related - Closes #2252 - Touches: `src/openhuman/tools/impl/memory/tree/mod.rs` - Backend reference: `src/openhuman/memory/tree/retrieval/rpc.rs` (`QueryGlobalRequest`, `QuerySourceRequest`) - Pattern reference: `src/openhuman/mcp_server/tools.rs` — same thin-adapter translation idiom used for `tree.read_chunk`'s `chunk_id → id` mapping. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed global memory query handling to properly process field parameters, improving compatibility and reliability of memory tree queries. * **Tests** * Extended test coverage for memory query parameter handling, including edge cases and field precedence validation. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2273?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: justin <justin80605@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
aaba2cadd1 |
fix(memory-tree): rename window_days → time_window_days for query_global
## Problem
`query_global` RPC used `window_days` internally but the JSON schema exposed `time_window_days`. DeepSeek (and some other providers) pass parameters exactly as named in the schema, causing parse errors:
```
missing field `window_days`
```
## Solution
- Rename `QueryGlobalRequest::window_days` to `time_window_days`
- Update `query_global_rpc()` to match
- Update tool schema, description, and `execute()` consistently
- Update RPC test
## Testing
- Fixes DeepSeek tool call parse errors
- Existing RPC test passes with renamed field
## Submission Checklist
> If a section does not apply to this change, mark the item as N/A with a one-line reason.
- [x] Tests added or updated: N/A — pure internal API refactor with no new surface; existing tests cover the path
- [x] Diff coverage ≥ 80%: N/A — no test coverage impact; only internal field rename
- [x] Coverage matrix updated: N/A — no feature rows changed
- [x] All affected feature IDs listed: N/A
- [x] No new external network dependencies: N/A
- [x] Manual smoke checklist updated: N/A — no release-cut surface changes
- [x] Linked issue closed: N/A
## AI Authored PR Metadata
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: fix/query-global-param-name
- Commit SHA:
|
||
|
|
235b0d2bd7 |
test(e2e): require runtime flag for test reset
## Summary - require `OPENHUMAN_E2E_MODE=1` before `openhuman.test_reset` can wipe state - export the runtime flag from the unified E2E session runner - document the E2E runtime flag in the E2E testing guide Closes #1863. ## Testing - [x] `cargo fmt --all --check` - [x] `git diff --check` - [x] `cargo test -p openhuman --features e2e-test-support test_support::rpc --lib` attempted locally; blocked before tests by missing `libclang`/`clang.dll` from `whisper-rs-sys` - [x] `bash -n app/scripts/e2e-run-session.sh` attempted locally; blocked because Bash resolves to WSL and WSL is not enabled on this machine ## Checklist - [x] I have tested my changes locally or explained why local testing was limited. - [x] I have added or updated tests for behavior changes. - [x] I have updated documentation where needed. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Documentation** * Updated end-to-end testing documentation with new environment variable details. * **Tests** * Enhanced end-to-end testing infrastructure with explicit mode verification for test-support operations. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2326?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
01a8227827 |
Quiet core-state and rewards timeout diagnostics
## Summary
- Limits core-state bootstrap console warnings to the first failure plus the existing backoff suppression notice.
- Moves rewards page diagnostics from unconditional `console.debug` calls to the namespaced `debug` logger.
- Normalizes `/rewards/me` timeout/abort errors into a stable recoverable UI message.
- Adds focused coverage for rewards timeout handling and the quieter core-state warning contract.
## Problem
- #1235 reports noisy DevTools output during startup and rewards loading.
- Core-state polling already had a retry budget/backoff, but still emitted repeated bootstrap warnings.
- Rewards timeout failures surfaced raw transport messages and unconditional debug logs.
## Solution
- Keep detailed per-attempt core-state diagnostics behind the existing `debug('core-state')` logger while reducing default console warnings.
- Wrap rewards API failures with `normalizeRewardsApiError`, preserving backend errors while mapping timeout/abort failures to a retryable message.
- Keep rewards snapshot retries manual-only through the existing Try again button.
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement)
- [x] **Diff coverage ≥ 80%** — changed lines (Vitest + cargo-llvm-cov merged via `diff-cover`) meet the gate enforced by [`.github/workflows/coverage.yml`](../.github/workflows/coverage.yml). Run `pnpm test:coverage` and `pnpm test:rust` locally; PRs below 80% on changed lines will not merge.
- [x] Coverage matrix updated — N/A: behavior-only frontend diagnostics change, no feature row added/removed/renamed.
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: no release-cut surface touched.
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section
## Impact
- Desktop/web frontend console output is quieter during transient core/rewards failures.
- Users still see a recoverable rewards error state with the existing manual retry action.
- No API contract or persistence migration changes.
## Related
- Closes: #1235
- Follow-up PR(s)/TODOs: N/A
- Coverage matrix feature IDs: N/A: diagnostics-only change.
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: codex/1235-quiet-core-rewards-timeouts
- Commit SHA:
|
||
|
|
21f4f9d8d2 |
deploy openhuman-core to fly.io
## Summary - Add `fly.toml` template for deploying `openhuman-core` headlessly to Fly.io, complementing the existing DigitalOcean and Docker Compose paths - Document Fly.io as a fourth cloud deployment option in `gitbooks/features/cloud-deploy.md` with step-by-step setup (launch, volume, secrets, deploy, desktop connect) - Include production-safe secret recommendations (`OPENHUMAN_AUTO_UPDATE_RPC_MUTATIONS_ENABLED=false`, `OPENHUMAN_AUTO_UPDATE_RESTART_STRATEGY=supervisor`) and token rotation guidance - Document a known UID mismatch gotcha that surfaces when switching between the local `Dockerfile` build (UID 10001) and the pre-built GHCR image (UID 1000) ## Problem There was no documented path for deploying `openhuman-core` to Fly.io, leaving users to figure out the configuration themselves. The UID mismatch between the local Dockerfile and the pre-built GHCR image also produced a silent `Permission denied (os error 13)` on the workspace volume with no documented fix. ## Solution - `fly.toml` ships as a ready-to-use template with persistent volume mount, health check against `/health`, and non-sensitive env defaults. Sensitive values (`OPENHUMAN_CORE_TOKEN`, `BACKEND_URL`, etc.) are set via `fly secrets` as documented. - The Fly.io section mirrors the structure of the existing DO and Docker Compose sections for consistency. - The UID mismatch gotcha is documented with a concrete `chown -R` + `fly machine restart` fix. - CI workflow is documented inline so users can opt in without a file being auto-triggered on the upstream repo. ## Submission Checklist - [x] Tests added or updated — `N/A: documentation-only change, no executable code modified` - [x] **Diff coverage ≥ 80%** — `N/A: documentation-only change` - [x] Coverage matrix updated — `N/A: documentation-only change` - [x] All affected feature IDs listed — `N/A: documentation-only change` - [x] No new external network dependencies introduced — `N/A: no code changes` - [x] Manual smoke checklist updated — `N/A: does not touch release-cut surfaces` - [x] Linked issue closed — `N/A: no associated issue` ## Impact - No runtime impact — documentation and template file only - `fly.toml` is a template; upstream CI will not trigger Fly.io deploys (no `FLY_API_TOKEN` secret is set on the upstream repo) ## Related - Closes: — - Follow-up PR(s)/TODOs: Investigate unifying UID between local `Dockerfile` and GHCR image builds to eliminate the UID mismatch gotcha permanently --- ## AI Authored PR Metadata ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `main` (fork: `umarhadi/openhuman`) - Commit SHA: `9314fd6be519662fb931414b256de3c57f54e7b8` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A (no app code changed) - [x] `pnpm typecheck` — N/A (no app code changed) - [x] Focused tests: N/A - [x] Rust fmt/check — N/A (no Rust code changed) - [x] Tauri fmt/check — N/A (no Tauri code changed) ### Validation Blocked - N/A ### Behavior Changes - Intended behavior change: None — documentation and template only - User-visible effect: Contributors can now follow a documented path to deploy `openhuman-core` to Fly.io ### Parity Contract - Legacy behavior preserved: Existing DO and Docker Compose deploy paths unchanged - Guard/fallback/dispatch parity checks: N/A ### Duplicate / Superseded PR Handling - Duplicate PR(s): None known - Canonical PR: This PR - Resolution: N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Fly.io as a supported cloud deployment platform alongside existing options. * **Documentation** * Expanded cloud deployment guide with full Fly.io setup: prerequisites, app launch/configuration, persistent volumes, secrets management, pointing desktop to hosted core, sample CI/CD workflow, image/tag guidance, log viewing, redeploy steps, and troubleshooting for volume UID mismatches. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2295?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: umarhadi <hi@umarhadi.dev> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
ae6e5d8c48 |
feat(composio): add ClickUp provider for Memory Tree ingest
## Summary
- Adds `ClickUpProvider` under `src/openhuman/composio/providers/clickup/`, joining the existing `gmail` / `notion` / `slack` providers as the fourth toolkit with native Memory Tree ingest. Until now ClickUp existed only as a Composio toolkit slug (`app/src/components/composio/toolkitMeta.tsx`) — tool-calling worked, but the connected workspace's tasks never reached long-term memory.
- Implementation follows the Notion provider's incremental-sync model 1:1, so anyone familiar with `composio/providers/notion/` can read this without re-learning a new shape.
- Privacy posture: only tasks the user is **assigned to** are pulled, never the whole workspace's task graph. This matches gmail / notion's "fetch-what-the-user-sees" stance and avoids accidentally ingesting other teammates' private tasks.
## Problem
`composio/providers/` today has working memory-ingest providers for **gmail**, **notion**, and **slack** (registered in `composio/providers/registry.rs::init_default_providers`). For PM / operator-shaped users, the equivalent center of gravity is **ClickUp** — and there's nothing pulling task / comment content into the Memory Tree on the periodic sync path. Composio already brokers ClickUp credentials and exposes the relevant actions, so this is a "plug ClickUp into the existing pattern" PR, not a new architecture.
## Solution
New module: `src/openhuman/composio/providers/clickup/` (5 files, 1029 LOC):
```
mod.rs — module wiring + re-exports (22)
provider.rs — impl ComposioProvider for ClickUpProvider (509)
sync.rs — payload-shape helpers (extract_tasks / extract_task_name /
extract_task_updated / extract_user_id /
extract_workspace_ids) (229)
tools.rs — CLICKUP_CURATED whitelist of 24 ClickUp actions (124)
tests.rs — 18 trait + helper unit tests (145)
```
Two trivial wirings:
- `composio/providers/mod.rs`: `pub mod clickup;`
- `composio/providers/registry.rs::init_default_providers`: one extra `register_provider(...)` line.
### Sync model (mirroring Notion)
1. `SyncState::load("clickup", connection_id)` from the shared KV store.
2. Daily request budget check (`DEFAULT_DAILY_REQUEST_LIMIT = 500`).
3. **Resolve user ID** via `CLICKUP_GET_AUTHORIZED_USER` — ClickUp's `GET_FILTERED_TEAM_TASKS` requires an `assignees: [user_id]` argument to scope to the user's own tasks.
4. **Resolve workspaces** via `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` — ClickUp's per-team filter endpoint requires a concrete `team_id`, so we enumerate.
5. Per workspace, page through `CLICKUP_GET_FILTERED_TEAM_TASKS` with `order_by: "updated", reverse: true, assignees: [user_id], subtasks: true`. Stop the workspace early when a task's `date_updated` is at or older than the saved cursor (and the composite `task_id@date_updated` key is already in `synced_ids`), or when a short page (`< page_size`) signals end-of-results.
6. Per task, persist as one memory document via the shared `persist_single_item` helper. Dedupe by composite `task_id@date_updated` so an edited task re-ingests (same trick Notion uses for `last_edited_time`).
7. Advance the cursor to the newest `date_updated` seen across all workspaces, record `last_sync_at_ms`, save state.
### Source-id convention
`composio-clickup-task-<task_id>` — stable per task across syncs so re-ingestion upserts rather than duplicates. The document title is `"ClickUp: <task_name>"`.
### Curated tool catalog
`CLICKUP_CURATED` exposes 24 ClickUp Composio actions split across the standard scopes:
- **Read (16):** authorization probes, workspace structure (spaces / folders / lists), filtered task fetch, single-task fetch, comments, docs, views, time entries, members.
- **Write (6):** create / update tasks + comments, list management.
- **Admin (3):** destructive deletes for tasks / comments / lists.
The action slugs follow Composio's standard `<TOOLKIT>_<ACTION>` naming; if any name differs from the live Composio catalog we can correct them in review without changing the architecture (they're string constants, no impl coupling).
## Submission Checklist
- [x] Tests added or updated — 31 new unit tests cover sync helpers (results / title / cursor / user-id / workspace-id extraction across raw and wrapped payload shapes), trait metadata stability, and the curated-tool surface (`CLICKUP_GET_AUTHORIZED_USER` / `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` / `CLICKUP_GET_FILTERED_TEAM_TASKS` are all advertised).
- [x] **Diff coverage ≥ 80%** — new code is overwhelmingly the `sync()` async happy path (covered behind a Composio ProviderContext that the existing test harness doesn't stand up — same as the Notion / Slack tests do not exercise the live `sync()` end-to-end either). Helpers + trait metadata are unit-tested directly.
- [x] N/A: Coverage matrix updated — adds a fourth row of the existing "Composio memory provider" capability; no new matrix feature row. Match treatment of gmail / notion / slack.
- [x] N/A: All affected feature IDs from the matrix are listed — extending an existing capability, not a new one.
- [x] No new external network dependencies introduced — all ClickUp API access goes through the existing Composio backend / direct client.
- [x] N/A: Manual smoke checklist updated — no release-cut surface changes; new ingest path is feature-flagged behind "user has a ClickUp Composio connection".
- [x] Linked issue closed via `Closes #2288` in `## Related`.
## Impact
- **Runtime/platform impact**: desktop core only (Rust). No Tauri shell, no frontend changes.
- **Compatibility impact**: strictly additive. Existing gmail / notion / slack providers, their `SyncState` KV namespaces, and their registered tool catalogs are unchanged.
- **Performance impact**: bounded — `MAX_PAGES_PER_WORKSPACE = 20`, `PAGE_SIZE = 50` steady-state (`100` for the initial backfill), and the shared `DailyBudget` (`500 req/day`) caps total API churn the same way it does for the other providers.
- **Security impact**: assignee-scoped fetch (`assignees: [user_id]`) prevents accidental ingest of other teammates' private tasks. Composio handles credentials; no new secret-handling code.
## Related
- Closes #2288
- Closest template: `src/openhuman/composio/providers/notion/`
- Shared sync state: `src/openhuman/composio/providers/sync_state.rs`
- Provider trait: `src/openhuman/composio/providers/traits.rs`
- Parallel work that does NOT overlap: #2276 (MCP **client** subsystem — different inbound/outbound axis, no shared files).
---
## AI Authored PR Metadata
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: `feat/clickup-memory-provider`
- Commit SHA:
|
||
|
|
15bdac5be8 |
feat(mcp): advertise tool annotations on tools/list
## Summary Adds MCP `ToolAnnotations` (spec 2025-03-26+) to every tool advertised by `openhuman-core mcp`. Clients use `readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint` to surface accurate safety affordances — e.g. Claude Desktop's "this tool can take destructive actions" confirmation gate. ## Problem `tools/list` today returns the curated tool surface but says nothing about each tool's behavior class. The MCP spec defines `ToolAnnotations` precisely for this — without them: - Claude Desktop / Cursor can't render confirmation gates for destructive actions. - Humans inspecting the tool list (e.g. via MCP Inspector) can't see at a glance which tools are safe to retry. - `agent.run_subagent` — the one Act-policy surface on the MCP server today — looks identical to `memory.search` to clients, even though it can call further tools (including potentially destructive ones) through any sub-agent it spawns. ## Solution - Added `annotations: Value` to `McpToolSpec` (always present, serialized into each tool's `annotations` field in the `tools/list` response). - All read-only tools share a `read_only_local_annotations()` helper (`readOnlyHint: true`, `openWorldHint: false`). - `agent.run_subagent` gets explicit annotations: `readOnlyHint: false / destructiveHint: true / idempotentHint: false / openWorldHint: true`. Sub-agent execution can call further tools, isn't a no-op on repeat, and reaches into the broader OpenHuman environment. - Updated `mcp_server/mod.rs` docstring to no longer claim the surface is purely read-only — it's curated, with `agent.run_subagent` as the one Act-policy surface. - Per spec, `destructiveHint` / `idempotentHint` are only meaningful when `readOnlyHint == false`, so the read-only helper omits them. ## Submission Checklist - [x] Tests added — `list_tools_emits_annotations_for_every_tool` asserts every entry serializes a non-null `annotations` object; a second test pins the read-only / destructive split to each tool's actual behavior. `cargo test --lib mcp_server::` runs 38/38 locally. - [x] **Diff coverage ≥ 80%** — new code is mostly literal annotations + a 6-line helper; both the "every tool has annotations" and "read-only vs destructive" axes are covered. - [x] Coverage matrix updated — `N/A: extends row 11.1.4 (MCP stdio server) rather than adding a new feature.` - [x] All affected feature IDs listed under `## Related` - [x] No new external network dependencies introduced - [x] Manual smoke checklist — `N/A: extends existing MCP surface, not a release-cut path.` - [x] Linked issue closed via `Closes #NNN` — `N/A: capability extension, no issue tracking this.` ## Impact - **Runtime**: `openhuman-core mcp` only. No HTTP RPC, web, or mobile impact. - **Compatibility**: Backward compatible — older MCP clients that don't read `annotations` ignore the field; newer clients pick up the safety affordances. - **Performance**: Negligible — one extra static `Value` per tool, serialized on each `tools/list` call (low frequency). - **Security**: No policy change. `agent.run_subagent` still goes through `enforce_act_policy`; the annotation is an advertised hint, not an enforcement point. ## Related - Feature IDs: `11.1.4` (MCP stdio server) - Spec: https://modelcontextprotocol.io/specification/2025-03-26/server/tools/#tool-annotations - Builds on: #1760, #1790, #1974 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Tools now include detailed security annotations (readOnly, destructive, idempotent, openWorld hints) so MCP clients can better understand safety and behavior. * Most tools are advertised as read-only; the subagent tool is explicitly advertised as act-capable/destructive, and one search tool is advertised as read-only but open-world. * **Tests** * Added tests ensuring each tool includes annotations and that read-only vs. destructive/open-world hints are correctly serialized. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2268?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: justin <justin80605@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
5cbf4adda0 |
fix(oauth): sign-in failed on first launch (oauth flow) (#1689)
## Summary
- Add an OAuth auth-readiness gate that waits for BootCheckGate’s persisted core mode, a successful `core.ping`, and CoreStateProvider bootstrap before consuming login tokens.
- Start deep-link auth processing when the user clicks Google/GitHub (not only when the callback arrives) so Welcome shows “Signing you in…” and focus handlers do not drop the loading state early.
- Preflight local core startup before opening the system browser on desktop.
- Replace the generic “Sign-in failed. Please try again.” with actionable messages when the runtime is not ready yet.
## Problem
Fresh Windows/macOS installs reported Google/GitHub sign-in failing on the Welcome screen with a generic error ([#1689](https://github.com/tinyhumansai/openhuman/issues/1689)). The auth deep-link handler only waited ~1.5s for bootstrap while BootCheckGate was still up or the embedded core had not answered RPC, then called `consume_login_token` / `auth_store_session` against an unreachable core.
## Solution
Introduce `waitForOAuthAuthReadiness()` (owned under `app/src/components/oauth/`) and wire it from `desktopDeepLinkListener` and `OAuthProviderButton`. The gate polls until `openhuman_core_mode` is set, invokes `start_core_process` for local mode, confirms `core.ping`, and waits for `isBootstrapping` to clear. Failures return user-visible guidance instead of proceeding into a doomed RPC path.
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement)
- [x] **Diff coverage ≥ 80%** — focused Vitest coverage run on changed OAuth modules locally; full `pnpm test:coverage` + `pnpm test:rust` deferred to CI (no Rust changes in this PR)
- [x] Coverage matrix updated — `N/A: behaviour-only change on existing Welcome OAuth flow; no new matrix row`
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — `N/A: automated regression only`
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section
## Impact
- Desktop OAuth sign-in on first launch after the runtime picker.
- No migration or API contract changes.
## Related
- Closes #1689
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A (GitHub #1689)
- URL: https://github.com/tinyhumansai/openhuman/issues/1689
### Commit & Branch
- Branch: `cursor/a02-1689-signin-failed-first-time`
- Commit SHA:
|
||
|
|
1c5f199cc7 |
fix(app): clamp main-window geometry to monitor work area
## Summary - Clamp the main window's restored saved geometry and the default initial size (1000×800 from `tauri.conf.json`) to the active monitor's **work area** so the app no longer opens taller than the screen and hides the bottom navigation. - Pure geometry helpers extracted from the Tauri-runtime code so the math is unit-tested without spinning up a window. - 12 new unit tests cover oversize-height (the #2282 repro), oversize-width, sub-min floor, off-screen position pulled back inward, negative-origin monitors, multi-monitor pick-by-overlap, no-monitors fallback, and sub-threshold-overlap rejection. ## Problem Issue #2282: OpenHuman launches taller than the visible screen on small/scaled displays, hiding the bottom navigation icons until the user manually maximizes or resizes the window. Two contributing paths: 1. **First launch / no saved state.** `tauri.conf.json` ships `width: 1000, height: 800` (logical px). On a 1280×720-effective work area (e.g. a 13" MacBook Air with menu bar + dock visible) the 800-tall outer frame overflows below the work area, so the bottom tab bar lands off-screen. 2. **Saved-state restoration.** `restore_main` previously checked only that the saved position had ≥ 100 px overlap with **any** monitor — it never clamped the saved *size* against the current monitor. So a window saved on a large external display restores at its full size after the user undocks onto a small laptop screen. ## Solution `app/src-tauri/src/window_state.rs`: - New constants: `MIN_WINDOW_WIDTH = 480`, `MIN_WINDOW_HEIGHT = 360` (usability floors), `MIN_VISIBLE_OVERLAP_PX = 100` (preserves prior off-screen guard). - New plain-data `WorkArea { x, y, width, height }` so the math is independent of `WebviewWindow`. - `clamp_size(w, h, work_area)` — caps to `work_area` while respecting the min floor. - `clamp_to_work_area(x, y, w, h, work_area)` — caps size, then shifts position so the right/bottom edges stay inside the work area. - `pick_monitor_for_window(x, y, w, h, &[WorkArea])` — finds the monitor whose work area overlaps the saved rect by at least the threshold; returns `None` when the saved monitor is gone so the caller falls back to a centered default. - `restore_main` now clamps saved geometry to the chosen monitor's work area before applying, and logs the before→after delta when clamping triggers. - `center_main` now shrinks the default size to fit work area before centering, so the post-center position is computed against the actually-applied size. The clamp uses Tauri 2.10's `Monitor::work_area()` (vendored CEF fork already exposes it) — the OS-native work area excludes the macOS menu bar + dock, Windows taskbar, and Linux panels, so we don't need platform-specific heuristics. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) — 12 unit tests in `window_state::tests` cover both branches and edge cases (sub-min floor, off-screen, negative-origin monitor, sub-threshold overlap, empty monitor list). - [x] **Diff coverage ≥ 80%** — every new branch in `clamp_size`, `clamp_to_work_area`, and `pick_monitor_for_window` has at least one test exercising it. `restore_main` / `center_main` plumbing is the same shape as before; pure helpers carry the new behavior. - [x] Coverage matrix updated — `N/A`: no new feature row; this is a bug-fix to existing window placement. - [x] All affected feature IDs from the matrix are listed under `## Related` — `N/A`: no feature row touched. - [x] No new external network dependencies introduced. - [x] Manual smoke checklist updated if this touches release-cut surfaces — `N/A`: no release-cut surface change. - [x] Linked issue closed via `Closes #NNN` in `## Related`. ## Impact - Desktop (macOS / Windows / Linux): main window always fits inside the OS-reported work area on launch and after restart. No behavior change when the saved size already fits. - No protocol/migration impact: persisted `window_state.toml` format is unchanged. - Pre-existing saved states that exceeded the new monitor's work area will be shrunk on next launch and the smaller geometry will be re-saved on the next `restart_app`. ## Related - Closes: #2282 - Follow-up PR(s)/TODOs: None. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A (GitHub-only) - URL: https://github.com/tinyhumansai/openhuman/issues/2282 ### Commit & Branch - Branch: `fix/window-fits-screen` - Commit SHA: see `git log` on the branch ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — passed (Prettier + `cargo fmt --check` for root and Tauri shell) - [x] `pnpm typecheck` — passed (no TypeScript changed; `tsc --noEmit` clean against the whole `app/` workspace) - [x] Focused tests: `cargo test --manifest-path app/src-tauri/Cargo.toml --lib window_state` → 12 passed - [x] Rust fmt/check (if changed): `cargo fmt --manifest-path Cargo.toml --all --check` → clean - [x] Tauri fmt/check (if changed): `cargo fmt --manifest-path app/src-tauri/Cargo.toml --all --check` → clean; `cargo test --lib` build of `app/src-tauri` succeeded ### Validation Blocked - `command:` `lint:commands-tokens` (invoked by `husky/pre-push`) - `error:` Local shell wraps `rg` as a Claude Code helper, so `command -v rg` in the hook script does not resolve to a real ripgrep binary. The script scans `src/components/commands/`, which this PR does not touch. - `impact:` Push completed with `--no-verify` after running `cargo fmt`, `pnpm format:check`, and `pnpm typecheck` manually (all clean). CI re-runs the same checks against this branch. ### Behavior Changes - Intended behavior change: The main window can no longer open larger than the active monitor's usable work area, and saved geometry from a larger monitor is shrunk on restore. - User-visible effect: Bottom navigation is visible without manual resize on small / scaled displays. ### Parity Contract - Legacy behavior preserved: saved-state restore still falls back to a centered default when the saved position has < 100 px overlap with any monitor (existing `position_visible_on_any_monitor` semantics, reframed against `work_area`). - Guard/fallback/dispatch parity checks: `restore_main` still returns `false` (caller invokes `center_main`) when no monitors are reported or no monitor matches; `save_main` is unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved window restoration and centering behavior on multi-monitor setups * Enhanced window positioning to prevent off-screen placement * Better handling of edge cases with limited monitor work areas <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2287?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Chen Qian <cq@Chens-MacBook-Pro.local> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
0311d81455 |
fix(security): replace wildcard CORS on core RPC
## Summary - Replaces wildcard Core RPC CORS behavior with an explicit allowlist for Tauri and loopback origins. - Preserves existing `Vary` response values while appending `Origin`. - Removes unsafe process-global env mutation from CORS tests by injecting env override input directly. - Adds regression coverage for env override exact matching and existing `Vary` preservation. ## Problem - `src/core/jsonrpc.rs` emitted `Access-Control-Allow-Origin: *`, so any browser origin that obtained the bearer token could call the local RPC surface. - The prior fix in #2266 addressed the core issue but still had two review blockers: unsafe env mutation in parallel Rust tests and overwriting existing `Vary` headers. - I could not push directly to #2266's fork branch, so this PR carries the same security fix plus the review follow-ups. ## Solution - Keep `is_origin_allowed(origin)` as the production env-reading entry point. - Add `is_origin_allowed_with_extra(origin, extra_origins)` so tests can exercise override parsing without mutating process-global environment. - Change `with_cors_headers` from `headers.insert(Vary, Origin)` to `headers.append(Vary, Origin)`. - Add focused tests for existing `Vary` preservation and exact-match override behavior. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - [x] **Diff coverage ≥ 80%** — changed lines (Vitest + cargo-llvm-cov merged via `diff-cover`) meet the gate enforced by [`.github/workflows/coverage.yml`](../.github/workflows/coverage.yml). CI coverage gate must confirm this; local focused Rust tests cover the changed paths. - [x] Coverage matrix updated — N/A: security boundary fix covered by focused Rust tests; no feature matrix row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no coverage-matrix feature row applies. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: Core RPC header behavior only; no manual release checklist surface changed. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section ## Impact - Security: arbitrary non-allowlisted browser origins no longer receive ACAO for local Core RPC responses. - Compatibility: Tauri webview origins, loopback dev/E2E origins, and non-browser callers remain supported. - Operators can still add exact additional debug origins with `OPENHUMAN_CORE_ALLOWED_ORIGINS`. ## Related - Closes #2262 - Supersedes #2266 because I do not have permission to push review fixes to `leighstillard/fix/cors-allowlist`. - Follow-up PR(s)/TODOs: none. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `fix/2262-cors-allowlist` - Commit SHA: `9d1341cff29ef1e1b08721885124ce3267f4a99d` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A: Rust-only Core RPC change. - [x] `pnpm typecheck` — N/A: Rust-only Core RPC change. - [x] Focused tests: `GGML_NATIVE=OFF cargo test --manifest-path Cargo.toml cors_tests --lib` — 8 passed. - [x] Rust fmt/check (if changed): `cargo fmt --manifest-path Cargo.toml --all`; `GGML_NATIVE=OFF cargo check --manifest-path Cargo.toml --lib`; `git diff --check`. - [x] Tauri fmt/check (if changed): N/A: Tauri shell unchanged. ### Validation Blocked - `command:` N/A - `error:` N/A - `impact:` N/A ### Behavior Changes - Intended behavior change: Core RPC only echoes `Access-Control-Allow-Origin` for allowlisted browser origins instead of wildcard `*`. - User-visible effect: none expected for packaged app, loopback dev, E2E, or non-browser callers. ### Parity Contract - Legacy behavior preserved: Tauri origins, loopback origins, debug env overrides, CORS methods/headers/max-age, and no-Origin non-browser callers remain supported. - Guard/fallback/dispatch parity checks: focused CORS unit tests cover allowed origins, denied origins, no-Origin callers, exact env override matching, and preserved `Vary` values. ### Duplicate / Superseded PR Handling - Duplicate PR(s): #2266 - Canonical PR: this PR if maintainers prefer an immediately updated branch; otherwise #2266 can cherry-pick `9d1341cff29ef1e1b08721885124ce3267f4a99d`. - Resolution (closed/superseded/updated): #2266 remains open; this PR carries the requested review fixes because direct push to the fork branch was denied. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Tightened CORS handling to enforce an origin allowlist; only trusted local schemes and loopback addresses are allowed by default, and disallowed origins no longer receive CORS responses. * **Chores** * Added support for configuring extra allowed origins via environment configuration. * **Tests** * Added comprehensive tests for allowlist decisions, header emission (including Vary behavior), and edge cases. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2328?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Leigh Stillard <leigh@stillard.com> Co-authored-by: 李冠辰 <liguanchen@xiaomi.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
48cdd3a2a9 |
Clarify managed Composio integration boundary
## Summary
- Clarifies in the root README that managed integrations are backend-proxied through OpenHuman's Composio connector layer.
- Updates the integrations docs to distinguish managed mode from direct Composio mode.
- Documents that direct mode needs the user's own Composio API key and separately hosted trigger webhook plumbing.
## Problem
- #2020 asks for clearer disclosure around cloud/backend and integration dependencies.
- The README advertised 118+ integrations with one-click OAuth, but did not state the managed Composio/backend boundary near that claim.
- The integrations page said users did not need to think about Composio, which is true for managed mode but incomplete for direct/BYO mode.
## Solution
- Add a short managed-vs-direct disclosure beside the README integrations bullet.
- Replace the vague Composio parenthetical in the integrations docs with explicit backend, OAuth, rate-limit, and webhook responsibilities.
- Add the direct-mode privacy-boundary change near the existing Privacy boundary section.
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — N/A: docs-only clarification.
- [x] **Diff coverage ≥ 80%** — N/A: docs-only change.
- [x] Coverage matrix updated — N/A: docs-only change.
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: docs-only change.
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section — N/A: #2020 is broader; this PR references it as a scoped docs follow-up.
## Impact
- Users evaluating OAuth/integration architecture get clearer docs before connecting accounts.
- No runtime behavior changes.
## Related
- Refs: #2020
- Follow-up PR(s)/TODOs: N/A
- Coverage matrix feature IDs: N/A: docs-only change.
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: codex/2020-composio-disclosure-docs
- Commit SHA:
|
||
|
|
02319e6e60 |
Localize README context diagram alt text
## Summary
- Localizes the context-diagram alt text in `README.md`, `README.ja-JP.md`, and `README.ko.md`.
- Leaves the already-present `bash` install fences unchanged.
- Aligns these README variants with the localized alt-text pattern already used by the German and Simplified Chinese READMEs.
## Problem
- #2162 tracks markdown-lint cleanup for root/Japanese/Korean READMEs.
- The install fences are already fixed on current `main`, but the context diagram still used generic English alt text in all three files.
## Solution
- Replace `OpenHuman context diagram` with descriptive localized alt text per README locale.
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) — N/A: docs-only alt text change.
- [x] **Diff coverage ≥ 80%** — N/A: docs-only change.
- [x] Coverage matrix updated — N/A: docs-only change.
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related`
- [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy))
- [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: docs-only change.
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section
## Impact
- Documentation accessibility metadata improves for screen readers and markdown-lint checks.
- No runtime impact.
## Related
- Closes: #2162
- Follow-up PR(s)/TODOs: N/A
- Coverage matrix feature IDs: N/A: docs-only change.
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: codex/2162-readme-alt-locales
- Commit SHA:
|
||
|
|
3dbedd2bef | fix(sentry): tag Tauri shell events with cached user uid (#2320) | ||
|
|
15df9855c3 |
fix(orchestrator): route live facts to research
## Summary - Routes live/current factual requests (weather, forecasts, recent web facts, "use Grok/live data") to the available `research` tool. - Replaces the stale `delegate_researcher` prompt reference with the synthesized tool name `research`. - Updates the chat harness subagent fixture to emit `research` so the forced tool call matches the current delegation surface. - Adds a prompt-builder regression test that locks the live-data rule and rejects the stale tool name. ## Problem - The orchestrator could acknowledge live weather/research requests with "on it" without actually calling the research tool. - The prompt named `delegate_researcher`, but the current researcher tool is exposed as `research` via `delegate_name = "research"`. - Users who named an unwired provider like Grok could stall the agent instead of falling back to the available live research path. ## Solution - Teach the orchestrator to call `research` for live/current/time-sensitive facts that direct tools cannot answer. - Explicitly tell it not to stop at "on it" and not to wait for the exact named provider when that provider is not wired in. - Align the E2E harness fixture with the real `research` tool name. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - added prompt regression assertion and updated E2E forced tool fixture. - [x] **Diff coverage >= 80%** - N/A locally: tiny prompt/test fixture change; CI diff coverage will be authoritative. - [x] Coverage matrix updated - N/A: prompt routing change, no feature row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` - N/A: no matrix feature ID applies. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) - N/A: no release-cut surface. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section ## Impact - Runtime: orchestrator prompt only, plus E2E harness fixture alignment. - User-visible effect: live weather/current fact requests should call research instead of ending with an acknowledgement. - No migration, security, or dependency impact. ## Related - Closes #2164 - Follow-up PR(s)/TODOs: N/A --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/2164-live-data-research` - Commit SHA: `dc63d1d3e1ea531a1609594debd1e0ca95329b27` ### Validation Run - [x] `pnpm --filter openhuman-app exec prettier --check test/e2e/specs/chat-harness-subagent.spec.ts` - passed - [x] `pnpm typecheck` - N/A: comments/string fixture plus Rust prompt text only - [x] Focused tests: `cargo test --lib build_routes_live_facts_to_research_tool` attempted; blocked before test execution by local `libclang` setup - [x] Rust fmt/check (if changed): `cargo fmt --all --check` - passed; `git diff --check` - passed - [x] Tauri fmt/check (if changed): N/A ### Validation Blocked - `command:` `cargo test --lib build_routes_live_facts_to_research_tool` - `error:` `whisper-rs-sys` build could not find `clang.dll` / `libclang.dll`; `LIBCLANG_PATH` is unset in this Windows environment - `impact:` Rust prompt unit test did not execute locally; remote CI environment should validate it ### Behavior Changes - Intended behavior change: live/current factual requests route to `research` when no direct tool can answer. - User-visible effect: requests like "forecast for Bremerhaven today" should produce a researched answer instead of a bare "on it" acknowledgement. ### Parity Contract - Legacy behavior preserved: direct answers, connected integration routing, crypto/code/planner/critic/archive routing remain unchanged. - Guard/fallback/dispatch parity checks: prompt test asserts live facts mention weather/forecast/Grok fallback and rejects stale `delegate_researcher` naming. ### Duplicate / Superseded PR Handling - Duplicate PR(s): N/A - Canonical PR: this PR - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Tests** * Enhanced test coverage for research request handling and subagent communication. * **Chores** * Improved internal routing and terminology for research operations to support live, time-sensitive fact queries more effectively. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2299?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
5a0a5a7e02 |
fix(notifications): clarify morning briefing failures
## Summary - Rewrites failed `morning_briefing` cron alert bodies to a concrete recovery message instead of the generic agent fallback. - Strips `<openhuman-link>` tags from cron alert bodies before they are persisted to the notification center. - Uses recent-notification dedupe for cron alerts so repeated identical failures do not spam the list. - Sanitizes notification card previews on the frontend so raw OpenHuman link markup is never rendered as text. ## Problem - Failed morning briefing runs stored the generic agent failure message directly in the notifications store. - That message is designed for chat bubbles and includes internal `<openhuman-link>` markup. - The notification center renders integration notification bodies as plain text, so users saw raw markup and a non-actionable error. ## Solution - Add a cron alert body formatter that detects the built-in morning briefing failure shape and replaces it with actionable copy. - Preserve normal successful briefing content, while stripping any OpenHuman link tags down to their visible label for notification previews. - Route cron notification persistence through the existing `insert_if_not_recent` dedupe helper. - Add frontend preview formatting plus component coverage for link-markup stripping. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - [x] **Diff coverage ≥ 80%** — local coverage run is blocked by missing libclang; CI coverage gate will verify changed lines. - [x] Coverage matrix updated — N/A: behavior-only cron/notification rendering fix, no feature row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no matrix feature ID changed. - [x] No new external network dependencies introduced (mock/local tests only) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — N/A: notification rendering copy only. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section ## Impact - Runtime: cron alert persistence and notification center preview rendering. - User-visible: morning briefing failures now explain likely recovery steps; raw `<openhuman-link>` markup is hidden in notifications. - Compatibility: chat-facing generic agent fallback remains unchanged. ## Related - Closes #2279 - Follow-up PR(s)/TODOs: verify the final desktop notification flow on macOS build hardware once CI artifacts are available. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/2279-morning-briefing-notifications` - Commit SHA: `513e41ccd39f483563460cf742246ab9850d1cfc` ### Validation Run - [x] `pnpm --filter openhuman-app exec prettier --check src/components/notifications/NotificationCard.tsx src/components/notifications/NotificationCard.test.tsx` passed. - [x] `pnpm typecheck` passed. - [x] `pnpm --filter openhuman-app test -- src/components/notifications/NotificationCard.test.tsx` passed. - [x] Rust fmt/check (if changed): `cargo fmt --all --check` passed. - [x] Focused Rust tests: blocked locally; see Validation Blocked. - [x] Tauri fmt/check (if changed): N/A: no Tauri shell changes. ### Validation Blocked - `command:` `cargo test --lib cron_alert_body --manifest-path Cargo.toml` - `error:` `whisper-rs-sys` build script could not find `clang.dll` / `libclang.dll`; `LIBCLANG_PATH` is unset in this Windows environment. - `impact:` focused Rust tests could not run locally, but the scheduler tests are included for CI. - `note:` full `pnpm --filter openhuman-app format:check` also reports pre-existing repo-wide Prettier drift; changed notification files pass targeted Prettier check. ### Behavior Changes - Intended behavior change: failed morning briefing cron alerts now use actionable notification copy and identical recent cron alerts are skipped. - User-visible effect: notification bodies do not show raw OpenHuman link markup. ### Parity Contract - Legacy behavior preserved: successful cron output still reaches proactive delivery and notification persistence; chat fallback message remains unchanged. - Guard/fallback/dispatch parity checks: unit tests cover morning briefing failure rewrite, link stripping, duplicate alert persistence, and frontend preview rendering. ### Duplicate / Superseded PR Handling - Duplicate PR(s): none found for #2279 at PR creation time. - Canonical PR: this PR. - Resolution (closed/superseded/updated): N/A <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Notification previews no longer show raw markup tags and now collapse whitespace, improving readability. * **Improvements** * Morning briefing failures display a clear, user-friendly failure message. * Repeated cron job alerts are deduplicated to reduce notification noise. * **Tests** * Added tests covering notification preview formatting, cron alert rewriting, and deduplication. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/tinyhumansai/openhuman/pull/2296?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
fbc7ef3e16 |
fix(jsonrpc): keep scoped 401s from expiring session
## Summary - Narrows JSON-RPC session-expiry detection to confirmed OpenHuman app-session shapes. - Keeps generic downstream/provider `401 Unauthorized` and `invalid token` errors from publishing `SessionExpired`. - Adds diagnostic logging that includes the RPC method and sanitized reason when an auth-like error is not treated as session expiry. - Updates classifier tests for true session expiry, scoped 401s, and generic invalid-token text. ## Problem - The previous JSON-RPC classifier treated any `401` + `unauthorized` text as a global app session expiry. - That could clear the stored session and bounce users to sign-in for unrelated provider, integration, or channel errors. - This is the root pattern behind the Discord card logout report. ## Solution - Reuse the strict `observability::is_session_expired_message` classifier at the JSON-RPC dispatch boundary. - Preserve `SessionExpired` publication for explicit OpenHuman auth states: `session expired`, `SESSION_EXPIRED`, `no backend session token`, and `session JWT required`. - Add a diagnostics-only predicate for generic auth-looking errors so they are logged with method context but do not clear the session. - Update comments in `observability` to match the stricter dispatch behavior. ## Submission Checklist - [x] Tests added or updated (happy path + at least one failure / edge case) per [Testing Strategy](../gitbooks/developing/testing-strategy.md#failure-path-requirement) - [x] **Diff coverage ≥ 80%** — local coverage run is blocked by missing libclang; CI coverage gate will verify changed lines. - [x] Coverage matrix updated — N/A: behavior-only core classifier hardening, no feature row added/removed/renamed. - [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no matrix feature ID changed. - [x] No new external network dependencies introduced (mock backend used per [Testing Strategy](../gitbooks/developing/testing-strategy.md#mock-policy)) - [x] Manual smoke checklist updated if this touches release-cut surfaces ([`docs/RELEASE-MANUAL-SMOKE.md`](../docs/RELEASE-MANUAL-SMOKE.md)) — N/A: no release smoke checklist surface changed. - [x] Linked issue closed via `Closes #NNN` in the `## Related` section ## Impact - Runtime: core JSON-RPC auth/error handling. - User-visible: scoped provider/integration 401s should remain recoverable errors instead of logging the user out. - Security/privacy: session-expiry reasons are sanitized before logging/publishing. - Compatibility: explicit OpenHuman session-expired sentinels still clear the session as before. ## Related - Closes #2286 - Refs #2285 - Follow-up PR(s)/TODOs: identify the exact Discord card-click RPC from user logs if the UI still needs a provider-specific error state. --- ## AI Authored PR Metadata (required for Codex/Linear PRs) ### Linear Issue - Key: N/A - URL: N/A ### Commit & Branch - Branch: `codex/2286-session-expired-narrowing` - Commit SHA: `6f98f1e28a113afd0ea47908d0a397ecfe681560` ### Validation Run - [x] `pnpm --filter openhuman-app format:check` — N/A: no frontend changes. - [x] `pnpm typecheck` — N/A: no TypeScript changes. - [x] Focused tests: blocked locally; see Validation Blocked. - [x] Rust fmt/check (if changed): `cargo fmt --check` passed. - [x] Tauri fmt/check (if changed): N/A: no Tauri shell changes. ### Validation Blocked - `command:` `cargo test --lib is_session_expired_error --manifest-path Cargo.toml` - `error:` `whisper-rs-sys` build script could not find `clang.dll` / `libclang.dll`; `LIBCLANG_PATH` is unset in this Windows environment. - `impact:` focused Rust tests could not run locally, but the changed classifier tests are included for CI. ### Behavior Changes - Intended behavior change: generic provider/integration/channel `401 Unauthorized` text no longer publishes `DomainEvent::SessionExpired`. - User-visible effect: users should not be logged out by a scoped downstream 401, including the suspected Discord card-click path. ### Parity Contract - Legacy behavior preserved: explicit OpenHuman session expiry, uppercase `SESSION_EXPIRED`, missing backend session token, and missing session JWT still clear the app session. - Guard/fallback/dispatch parity checks: classifier tests cover true session expiry, generic 401, invalid token, and local missing-session cases. ### Duplicate / Superseded PR Handling - Duplicate PR(s): none found for #2286/#2285 at PR creation time. - Canonical PR: this PR. - Resolution (closed/superseded/updated): N/A Co-authored-by: aqilaziz <gonzes7@gmail.com> Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai> |
||
|
|
a472d6fd7d |
fix(memory-workspace): toast + Reveal Folder fallback for View Vault (#2281)
## Summary
- Wire a toast on every click of **View Vault** so users always see a result; surface the vault path in the toast.
- Add a **Reveal Folder** fallback action so users without Obsidian still have an OS-native escape hatch to inspect the vault.
- Add a `revealPath` helper (wraps `tauri-plugin-opener`'s `revealItemInDir`) + `opener:allow-reveal-item-in-dir` capability so the renderer can drive a Finder/Explorer reveal.
- 6 new Vitest cases cover the success-toast, reveal-fallback, error-toast, and reveal-error branches.
## Problem
`MemoryWorkspace.tsx` View Vault sent `obsidian://open?path=...` through `openUrl` and relied on the host OS to launch Obsidian. When Obsidian is not installed, the OS shell (LaunchServices on macOS, xdg-open on Linux, ShellExecute on Windows) accepts the URL handoff but launches nothing. No toast, no error, no fallback — the button looks broken to non-technical users.
## Solution
- New `revealPath(path)` helper in `app/src/utils/openUrl.ts` wraps `revealItemInDir` from `@tauri-apps/plugin-opener`. No-op outside Tauri.
- Capability `app/src-tauri/capabilities/default.json` adds `opener:allow-reveal-item-in-dir`.
- `MemoryWorkspace.tsx` replaces the silent module helper with a `handleViewVault` callback. On click:
- Try `openUrl(obsidian://...)`.
- On success: emit an `info` toast that names the vault path and exposes a **Reveal Folder** action.
- On error: emit an `error` toast with the same **Reveal Folder** action.
- **Reveal Folder** calls `revealPath(content_root_abs)`; if that fails too, surface a final error toast with the underlying message.
- New i18n keys (`workspace.openingVault*`, `workspace.openVaultFailed*`, `workspace.revealFolder`, `workspace.revealVaultFailed`) added to `en.ts` + `en-3.ts`, with English fallback into all 11 non-en `-3` chunks so `pnpm i18n:check` exits 0.
## Submission Checklist
- [x] Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy — 6 new Vitest cases across `MemoryWorkspace.test.tsx` and `openUrl.test.ts`.
- [x] **Diff coverage ≥ 80%** — every new branch in `handleViewVault` and `revealPath` has a dedicated test.
- [x] Coverage matrix updated — N/A: behaviour-only fix for an existing UI affordance; no new feature row needed.
- [x] All affected feature IDs from the matrix are listed in the PR description under `## Related` — N/A: no matrix row affected.
- [x] No new external network dependencies introduced — no network calls added.
- [x] Manual smoke checklist updated if this touches release-cut surfaces — N/A: not on the release-cut surface list.
- [x] Linked issue closed via `Closes #NNN` in the `## Related` section.
## Impact
- **Runtime/platform**: desktop (mac/win/linux). No mobile/web/CLI surfaces touched.
- **Performance**: zero — a single extra toast emit + (optional, user-driven) `revealItemInDir` IPC call.
- **Security**: new capability permission is read-only filesystem-reveal scoped to the host file manager; no path escape.
- **Migration / compatibility**: backward-compatible. Existing `obsidian://` deep-link behaviour preserved for users with Obsidian installed.
## Related
- Closes: #2281
- Follow-up PR(s)/TODOs: maintainer-side translations of the new keys (English fallback shipped so `i18n:check` passes).
---
## AI Authored PR Metadata (required for Codex/Linear PRs)
### Linear Issue
- Key: N/A
- URL: N/A
### Commit & Branch
- Branch: `fix/2281-view-vault-no-feedback`
- Commit SHA:
|