mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
f098cfda405362e4da71cc43378e7fa22a1f82f2
1141
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f098cfda40 |
test(coverage): batches 13–18 — Rust unit tests for 40+ modules (#530) (#618)
* test(coverage): batch 13–14 — core/all registry, proxy_config tool (#530) Add 36 new tests: - core/all: registry integrity (no duplicates, schema-controller parity), rpc_method_name, namespace_description, validate_params, schema lookup - proxy_config: parse_scope, parse_string_list (CSV, array, errors), parse_optional_string_update, env_snapshot, proxy_json, security gates All 4096 tests pass. * test(coverage): batch 15 — memory/store/unified/helpers pure functions (#530) Add 31 new tests for helpers module: - vec_to_bytes/bytes_to_vec roundtrip, cosine_similarity (identical, orthogonal, mismatched, zero), collapse_whitespace, normalize_search_text, tokenize_search_terms, normalize_graph_entity/predicate, json_string_array, merge_unique_string_arrays, json_i64 (int/float/missing/string), recency_score (current/old/future), chunk_document_content All 4127 tests pass. * test(coverage): batch 16 — terminal, supervision, security detect, trigger history (#530) Add 27 new tests across 4 modules: - accessibility/terminal: is_text_role, is_terminal_app, looks_like_terminal_buffer, extract_terminal_input_context, noise line detection - channels/runtime/supervision: compute_max_in_flight_messages clamping - security/detect: all sandbox backend fallback paths (landlock, firejail, bubblewrap, docker on non-linux), disabled-via-enabled-false - composio/trigger_history: list_recent with limit, empty store, field validation All 4154 tests pass. * test(coverage): batch 17 — learning, update, encryption, doctor, service schemas + skills/types (#530) Add 49 new tests across 6 modules: - learning/schemas: catalog, schema validation, unknown fallback - update/schemas: check/apply schemas, optional staging_dir, controller parity - encryption/schemas: encrypt/decrypt schemas, read_required helper - doctor/schemas: report/models schemas, read_optional helper (none/null/value/error) - service/schemas: 8 lifecycle functions, restart optional params, daemon_host - skills/types: ToolResult success/error/json/mixed, serde roundtrip, ToolContent All 4203 tests pass. * test(coverage): batch 18 — accessibility/keys key-state probes (#530) Add tests for is_tab_key_down/is_escape_key_down (platform-safe), macOS-specific constant validation. All 4216 tests pass. * test(coverage): batch 19 — service/restart, memory/store/factories (#530) Add 7 new tests: - service/restart: default source/reason, whitespace trimming, empty-string defaults, RestartStatus serde, startup delay noop - memory/store/factories: effective_memory_backend_name, migration-disabled error All 4223 tests pass. * test(coverage): batch 20 — tree_summarizer schemas, subconscious schemas (#530) Add 38 new tests across 2 modules: - tree_summarizer/schemas: catalog parity, all 5 functions, param helpers (read_required, read_optional, read_optional_timestamp), type_name, namespace_input - subconscious/schemas: catalog parity, all 10 functions, required input validation, field/field_req/field_opt helpers All 4261 tests pass. --------- Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com> |
||
|
|
ec309c8f90 |
feat(onboarding): complete conversational onboarding stack and UX audit (#619)
* fix(onboarding): guard complete_onboarding against premature flag flip (#591) - Remove premature `chat_onboarding_completed = true` flip from `set_onboarding_completed` in config/ops.rs. The flag is now exclusively owned by the welcome agent via `complete_onboarding`. - Strip auto-finalize side-effect from `check_status` action. It is now pure read-only and returns `onboarding_status`, `exchange_count`, and `ready_to_complete` in the snapshot instead of `finalize_action`. - Add engagement guard to `complete` action: rejects with a descriptive error unless exchange_count >= 3 OR ≥1 Composio integration connected. Auth check also enforced before any write. - Add process-global `WELCOME_EXCHANGE_COUNT` (AtomicU32) with `increment_welcome_exchange_count()` / `get_welcome_exchange_count()`. Dispatch layer calls `increment_welcome_exchange_count()` each time a user message routes to the welcome agent. - Update `welcome_proactive.rs` snapshot call to new signature and prompt copy to reflect `onboarding_status: "pending"` / no pre-flip. - Add 7 pure-logic unit tests for `engagement_criteria_met`, plus tests for the new exchange counter and updated snapshot shape. Fixes #591 * style: cargo fmt for complete_onboarding.rs * feat(onboarding): inject CONNECTION_STATE block into welcome-agent turns (#593) Add `build_connection_state_block()` to dispatch.rs: fetches current Composio integration status (with a 3s timeout for graceful degradation) and formats it as a `[CONNECTION_STATE]...[/CONNECTION_STATE]` block. After `resolve_target_agent` selects the welcome agent, the block is appended to the last user message in history so the agent always has up-to-date connection state without spending a tool call. This captures OAuth completions that happened mid-conversation (user clicked auth link in chat, authenticated in browser, came back). Scoped strictly to welcome-agent turns (chat_onboarding_completed=false). Orchestrator turns are unaffected. Fixes #593 Part of #599 * style: cargo fmt for dispatch.rs * feat(welcome): parallel template messages with LLM inference for faster perceived welcome (#592) Show two template messages immediately while the LLM runs in the background, cutting the perceived wait from ~15s to ~0s: - Template 1 (t≈0ms): time-of-day greeting that names any connected channels, built from the status snapshot without extra I/O - Template 2 (t=4s): "Getting everything ready for you..." loading indicator, published via tokio::join! alongside the LLM future - LLM response: published when inference completes, opened directly with personalised setup content (no duplicate greeting) `run_proactive_welcome` now fires three `ProactiveMessageRequested` events rather than one. The two template helpers (`time_of_day_greeting`, `build_template_greeting`) are pure functions covered by 6 new unit tests. `prompt.md` gains a proactive-invocation section explaining that greeting templates are pre-delivered and the agent must skip them. * feat(welcome): add composio_authorize tool and inline auth link guidance (#594) Wire `composio_authorize` into the welcome agent's tool allowlist and teach the prompt how to offer OAuth links directly in chat: - agent.toml: add "composio_authorize" to the named tools list so the welcome agent can call it during multi-turn conversations - prompt.md: new "Offering inline auth links" section covering the consent-first flow (offer → user agrees → call tool → markdown link → confirm success via [CONNECTION_STATE] block on next turn) - prompt.md: toolkit slug reference table for the common services - prompt.md: auth link rules (no speculative calls, no bare URLs, one service at a time, await CONNECTION_STATE before confirming) - prompt.md: two new "What NOT to do" bullets for composio_authorize misuse patterns * feat(welcome): conversational onboarding prompt for issue #595 - Rewrite prompt.md: multi-turn flow, Gmail-first, no silent first turn - Align with check_status/complete and ready_to_complete semantics - Update proactive injection copy to match new tool wording Made-with: Cursor * feat(onboarding): add completion readiness reason Made-with: Cursor * docs(ux): add onboarding and welcome audit for #563 Made-with: Cursor * docs(welcome): clarify OAuth link behavior in onboarding prompt Updated the onboarding prompt to explicitly state that clicking the Gmail connection link opens the user's default browser for authentication. Added guidance to return to the chat after completing the authorization process. * fix(onboarding): resolve CI test and proactive greeting review Made-with: Cursor |
||
|
|
dced586a18 | chore(release): v0.52.18 v0.52.18 | ||
|
|
7db71408bd |
feat(local_ai): default to cloud fallback on <8GB RAM devices (#589)
* Enhance draft message handling in streaming edits
- Introduced a new `draft_sent` field in the `StreamingState` struct to track when a draft message has been posted, decoupling the existence of a draft from the ability to edit it.
- Updated the `flush_streaming_edit` function to set `draft_sent` upon posting a draft, ensuring that duplicate messages are not sent if the backend fails to return an ID.
- Modified the `finalize_channel_reply` function to prevent sending a fresh message if a draft was already posted without an ID, improving user experience by avoiding duplicate bubbles.
These changes enhance the robustness of message handling during streaming edits, ensuring a smoother interaction for users.
* feat(onboarding): enhance LocalAIStep for low-RAM device handling
- Added logic to determine if the device is below the RAM threshold, defaulting to a cloud AI fallback if necessary.
- Introduced a new UI for low-RAM devices, informing users about the cloud mode and providing options to continue with cloud AI or force-enable local AI.
- Updated the `ensureRecommendedLocalAiPresetIfNeeded` function to return a `recommend_disabled` flag based on device RAM.
- Enhanced tests to cover new cloud fallback UI and local AI consent handling.
These changes improve the onboarding experience by providing clearer options based on device capabilities.
* style: apply prettier formatting to LocalAIStep
* feat(local_ai): unlock model selection + add Disabled/cloud fallback option
- Remove MVP ceiling that clamped selection to the 2-4 GB tier, in bootstrap
and in the apply_preset RPC — users can now pick any tier.
- Add special "disabled" tier string to apply_preset that toggles
config.local_ai.enabled = false so the app uses the cloud summarizer.
- Presets RPC now returns local_ai_enabled so the UI can render the
currently-active state correctly.
- Rewrite DeviceCapabilitySection: tiers are now clickable buttons that
call apply_preset; adds a "Disabled — Cloud fallback" card at the top
marked "Recommended" on low-RAM devices and "Active" when enabled=false.
- Remove the MVP message copy from the model tier panel.
- Remove unread-count badge from the bottom tab bar.
* refactor(onboarding): streamline LocalAIStep and update local AI preset handling
- Removed the `ensureRecommendedLocalAiPresetIfNeeded` function call from `LocalAIStep`, replacing it with `openhumanLocalAiPresets` to directly fetch preset information.
- Updated the logic in `ensureRecommendedLocalAiPresetIfNeeded` to ensure the recommended tier is applied correctly based on user consent, improving clarity in the local AI setup process.
- Enhanced tests to mock the new `openhumanLocalAiPresets` function, ensuring coverage for low-RAM device scenarios and local AI consent handling.
- Updated documentation in the `schemas.rs` file to reflect changes in the data structure returned by the presets RPC.
These changes improve the onboarding experience by providing a more direct and efficient method for managing local AI presets based on device capabilities.
* test(LocalAIStep): improve mock implementation for local AI presets
- Refactored the mock for `openhumanLocalAiPresets` to enhance readability and maintainability.
- Ensured the mock returns consistent device information and preset details for testing scenarios.
- This change supports better test coverage and clarity in the LocalAIStep component's behavior during onboarding.
* fix(local_ai): preserve hadSelectedTier semantics in bootstrap return
hadSelectedTier / selectedTier represent the incoming state ("was a tier
already selected before this call"), not the post-apply state. Setting
both to the just-applied tier broke the existing localAiBootstrap
contract and the unit test that encodes it.
The Rust-side persistence fix is independent: removing the
recommend_disabled short-circuit ensures openhumanLocalAiApplyPreset
actually writes the selected tier to disk on the opt-in path, so
config_with_recommended_tier_if_unselected() honors the user's choice.
|
||
|
|
923c920ad5 |
fix(tauri): hide main window on close instead of destroying it (#601) (#610)
* fix(tauri): hide main window on close instead of destroying it (#601) On macOS, clicking the close button destroyed the main window. Since a tray icon keeps the process alive, subsequent dock-icon clicks fired RunEvent::Reopen but get_webview_window("main") returned None — the window was gone. Now CloseRequested is intercepted: the close is prevented and the window is hidden instead, so Reopen and tray clicks can show it again. Closes #601 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(tauri): cargo fmt line wrap Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
2bb20faa55 |
feat(threads): dedicated threads controller with per-thread session scoping (#590)
* feat(conversations): implement thread management features including creation and deletion - Added functionality to create new conversation threads with unique IDs and titles based on the current date and time. - Introduced a deleteThread action to remove existing threads, updating the selected thread accordingly. - Enhanced the UI to display threads in a sidebar, allowing users to select and delete threads easily. - Updated the Conversations component to handle thread loading and selection more efficiently, ensuring a smoother user experience. Also updated the OpenHuman package version to 0.52.15 in Cargo.lock files. * refactor(conversations): rename createThreadLocal to createNewThread and streamline thread creation logic - Updated the function name from `createThreadLocal` to `createNewThread` for clarity and consistency. - Simplified the thread creation process by removing the manual ID and title generation, leveraging the new API method for automatic thread creation. - Adjusted the Conversations component to utilize the new `handleCreateNewThread` function, enhancing readability and maintainability. - Removed unused thread ID and title generation functions to clean up the codebase. This refactor improves the overall structure and clarity of the thread management functionality. * refactor(memory): remove deprecated conversation thread management functions - Eliminated unused functions related to listing, creating, updating, appending, and deleting conversation threads in memory operations. - This cleanup enhances code maintainability and reduces complexity in the memory module. - The refactor focuses on streamlining the conversation management logic, aligning with recent changes in the thread handling API. * refactor(api): update thread API method names and remove deprecated functions - Renamed thread-related API methods to align with the new naming convention, improving clarity and consistency. - Removed deprecated functions related to thread creation, streamlining the API and enhancing maintainability. - Adjusted the implementation of existing methods to reflect the updated API structure, ensuring proper functionality. * refactor(thread): simplify thread state management and remove unused properties - Streamlined the thread state by removing the lastViewedAt property and related logic, enhancing clarity in unread message counting. - Updated the BottomTabBar component to reflect the new unread count logic, which now simply returns the length of threads. - Removed the setLastViewed action from the Conversations component, further simplifying the thread management logic. - Introduced a new deleteThread action to handle thread deletion, ensuring proper state updates and selection handling. - Overall, these changes improve maintainability and reduce complexity in the thread management system. * style(threads): apply cargo fmt * refactor(tabbar): remove conversations unread badge * update(Cargo.lock): bump OpenHuman package version to 0.52.15 * test(threadApi): update RPC method names to threads namespace * refactor(conversations): update model ID for chat functionality - Changed the model ID used in the chatSend function from `agentic-v1` to `reasoning-v1`, clarifying the purpose of each model. - Added comments to explain the distinction between the reasoning model and the agentic model, enhancing code readability and maintainability. |
||
|
|
ead0862d50 |
fix(onboarding): prevent home page flash after onboarding completion (#609)
* fix(onboarding): prevent home page flash after onboarding completion Navigate to /conversations before persisting onboarding_completed so the overlay stays rendered during the route transition. A local isDismissing flag keeps the overlay visible until the flag is persisted and the conversations screen is active, eliminating the brief home page flash. Closes #598 * fix(onboarding): enhance onboarding overlay with location tracking and improved dismissal logic |
||
|
|
ea6895f19d |
test(coverage): batch 5–8 — Rust unit tests toward 80% for 20 modules (#607)
* test(coverage): batch 5–8 — Rust unit tests toward 80% for 20 modules (#530) Add 244 new unit tests across 20 modules to push line coverage from 75.06% → 75.70% overall. Modules improved: - api/socket: 77% → 100% - rpc/dispatch: 75% → 100% - config/schema/channels: 77% → 100% - composio/gmail/sync: 78% → 97% - composio/notion/sync: 77% → 96% - webhooks/router: 78% → 96% - agent/hooks: 78% → 92% - config/schema/proxy: 76% → 90% - local_ai/device: 79% → 89% - text_input/schemas: 73% → 89% - agent/harness/interrupt: 76% → 88% - billing/schemas: 79% → 87% - screen_intelligence/schemas: 78% → 81% - about_app/types, health/schemas, app_state/schemas, core/types, config/schema/identity_cost, cron/scheduler Tests cover: schema catalog integrity, param deserialization, serde roundtrips, helper functions, edge cases, error paths. All 3974 tests pass. * test(coverage): batch 9–10 — browser_open, update_memory_md, credentials profiles, cost tracker (#530) Add 53 new tests across 4 more modules: - browser_open: IPv4/IPv6 private ranges, host matching, normalize_domain edges - update_memory_md: empty file, section creation, unknown action, param validation - credentials/profiles: token expiry, CRUD operations, active profile management - cost/tracker: budget warnings, monthly exceeded, model stats aggregation All 4027 tests pass. * test(coverage): batch 11–12 — channels schemas, conversation store (#530) Add 33 new tests: - channels/controllers/schemas: per-function input validation, param deserialization, helper coverage - memory/conversations/store: thread lifecycle (create, delete, idempotent), multi-thread, empty/nonexistent thread, purge empty store All 4060 tests pass. |
||
|
|
7f686003a0 |
feat(core): gate service lifecycle on user login/logout (#582) (#603)
* refactor(voice): wrap CancellationToken in Mutex for restart support The VoiceServer singleton uses OnceCell so it can't be recreated. CancellationToken is one-shot — once cancelled, stays cancelled. Wrapping it in std::sync::Mutex + adding fresh_cancel() allows stop() then run() to work within the same process (logout → re-login). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(screen_intelligence): wrap CancellationToken in Mutex for restart support Same pattern as voice server — enables stop() then run() within the same process for logout → re-login cycles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(credentials): add start/stop helpers for login-gated services Add start_login_gated_services() and stop_login_gated_services() to credentials/ops.rs. Wire start into store_session() (after login) and stop into clear_session() (on logout) so voice, autocomplete, screen intelligence, and local AI are properly managed around auth lifecycle. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(core): defer service startup behind login gate in jsonrpc.rs Replace the unconditional service startup block with a login check. If active_user.toml exists, start services immediately via the new start_login_gated_services() helper. Otherwise defer until the login handler triggers it. Autocomplete shutdown hook remains unconditional. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(screen_intelligence): wait for Stopped state in stop() to prevent restart race stop() now polls until the run-loop sets ServerState::Stopped (5s timeout). Prevents fast logout→login from seeing stale Idle/Running state and skipping the restart. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(dictation): add stop() to prevent listener accumulation across re-logins Store the spawned task JoinHandle and abort it on stop(). Prevents duplicate rdev hotkey listeners from stacking across logout→login cycles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(credentials): call dictation_listener::stop() on logout Wire the new dictation stop into stop_login_gated_services() so the hotkey forwarder task is aborted when the user logs out. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
cf35f27cd6 | chore(release): v0.52.17 v0.52.17 | ||
|
|
e8639adae0 |
fix: Improve deep link authentication state management and improve logout (#608)
* feat(deepLink): implement deep link authentication state management - Added a new module for managing deep link authentication state, including processing states and error handling. - Integrated deep link authentication state management into the desktop deep link listener, enhancing the handling of authentication flows. - Introduced functions to begin, complete, and fail deep link authentication processing, improving user feedback during the authentication process. * refactor(settings): simplify logout process and enhance error handling - Removed onboarding completion flag from the logout process to streamline functionality. - Improved error handling during logout to provide user feedback if the logout fails. - Updated comments to clarify the behavior of session clearing and routing after logout. - Integrated deep link authentication state management into the settings component for better user experience. * refactor(settings, deepLink): enhance logout and session management - Simplified the logout process by removing unnecessary flags and improving error handling. - Introduced a new function to manage signed-out state in the core state provider. - Streamlined session token application in the deep link listener for better authentication flow. - Updated comments for clarity on session clearing and routing behavior post-logout. * chore(dependencies): update OpenHuman to version 0.52.16 in Cargo.lock files * refactor(format): format the code |
||
|
|
a78506f6a3 |
fix(agent): use canonical assistant history format in subagent_runner (#606)
build_native_assistant_payload in subagent_runner.rs serialised the
assistant tool-call message using {"text": …, "tool_calls": [{
"type":"function","function":{…}}]} — two mismatches vs the format
parse::build_native_assistant_history produces and the backend
jinja template expects:
1. "text" instead of "content" — the downstream convert_messages
parser looks for "content" to detect assistant-with-tool-calls
messages; "text" is not recognised, so the message is treated
as a plain assistant message.
2. Nested {"type":"function","function":{"name":…,"arguments":…}}
wrappers instead of flat {"id":…,"name":…,"arguments":…}.
Result: every sub-agent that made a tool call and entered iteration
1+ hit a 400 from the backend: "jinja template rendering failed.
Message has tool role, but there was no previous assistant message
with a tool call!" — the backend saw a role=tool message without a
recognised assistant-with-tool-calls predecessor.
The fix replaces the broken inline copy with a direct call to
parse::build_native_assistant_history (the same serialiser
tool_loop.rs uses successfully for the orchestrator's tool calls).
The dead build_native_assistant_payload function is removed.
Introduced in PR #474 (
|
||
|
|
fd213d40a2 | chore(release): v0.52.16 v0.52.16 | ||
|
|
c26ca795ca |
fix: keep chat processing alive across tab switches (#587)
* fix(chat): keep in-flight responses alive across tab switches Made-with: Cursor * chore: satisfy lint and format push gates Made-with: Cursor * fix: address CodeRabbit review on chat runtime PR Made-with: Cursor * feat(chat): add explicit inference turn lifecycle in chat runtime slice Made-with: Cursor * feat(chat): implement thinking summary feature in chat responses Added a new mechanism to accumulate and send model reasoning text as a separate message during chat interactions. This includes handling "thinking_delta" events to gather reasoning content, formatting it for clarity, and ensuring it is sent before the main response. Updated the StreamingState struct to include a thinking accumulator for this purpose. This enhancement improves user experience by providing insight into the model's reasoning process. * feat(telegram): update bot username handling for staging and production environments Refactored the Telegram bot username resolution logic to differentiate between staging and production environments. Introduced constants for default usernames based on the application environment and updated the GitHub Actions workflow to set the appropriate environment variables. This change enhances the flexibility and clarity of bot username management in the application. * fix: resolve CodeRabbit review issues on feat/thinking-telegram-summary - bus.rs: fix UTF-8 char boundary panic in format_thinking_summary truncation - threadSlice.ts: remove premature activeThreadId clear from addInferenceResponse.rejected - Conversations.tsx: add composerBlocked global lock, clear tool timeline in safety timeout - ChatRuntimeProvider.tsx: replace stale toolTimelineRef/inferenceStatusRef reads with live store.getState() calls in all event handlers - LocalAIDownloadSnackbar.tsx: reset dismissed/collapsed on not-downloading → downloading transition edge - MemoryGraphMap.tsx: derive activeSelectedNode to guard stale selectedNode after relations refresh; add debug logs to useMemo graph recompute Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: use render-phase update for download dismiss reset in LocalAIDownloadSnackbar Replace effect-based setState with the React render-phase update pattern so the not-downloading → downloading transition resets dismissed/collapsed without triggering the react-hooks/set-state-in-effect lint warning. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: apply prettier and cargo fmt auto-formatting Formatting changes applied by the pre-push hook during the previous commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: replace endInferenceTurn with clearRuntimeForThread in Conversations component Updated the Conversations component to replace the endInferenceTurn dispatch with clearRuntimeForThread. This change simplifies the handling of thread runtime state during error scenarios and timeout conditions, ensuring a cleaner state management approach. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
a8664f066f |
test(coverage): batch 1–4 — Rust unit tests toward 80% for critical modules (#530) (#581)
* test(coverage): phase 1 — webhooks/types, workspace/ops, webhooks/schemas
Lines: webhooks/types 0% → 100%; workspace/ops 0% → 96.98%;
webhooks/schemas 35.40% → 79.18%.
- webhooks/types.rs: serde round-trip tests for WebhookRequest /
WebhookResponseData / TunnelRegistration (including the
default_webhook_target_kind fallback) / WebhookActivityEntry /
WebhookDebugLogEntry / the three debug result wrappers / and
WebhookDebugEvent, exercising every `#[serde(default)]` and
camel-case rename.
- workspace/ops.rs: ensure_workspace_file covers create / leave / force
/ write-error branches; BOOTSTRAP_FILES contract test locks in SOUL
and IDENTITY presence; init_workspace covers fresh-install, idempotent
second-call, and forced-overwrite paths against a temp OPENHUMAN_WORKSPACE
(serialised via the shared TEST_ENV_LOCK).
- webhooks/schemas.rs: catalog integrity (length / namespace /
uniqueness / schema↔handler parity), per-function required-field
assertions for all 11 RPC methods plus the unknown fallback, and
deserialize_params / json_output / to_json coverage.
Also fixes a pre-existing test bug in composio/ops.rs discovered while
running llvm-cov: fetch_connected_integrations_via_mock_aggregates_tools
was not mocking /composio/toolkits, so list_toolkits failed and the
expected aggregation never happened. Adds the missing route so the
test now observes the 2-integration result it asserts.
* test(coverage): phase 2 — webhooks/bus, webhooks/ops
Lines: webhooks/bus 0% → 100%; webhooks/ops 14.34% → 97.96%.
- webhooks/bus.rs: base64_encode / error_body helpers; Default vs new
equivalence; EventHandler name and domain filter; handle() on a
non-webhook variant (early return) and on a WebhookIncomingRequest
without a registered socket manager (graceful fallthrough).
- webhooks/ops.rs: require_token for missing / whitespace / valid
stored sessions; the four stub RPC ops (list_registrations, list_logs
including ignored-limit, clear_logs, register/unregister_echo) lock
in their current payload + log shape; build_echo_response decodes
back to the expected echo body and sets the echo-target header;
trimmed-input validation for create_tunnel (empty/whitespace name)
and the id-bearing ops (get/update/delete); and full mock-backend
round-trips for list_tunnels, create_tunnel (trim + drop-whitespace
description), get_tunnel, update_tunnel, delete_tunnel, and
get_bandwidth, plus a guard asserting authed HTTP calls fail fast
without a session token.
* test(coverage): phase 3 — voice/postprocess, voice/text_input
Lines: voice/postprocess 58.94% → 92.06%; voice/text_input 18.83% → 51.18%.
voice/postprocess.rs
- Convert existing short-circuit tests to #[tokio::test] so the async
function is awaited directly instead of via a freshly-constructed
runtime per case.
- Add `enabled_but_llm_not_ready_returns_raw_text` for the "cleanup is
on but the local LLM hasn't reached ready/degraded yet" branch.
- Add five LLM-ready tests that spin up a mock Ollama behind the
OPENHUMAN_OLLAMA_BASE_URL override: happy-path cleanup + trim,
whitespace-only response fallback, HTTP 500 fallback, conversation
context embedded in the prompt, and whitespace-only context
ignored. Assertions are permissive about "LLM called → cleaned" vs
"LLM short-circuited → raw" because ~30 sibling tests touch the
shared `local_ai::global()` singleton without LOCAL_AI_TEST_MUTEX
and can race our `state = "ready"` setup. Either branch is
documented as acceptable; the function must always return a
deterministic String and never panic. Full end-to-end correctness
of the cleanup output is pinned by the deterministic short-circuit
tests above.
voice/text_input.rs
- Add `\\t` / `\\n`-only input case and verify the OpenWhispr timing
constants (PASTE_DELAY 120ms, CLIPBOARD_RESTORE_DELAY 450ms) so
nobody silently shortens them and breaks paste reliability.
- macOS: escape_applescript_string backslash/quote/idempotence cases
and restore_focus_to_app error path against a bogus app name.
- Ceiling note: the clipboard/enigo body of insert_text is not
testable in a headless environment (Clipboard::new / Enigo::new
fail without a display). Pushing past ~51% here requires
dependency-injecting those traits — a production refactor, not a
test addition.
* test(coverage): batch 4.1 — skills/bus, text_input/{types,ops}
Lines: skills/bus 0% → 100%; text_input/types 0% → 100%;
text_input/ops 0% → 57.67% (accessibility-gated ceiling).
- skills/bus.rs: idempotent no-op for the legacy
register_skill_cleanup_subscriber() hook.
- text_input/types.rs: FieldBounds ↔ accessibility::ElementBounds
round-trip, ReadFieldParams default/omitted-key serde, and
round-trips for every request/result struct (InsertText,
ShowGhostText, DismissGhostText, AcceptGhostText).
- text_input/ops.rs: empty-text guard assertions for insert_text,
show_ghost, and accept_ghost; dismiss_ghost idempotent-success
contract; plus a deterministic-shape check that the accessibility
failure path wraps the error into InsertTextResult rather than
panicking. Anything past the guard reaches `accessibility::*`,
which requires a live focused field on an OS display and is
therefore not reachable in a headless unit-test environment —
lifting the ceiling past ~58% requires dependency-injecting the
accessibility surface, a production refactor.
* test(coverage): batch 4.2 — service/bus, migration/ops, referral/ops
Lines: service/bus 0% → 85.25%; migration/ops 0% → 89.71%;
referral/ops 0% → 94.63%.
- service/bus.rs: RestartSubscriber name and domain metadata, plus
two handle() branches that are safe to exercise — non-restart
event (early return) and duplicate-suppression (gate already set).
Deliberately does NOT cover the success path of a real
SystemRestartRequested — it spawns a tokio task that calls
std::process::exit(0) and would terminate the test runner.
register_restart_subscriber idempotency test confirms the
OnceLock guard skips re-registration.
- migration/ops.rs: dry-run against an empty temp workspace returns
the canonical "migration completed" log; missing source-workspace
path exercises the Err-propagation branch.
- referral/ops.rs: require_token for missing / whitespace / valid
sessions; get_stats + claim_referral guard fast-fail without a
session; claim_referral round-trip against a mock backend
asserting (a) the referral code is trimmed, (b) a whitespace-only
deviceFingerprint is dropped from the outgoing body, and (c) a
non-empty fingerprint is trimmed and forwarded.
* test(coverage): batch 4.3 — security/ops, service/{bus,ops}, update/{ops,scheduler}
Adds unit tests covering:
- security/ops: security_policy_info payload shape + default values
- service/ops: daemon_host_get/set happy path and error branches
- service/bus: fix register_restart_subscriber test to use #[tokio::test]
so it has a runtime under `cargo llvm-cov`
- update/ops: validate_asset_name and validate_download_url edge cases,
update_apply short-circuit guards
- update/scheduler: min-interval invariant, disabled-run short-circuit,
tick resilience when the event bus is uninitialised
All 3583 lib tests pass under `cargo llvm-cov`. Refs #530.
* style: cargo fmt cleanup in coverage test modules
Auto-fixes from `cargo fmt` on test code added in batches 4.1–4.3.
No behavioral changes.
* test(coverage): batch 5.1 — cron/{ops,schemas}
- cron/ops.rs: 74.73% → 91.20% (+add_once_at, pause/resume, async cron_list/update/remove/runs, enabled/disabled and empty-id branches)
- cron/schemas.rs: 29.11% → 77.00% (all schemas() branches, registry helpers, read_required/read_optional_u64/type_name)
30 new deterministic tests. Refs #530.
* test(coverage): batch 5.2 — memory/{rpc_models,schemas}
- memory/rpc_models.rs: 70.91% (targets resolved_limit priority across QueryNamespace/RecallContext/RecallMemories, deny_unknown_fields enforcement, ApiError/ApiMeta/ApiEnvelope round-trips)
- memory/schemas.rs: 45.67% (all 31 controller schemas present, registry parity with handlers, parse_params success + error paths, unknown function placeholder)
19 new deterministic tests. Refs #530.
* test(coverage): batch 5.3 — socket/manager webhook router paths
- socket/manager.rs: 67.54% (adds set_webhook_router populates/overwrites paths and emit-after-disconnect guard)
3 new deterministic tests. Refs #530.
* test(coverage): batch 5.4 — config/{schemas, schema/observability}
- config/schemas.rs: 52.37% (adds required_string / optional_string / optional_bool field builder coverage, exercises deserialize_params across ModelSettings / MemorySettings / WorkspaceOnboarding / SetBrowserAllowAll / OnboardingCompleted params, pins DEFAULT_ONBOARDING_FLAG_NAME constant)
- config/schema/observability.rs: 66.67% (default-values invariant, serde defaults for optional fields, explicit analytics flag, round-trip)
16 new deterministic tests. Refs #530.
* test(coverage): batch 5.5 — local_ai/{core,gif_decision}
- local_ai/core.rs: 33.33% (pins model_artifact_path structure: models/local-ai dir, `.ollama` suffix, colon→dash normalisation for Windows-safe filenames; Arc sharing across global() calls)
- local_ai/gif_decision.rs: 44.04% (trim whitespace in parse, length/word-count boundary cases, tenor_search empty-query guard, local_ai_should_send_gif empty-message early return)
10 new deterministic tests. Refs #530.
* test(coverage): batch 5.6 — local_ai/sentiment, migration/schemas, referral/schemas
- local_ai/sentiment.rs: 68.03% (negative-confidence clamp to zero, unknown valence fallback, all documented emotion/valence labels accepted, neutral() constructor invariants, empty-message early return)
- migration/schemas.rs: 36.73% (controller registry parity, openclaw input shape, MigrateOpenClawParams defaults + round-trip, unknown function placeholder, to_json wrapping)
- referral/schemas.rs: 37.18% (controller registry parity, claim input required/optional mapping, ReferralClaimParams camelCase alias + missing-code rejection, json_output + to_json helpers)
25 new deterministic tests. Refs #530.
* test(coverage): batch 5.7 — tools/traits, local_ai/device
- tools/traits.rs: 76.77% (Tool default-method values for permission/scope/category, PermissionLevel total order + default + Display + serde round-trip, ToolCategory default + Display + snake_case serde, ToolScope variant distinctness)
- local_ai/device.rs: 63.16% (total_ram_gb truncation for sub-GB and partial-GB, detect_gpu branches for Apple-brand / ARM-on-mac / Intel-Mac, DeviceProfile serde round-trip)
17 new deterministic tests. Refs #530.
* test(coverage): address PR review — tighten assertions, fix flaky test, add env-var RAII guard
Inline review fixes:
- migration/ops.rs: migrate_openclaw_returns_error_for_missing_source_workspace now requires Err() (the underlying helper bails when the source dir doesn't exist) and asserts a non-empty error message.
- text_input/ops.rs: replace tautological `!inserted || inserted` in insert_text_surfaces_accessibility_failure_as_inserted_false with the real contract: require Ok(..) and pin `inserted`↔`error` mutual exclusion. Headless runs legitimately see inserted=false, so the assertion still holds while catching regressions in either branch.
- update/scheduler.rs: remove tick_runs_without_panicking_when_event_bus_is_uninitialised — it hit real api.github.com HTTPS and was flaky under offline CI / rate limits. Replace with a comment documenting the decision and the integration-test path for exercising tick().
Nitpick fixes:
- security/ops.rs: extend security_policy_info_matches_default_policy_values with assertions for autonomy and allowed_commands so the full default shape is pinned.
- voice/postprocess.rs: tighten ready_llm_with_whitespace_only_context_never_embeds_header from `assert_eq!(result.trim(), "raw text")` to exact equality (cleanup_transcription trims internally). The pre-existing doc comment on with_ready_llm plus the in-module block comment at lines 255-268 already document the LOCAL_AI_TEST_MUTEX contract and the deliberate non-use in permissive tests — no new docs needed.
- webhooks/ops.rs: list_tunnels_hits_webhooks_core_endpoint_and_returns_payload now asserts the inbound Authorization header equals `Bearer test-session-token`; get_tunnel_encodes_id_in_path uses an id full of reserved URL chars so the test actually verifies percent-encoding rather than just trimming.
- workspace/ops.rs: introduce a WorkspaceEnvGuard RAII helper; replace all six unsafe set_var/remove_var pairs in the init_workspace tests so OPENHUMAN_WORKSPACE is cleared on panic too. Contract is documented inline: guard requires the caller to hold ENV_LOCK.
Refs #530.
* test(coverage): tighten sentry_dsn round-trip assertion to exact value
round_trip_preserves_all_fields previously only checked
`back.sentry_dsn.is_some()`, which would still pass if serde dropped or
corrupted the DSN string. Compare the full decoded value instead so any
regression in the Option<String> path is caught.
Refs #530.
|
||
|
|
19aa50a429 |
fix(agent): thread agent_id into build_session_agent_inner (#584)
build_session_agent_inner took an agent_id: &str parameter but
never threaded it into the Agent::builder() chain — a `let _ =
agent_id;` silenced the unused-variable warning. AgentBuilder::build()
fell back to the legacy "main" default at builder.rs:310-312, so
every session built via Agent::from_config_for_agent carried
agent_definition_name="main" regardless of the id the caller asked
for.
Only two ids reach this path in production: "orchestrator" (legacy
Agent::from_config wrapper, cron, local_ai, escalation) and
"welcome" (channels/providers/web.rs routing after #525/#526, and
welcome_proactive). Orchestrator is benign — "main" was already
an alias for orchestrator everywhere downstream (see debug_dump.rs:249).
Welcome is the visible bug — agent_definition_name feeds three
surfaces that are all silently wrong pre-fix:
1. Transcript filename — welcome sessions land as main_*.md
instead of welcome_*.md.
2. Transcript metadata — the <!-- session_transcript --> block
stamps `agent: main` instead of `agent: welcome`.
3. Transcript resume cross-contamination —
try_load_session_transcript calls
find_latest_transcript(workspace_dir, "main") which scans all
dated session dirs for the latest main_*.md. It finds the
last orchestrator session and resumes from it, loading its
system prompt + user messages + assistant tool-call history
into the welcome agent's `history` as a resume prefix before
run_single runs. The written transcript mixes yesterday's
orchestrator email thread with today's welcome message under
the same main_0.md filename. Reproduced live 2026-04-16: a
welcome_proactive session loaded 5 messages from yesterday's
15042026/main_0.md and wrote 6 messages back that included a
spawn_subagent(skills_agent, toolkit=gmail) tool-call the
welcome agent never made.
Prompt rendering is NOT affected. context/prompt.rs only reads
ctx.agent_id for the is_skill_executor branch at prompt.rs:655, so
welcome/main/orchestrator all fall through the same delegator path.
The welcome persona prompt is rendered by the stamped
SystemPromptBuilder::for_subagent(target_def.system_prompt) built
at session-build time, independent of agent_definition_name. The
pre-fix main_0.md on disk contains `# Welcome Agent\n\nYou are the
Welcome agent...` as its system prompt body — correct content,
wrong filename and metadata.
skills_agent and other typed sub-agents are unaffected — they go
through subagent_runner, which constructs its prompt directly and
writes transcripts under the explicit id it receives. The
pre-existing sessions/15042026/skills_agent_0.md on disk with
`agent: skills_agent` confirms this code path has always been
correct.
Changes:
* src/openhuman/agent/harness/session/builder.rs:
- Add .agent_definition_name(agent_id.to_string()) to the
builder chain in build_session_agent_inner.
- Delete the `let _ = agent_id;` suppression.
- Replace the misleading 8-line comment block at the call site
(which claimed event_channel was for transport identity and
therefore stamping agent_id wasn't needed — conflating two
unrelated fields) with an accurate description of the three
load-bearing surfaces.
- Expand the docstring on AgentBuilder::agent_definition_name
to document the surfaces and the latent prompt-section
foot-gun the fix closes for future code.
- New log::debug! call at the stamping site for grep-friendly
runtime traces ([agent::builder] stamping
agent_definition_name=<id> onto session agent).
* src/openhuman/agent/harness/session/runtime.rs:
- Add pub fn agent_definition_name(&self) -> &str accessor
on Agent so tests and runtime callers can introspect the
stamped id without reaching into the pub(super) field.
* src/openhuman/agent/harness/session/tests.rs:
- Add build_minimal_agent_with_definition_name helper.
- agent_builder_threads_agent_definition_name_when_set —
parameterised over welcome/skills_agent/orchestrator/
trigger_triage, asserts the setter threads the id through.
- agent_builder_falls_back_to_main_when_definition_name_unset
— pins the legacy fallback contract direct builder users rely
on.
Tests: 2 passed; 0 failed; 3477 filtered out; finished in 0.21s.
cargo check --lib clean; cargo fmt clean.
Verified live against G:/projects/vezures/.openhuman on 2026-04-16:
- Pre-fix welcome_proactive run wrote sessions/16042026/main_0.md
with `agent: main` in the metadata header.
- Post-fix welcome_proactive run wrote sessions/16042026/welcome_0.md
with `agent: welcome` in the metadata header.
- Post-fix web-chat dispatch to orchestrator wrote
sessions/16042026/orchestrator_0.md (moved off the historical
main_*.md alias — behaviorally unchanged for orchestrator).
- The new [agent::builder] stamping debug line fires on both
welcome and orchestrator paths.
Does not touch: subagent_runner, spawn_subagent / dispatch_subagent,
any agent/agents/*/agent.toml, any context::prompt code, or the
AgentBuilder::build() fallback itself.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
d4f5b9a357 |
fix(overlay): fullscreen visibility, voice server reliability, and resize (#528) (#585)
* fix(overlay): shrink initial overlay window to match idle orb dimensions (#528) The Tauri overlay window was 248×228 px while the idle orb renders at 50×50. The excess transparent area wasted compositing resources and created an invisible click-absorbing region. Reduce to 60×60 to tightly frame the idle orb with minimal padding. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(overlay): add native drag support with position persistence (#528) - Mouse-down on the orb initiates Tauri startDragging() for native window drag - Dragged position is saved to localStorage and survives mode changes (idle ↔ active) so the orb stays where the user placed it - Double-click resets to the default bottom-right corner - Cursor changes to grab/grabbing for affordance - Skip default repositioning when a saved position exists Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(overlay): reclass NSWindow to NSPanel for fullscreen visibility (#528) macOS fullscreen apps run in separate Spaces where standard NSWindow cannot follow. Use object_setClass() to reclass the Tauri overlay window from NSWindow to NSPanel at runtime, then configure it with NonactivatingPanel style mask and Transient collection behavior — matching the working Swift accessibility helper pattern. Key configuration that makes this work: - object_setClass(NSWindow → NSPanel) — in-place reclass, no reparenting - NSWindowStyleMask::NonactivatingPanel — critical for panel behavior - NSWindowCollectionBehavior::Transient (not Stationary) — follows Spaces - Window level 25 (NSStatusWindowLevel) — floats above fullscreen apps - setFloatingPanel(true), setHidesOnDeactivate(false) Previous approaches that failed: 1. CGShieldingWindowLevel + CanJoinAllSpaces — hidden (NSWindow limitation) 2. Window level i32::MAX-17 + Stationary — hidden (Space membership issue) 3. CGS private API CGSSetWindowTags sticky bit — blocked on Sonoma 4. object_setClass WITHOUT NonactivatingPanel mask — hidden 5. Create new NSPanel + reparent webview — CRASH (Tao delegate panic) Also removes unused objc2-core-graphics and objc2-foundation deps. Ref: https://github.com/tauri-apps/tauri/issues/11488 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(sidecar): make dev signing non-fatal in stage script codesign failures no longer call process.exit(), preventing yarn tauri dev from hanging when the dev signing identity is missing or the keychain rejects the request. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(voice): prevent race condition and fix restart after stop - Atomically transition Stopped → Idle at start of run() to prevent duplicate run() calls during slow globe listener compilation - Wrap CancellationToken in Mutex so run() creates a fresh token on each start — a cancelled token cannot be reused after stop() - Reset state to Stopped if hotkey listener fails to start Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(voice): capture server errors from spawned run() task Store errors from the background server.run() task via set_last_error() so they surface in voice_server_status RPC responses instead of being silently lost. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(overlay): enable programmatic resize and shrink idle dimensions - Change overlay window from 60x60 to 50x50 to match idle orb size - Remove minWidth/minHeight constraints that blocked dynamic resize - Set resizable: true so setSize() calls work for bubble expansion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(overlay): simplify window resize and bubble rendering - Clear min/max constraints before resizing to avoid clamping - Replace CSS transition-based bubble visibility with conditional mount for more reliable rendering when mode changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: fix fmt and remove unused bubbles variable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(voice): enforce lock ordering to prevent race between run() and stop() Acquire cancel lock before state lock in run() — same order as stop() — so stop() cannot cancel a stale token between setting Idle and swapping. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(overlay): restore saved position on resize and format with prettier Parse and apply saved drag coordinates instead of just using their presence as a sentinel. Also reformats for prettier compliance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(sidecar): fail-fast on dev signing failure in CI environments Add CI detection so signing failures abort the build in CI but remain non-fatal for local development. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: fix cargo fmt on Tauri shell import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
f014058417 |
feat(local_ai): MVP model lockdown — lock selection to 2-4 GB tier (#573) (#588)
* feat(local_ai): add MVP tier ceiling and cap model recommendation (#573) Introduce MVP_MAX_TIER constant (Ram2To4Gb), is_mvp_allowed() gate, mvp_presets() filter, and cap recommend_tier() so auto-provisioning never selects a model above the MVP ceiling regardless of device RAM. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(local_ai): enforce MVP model allowlists on resolved IDs (#573) Add per-category allowlists (chat, vision, embedding) so that effective_*_model_id() silently redirects any non-MVP model to the default. Prevents config-file edits from bypassing the 2-4 GB tier restriction. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(local_ai): reject non-MVP tiers in RPC and clamp at bootstrap (#573) apply_preset handler now returns an error for tiers above the MVP ceiling. Bootstrap clamps any existing out-of-range tier selection down to the recommended (capped) preset on startup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(ui): lock model tier selection and show full roadmap (#573) Replace clickable tier buttons with static cards. Active tier shows "Active" badge; locked tiers show "Coming soon" with reduced opacity. Add MVP info banner. Fix download size to 1 decimal place. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(local_ai): resolve CI failures — fmt, unused props, dead code (#573) Apply cargo fmt to single-element array constants. Remove unused isApplyingPreset/onApplyPreset props and applyPreset function from the settings panel since tier switching is disabled for MVP. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: apply Prettier formatting to settings panels (#573) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
098206cea7 | chore(release): v0.52.15 v0.52.15 | ||
|
|
a2aee3a1f1 | chore(release): v0.52.14 | ||
|
|
cca6c08ab0 |
Fix: discord (#580)
* feat(discord): implement managed link functionality and enhance DiscordConfig component - Added support for managed Discord linking, including new API methods for initiating and checking link status. - Enhanced the DiscordConfig component to manage link tokens and implement polling for link completion. - Introduced new state management for link tokens and improved error handling during connection processes. - Updated the definitions to include a new auth action for managed links, streamlining the onboarding experience for users. - Added tests for the new Discord link functionality to ensure robust integration and error handling. This commit significantly improves the user experience for connecting Discord accounts, providing clearer feedback and handling for managed links. * feat(discord): implement managed link functionality and enhance DiscordConfig component - Added support for managed Discord linking, including new API methods for initiating and checking link status. - Enhanced the DiscordConfig component to manage link tokens and implement polling for link status, improving user experience during the linking process. - Introduced new state management for link tokens and error handling, ensuring robust interaction with the Discord API. - Updated the channel definitions to include a new auth action for managed links, streamlining the integration process. - Added tests for the new API methods and updated existing tests to cover the new functionality. This commit significantly improves the integration with Discord, allowing users to link their accounts more effectively and providing better feedback during the linking process. * chore(release): update OpenHuman version to 0.52.9 in Cargo.lock - Bumped the version of the OpenHuman package from 0.52.7 to 0.52.9 in both Cargo.lock files for the main application and the Tauri app. - This update ensures that the latest features and fixes from the OpenHuman package are included in the project. * fix(tests): update DiscordConfig test to reflect new Connect button count - Adjusted the test for the DiscordConfig component to expect three Connect buttons instead of two, aligning with recent changes in the component's authentication modes. - This update ensures that the test accurately reflects the current functionality and improves test reliability. * refactor(discord): modularize channel permission checks and enhance logging - Extracted the `check_channel_permissions_at_base` function to modularize the permission checking logic for better readability and maintainability. - Updated the API calls to use a dynamic base URL instead of a hardcoded one, improving flexibility. - Enhanced logging for non-success responses from Discord API calls, providing more context for debugging. - Minor adjustment in the hallucination check logic to improve clarity in variable usage. * fix(logging): enhance error handling in DiscordConfig and SocketProvider - Updated error handling in DiscordConfig to log specific errors when link checks fail, improving debugging capabilities. - Enhanced SocketProvider to log non-fatal RPC connection failures, providing clearer context for potential issues with the sidecar or backend connectivity. * feat(discord): add validation functions for Discord link start and complete responses - Introduced `expectDiscordLinkStart` and `expectDiscordLinkComplete` functions to validate the structure of responses from Discord link API calls. - Updated `channelConnectionsApi` methods to utilize these new validation functions, improving error handling and response consistency. - Added tests to ensure proper unwrapping and validation of Discord link responses, enhancing overall reliability of the API integration. * fix(channelConnections): improve handling of lastError and capabilities in touchConnection function - Updated the touchConnection function to conditionally assign lastError and capabilities based on their presence in the patch object, ensuring more accurate state management. - This change enhances the reliability of connection updates by preventing unintended overwrites of existing values. * test(channelConnections): add test to clear lastError when explicitly set to undefined - Introduced a new test case to verify that the lastError state is cleared when an explicit patch sets it to undefined. This enhances the reliability of the state management in the channelConnectionsSlice reducer. * test(tests): add tests for upstream_unhealthy detection and failure reason precedence - Introduced multiple test cases to verify the detection of upstream unavailability and service unavailability errors. - Ensured that the `failure_reason` function correctly prioritizes upstream_unhealthy over other error states, enhancing the reliability of error handling in the system. * feat(discord): add OAuth success handling in DiscordConfig component - Implemented a new useEffect to handle successful OAuth events for Discord, updating the channel connection status and capabilities accordingly. - This enhancement improves the integration with Discord by ensuring that the application responds correctly to OAuth success events, providing a better user experience. * feat(deepLink): enhance OAuth deep link handling to include skillId - Updated the deep link handling logic to also retrieve the skillId from the URL parameters, improving flexibility in OAuth success scenarios. - Added a new simulation example for skillId in the setupDesktopDeepLinkListener function to aid in testing and development. * refactor(format): ran format * fix(discord): update permissions mock and improve message dispatch test - Revised the permissions mock to include additional endpoints for better accuracy in testing Discord API interactions. - Adjusted the message dispatch test to utilize a deterministic stub for the agent's response, ensuring consistent timing and behavior during tests. - Reduced the delay in the SlowProvider to enhance test performance while maintaining robustness. * chore(dependencies): update OpenHuman package version to 0.52.13 in Cargo.lock |
||
|
|
d545c193b9 |
feat(agent): fuzzy-filter skills_agent toolkit actions by task prompt (#579)
* feat(agent): fuzzy-filter skills_agent toolkit actions by task prompt Narrow large Composio toolkits (e.g. github ~500 actions) down to the handful relevant to a given delegation prompt before registering them as native tools on a spawned skills_agent. Falls back to the full catalogue when the filter yields fewer than MIN_CONFIDENT_HITS hits to avoid starving the sub-agent on under-specified prompts. Filter is only invoked when both `definition.id == "skills_agent"` and a `toolkit=` argument is present, so orchestrator and other sub-agents are unaffected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(composio): mock toolkits route in ops integration test --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
d575cf2cca | chore(release): v0.52.13 | ||
|
|
70a2a6fcc3 | chore(release): v0.52.12 v0.52.12 | ||
|
|
f179d2d3f9 | chore(release): v0.52.11 | ||
|
|
fc103bf89f | chore(release): v0.52.10 | ||
|
|
ea088d9f15 |
feat(prompt): unified delegation guide + dynamic per-toolkit tool registration (#447) (#570)
* feat(prompt): unified delegation guide + dynamic per-toolkit tool registration (#447) Cuts main agent prompt token cost ~98% on accounts with connected integrations and replaces the generic Composio dispatcher with native per-action tool calling inside skills_agent. ## Why Issue #447: prompt payloads were ballooning because main/orchestrator re-shipped a full prose enumeration of every connected toolkit's actions on every turn (~13.7k tokens for one gmail integration alone), and skills_agent had no way to scope tools to a single toolkit so it inherited a flat dispatcher (composio_execute) that the LLM couldn't reliably call without first round-tripping composio_list_tools. ## What ### main / orchestrator prompt - Replace `ConnectedIntegrationsSection`'s per-action prose dump with a unified Delegation Guide: one bullet per integration (toolkit + one-line description + spawn snippet). Tokens added per integration: ~30. Savings vs old per-action listing: ~5k+ tokens per connected toolkit. - Drop every "Composio" reference from delegating-agent prose so the surface stays provider-neutral. ### skills_agent - Add a `toolkit` argument to `spawn_subagent` with three pre-flight validation modes resolved against the parent's connected integrations list before any LLM call: * missing toolkit -> ToolResult::error (model retries) * unknown toolkit -> ToolResult::error (model retries) * in allowlist, not connected -> ToolResult::success (model surfaces "authorize in Settings -> Integrations" to user; not flagged as a tool failure in the agent loop or web channel) - New `ComposioActionTool` (`src/openhuman/composio/action_tool.rs`) implements the `Tool` trait per Composio action. The sub-agent runner constructs ~N of these at spawn time from the cached integration overview and injects them via a new `extra_tools` parameter through `run_typed_mode` -> `run_inner_loop`. - `filter_tool_indices` drops every skill-category parent tool when `is_skills_agent_with_toolkit` is true so the only skill-category entries the sub-agent sees are the freshly-built per-action tools. This eliminates apify_*, composio_list_*, composio_authorize, and composio_execute from the toolkit-scoped surface. - Sub-agent renderer takes the parent's actual `tool_call_format` instead of hardcoding PFormat. Native dispatchers no longer carry a prose `## Tools` section at all (schemas already travel through the request body's `tools` field) — eliminates a ~30k-token duplication that was blowing past the model's context window. ### integration overview fetch - `fetch_connected_integrations_uncached` now merges Composio's toolkit allowlist with the user's active connections and returns one `ConnectedIntegration` per allowlisted toolkit with a `connected: bool` flag. Unconnected entries carry no schemas, just the toolkit name + description, so the orchestrator can mention them without trying to invoke them. - `ConnectedIntegrationTool` preserves the action's full JSON parameter schema so `ComposioActionTool` can advertise it through native function-calling. ### plumbing - `ParentExecutionContext` carries a `ComposioClient` and the parent's resolved `tool_call_format`, populated alongside `connected_integrations` in `Session::fetch_connected_integrations`. Triage and test paths pass `None` / `PFormat` defaults. - `dispatch_subagent` (the `SkillDelegationTool` path) plumbs its pre-bound skill_id through `toolkit_override` instead of the broken `skill_filter_override` (which used `{skill}__` prefix matching that never matched Composio's `TOOLKIT_*` naming). - `web::run_chat_task` failures now log the underlying error at WARN so debugging an in-flight failure no longer requires turning on TRACE for socket events. - `scripts/stage-core-sidecar.mjs` queries `cargo metadata` for the real target directory instead of assuming `<repo>/target` so the staging step works under workspace-level `target-dir` overrides (the vezures-workspace shared `.cargo-target` setup). ## Verified end-to-end Two RPC tests against a freshly-rebuilt sidecar (gmail connected, notion / slack / etc. allowlisted but not connected): | Test | Behavior | Tokens | Iterations | |---|---|---|---| | Connected (gmail, "fetch 5 unread emails") | spawn_subagent -> 62 dynamic gmail tools registered -> 1 GMAIL_FETCH_EMAILS call with smart args -> markdown table response | 42,911 input | 1 | | Not-connected (notion, "create a page") | main answers directly without spawning, tells user to authorize in Settings -> Integrations | 3,319 input | 1 | Both flows complete cleanly. The connected path proves dynamic per-action tool registration is working with full schema validation; the unconnected path proves the unified delegation guide + ToolResult::success return for not-connected toolkits keeps the model on a graceful path without polluting the chat with error styling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(prompt): update test callers + assertions for new renderer signature Follow-up to #447. The main patch changed three signatures that test callers hadn't been updated for, and flipped one assertion that was validating the now-removed prose schema duplication. - `SubagentRunOptions` test constructors in subagent_runner.rs (2 sites) now pass `toolkit_override: None`. - `ConnectedIntegration` test constructor in orchestrator_tools.rs now passes `connected: true` (the default for test integrations — they're treated as authorized so delegation logic still runs). - 12 `render_subagent_system_prompt` test callers in prompt.rs now pass `&[]` for the new `extra_tools` slice and `ToolCallFormat::PFormat` for the new `tool_call_format` argument. - `render_subagent_system_prompt_honors_identity_safety_and_skills_flags` used to assert `rendered.contains("Parameters:")` on the Json dispatcher branch — that was valid in the old world where the prose `## Tools` section dumped full JSON schemas for Json/Native formats. The main patch deliberately removes that dump (it was the ~30k-token duplication of the native `tools` field), so the test now asserts the opposite: no `## Tools` header and no `Parameters:` line are emitted for Native/Json dispatchers. The schemas still travel through the provider request's `tools` field. Also picks up `rustfmt` rewraps in action_tool.rs and ops.rs from a background linter run — pure whitespace, no semantic change. Verified green against the full `cargo test --lib` suite for every test touched by this PR: - openhuman::context::prompt::tests (26 passed) - openhuman::agent::harness::subagent_runner::tests (19 passed) - openhuman::composio::ops::tests (2 passed) - openhuman::tools::impl::agent::tests (0 scoped) The 7 remaining failures in `cargo test --lib` are pre-existing Windows-path/filesystem flakes in subsystems this PR doesn't touch (self_healing polyfill path separator, cron scheduler shell spawning, local_ai::paths absolute-path detection, security::policy sandbox path handling, composio::trigger_history jsonl archive, and a real pre-existing `Option::unwrap()` panic in browser::screenshot). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(harness): add composio_client + tool_call_format to integration test stub Follow-up to #447. The `tests/agent_harness_public.rs` integration test constructs a `ParentExecutionContext` in `stub_parent_context` that was missing the two fields added in the main patch (`composio_client` and `tool_call_format`). `cargo test --lib` doesn't compile integration tests, which is why this slipped past local verification — it only surfaced on Linux CI. - `composio_client: None` — the stub parent has no composio client because these tests don't exercise the integration-overview path. - `tool_call_format: ToolCallFormat::PFormat` — default legacy format; none of the tests in this file exercise the sub-agent renderer's format branching, so PFormat is the safe pick. Verified locally that `cargo test --no-run` compiles all integration test targets including `agent_harness_public`. (The `agent_memory_loader_public` link error in the local run is a pre-existing Windows `libucrt`/`fgets` C-runtime issue unrelated to this PR — won't reproduce on Linux CI.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(prompt,composio): address CodeRabbit review on #570 (#447) Four fixes from the CodeRabbit review of PR #570, ranked by impact: ## `context/prompt.rs` — Json dispatcher needs prose tool catalog The initial patch gated the prose `## Tools` section behind `matches!(tool_call_format, ToolCallFormat::PFormat)`, which conflated Json with Native. Only `ToolCallFormat::Native` uses the provider's native function-calling channel where schemas travel via the request body's `tools` field. `ToolCallFormat::Json` is a prompt-driven format (the model wraps JSON tool calls in `<tool_call>` tags) and relies on the prose catalog the same way PFormat does — without it the model sees protocol instructions but no visible tool names or schemas. Inverted the guard to `!matches!(tool_call_format, Native)` so PFormat and Json both render the `## Tools` section with their respective per-entry shapes (compact `Call as:` signature for PFormat, inline `Parameters:` JSON schema for Json). Updated the `render_subagent_system_prompt_honors_identity_safety_and_skills_flags` test: the Json assertion now expects `Parameters:` to be present again (reverting commit 2's flip), and a new Native-branch assertion guards against the ~54k-token schema duplication the original PR fixed. ## `composio/ops.rs` — don't cache degraded snapshots All three backend calls in `fetch_connected_integrations_uncached` (`list_toolkits`, `list_connections`, `list_tools`) previously returned `Some(Vec::new())` or fell through to an empty inner vec on transient errors. The outer `fetch_connected_integrations` caches whatever the uncached path returns, so a single transient 5xx would silently hide every integration, mark connected toolkits as disconnected, or register dynamic Composio tools with zero callable actions — until the cache is invalidated or the process restarts. Changed all three branches to return `None`, which signals the caller to NOT cache the result and retry on the next call. ## `composio/ops.rs` — prefix match needs a delimiter `starts_with(&slug.to_uppercase())` false-matches when two toolkit slugs share a text prefix (e.g. `git` vs `github`). The current allowlist doesn't trigger this, but adding a new toolkit could silently leak actions between integrations. Anchored the prefix with an underscore so `GMAIL_SEND_EMAIL` matches `gmail_`, not just `gmail`. ## `scripts/stage-core-sidecar.mjs` — resolve CARGO_TARGET_DIR vs repo root `resolve(process.env.CARGO_TARGET_DIR)` uses the process's current working directory, but the `cargo build` spawn below runs with `cwd: root`. For an absolute env var this is identical, but a relative `CARGO_TARGET_DIR` and a cwd outside the repo would make the two paths disagree and the binary lookup would miss. Defensive fix: `resolve(root, process.env.CARGO_TARGET_DIR)` so both paths anchor to the same base. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
1836c7691f |
Feat: smart routing (#569)
* chore: update OpenHuman version to 0.52.9 and add intelligent routing functionality - Bumped OpenHuman version from 0.52.7 to 0.52.9 in Cargo.lock files. - Introduced a new routing module that implements intelligent model routing based on task complexity and local model health. - Added a health checker for the local Ollama model server to improve routing decisions. - Enhanced the provider to classify tasks and determine the appropriate backend (local or remote) for processing requests. - Updated related files to support the new routing logic and ensure seamless integration with existing functionalities. * refactor(routing): streamline provider and enhance routing logic - Removed the `build_tool_instructions` function from the public API, simplifying the routing module. - Updated the `IntelligentRoutingProvider` to utilize a more efficient model resolution process, improving routing decisions based on task complexity and local model health. - Introduced a new `quality` module to assess response quality, enabling better fallback decisions when local responses are deemed low quality. - Enhanced the `RoutingHints` struct to provide more granular control over routing behavior, including privacy requirements and cost sensitivity. - Added tests to validate the new routing logic and quality assessment, ensuring robust functionality across various scenarios. * feat(tests): add live end-to-end routing tests for real backend integration - Introduced a new test file `live_routing_e2e.rs` containing end-to-end tests for routing against a live backend. - Tests require a valid backend URL, user session JWT, and real network interactions, hence marked as `#[ignore]`. - Implemented functionality to set up environment variables, write configuration files, and perform JSON-RPC calls to validate routing behavior. - Added assertions to ensure correct handling of various routing cases, enhancing test coverage for the routing module. * refactor(format): ran format command * feat(routing): add IntelligentRoutingProvider and enhance LocalHealthChecker - Introduced a new `factory.rs` file containing the `new_provider` function to construct an `IntelligentRoutingProvider` that integrates local AI capabilities with remote backend providers. - Enhanced the `LocalHealthChecker` in `health.rs` by adding a `reqwest::Client` for improved health probing, including better logging for cache hits and misses, and streamlined cache updates. - Updated health check logic to utilize the new client, ensuring more reliable health status checks for local AI services. * refactor(routing): move new_provider function to factory module - Moved the `new_provider` function from `mod.rs` to a new `factory.rs` module to improve code organization and maintainability. - Updated public exports to include the new location of `new_provider`, ensuring continued accessibility for constructing `IntelligentRoutingProvider` instances. - Removed the old implementation from `mod.rs`, streamlining the routing module's structure. * refactor(routing): simplify local task routing logic - Removed redundant conditions for routing medium tasks locally, streamlining the decision-making process in the `decide` function. - Updated comments to reflect the simplified logic, enhancing code clarity and maintainability. * docs(tests): clarify comments in json_rpc_e2e.rs regarding hint overrides logic. * refactor(tests): enhance live routing end-to-end tests with timeout handling - Introduced a timeout mechanism for reading SSE events to prevent indefinite blocking. - Updated environment variable management in tests to ensure safe access and cleanup. - Improved comments for clarity regarding the safety of environment variable mutations during tests. * refactor(tests): update SSE event reading in live routing tests. * refactor(routing): enhance medium task routing logic and update comments - Updated the routing logic for medium tasks to utilize hints for local bias, ensuring more accurate routing decisions. - Revised comments throughout the code to clarify the behavior of task categories and routing preferences. - Adjusted test cases to reflect the new routing logic, ensuring they accurately validate the expected behavior for medium tasks. * refactor(tests): implement timeout handling for dictation event reception - Added a timeout mechanism to the dictation event test to prevent indefinite blocking while waiting for the "pressed" event. - Enhanced the test logic to consume events until the expected event type is received, improving reliability and clarity in the test flow. --------- Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com> |
||
|
|
b2c74458d3 |
fix(voice): enable GPU detection and Metal acceleration for whisper (#558) (#571)
* fix(device): expand GPU detection with Intel Mac and NVIDIA probes (#558) Add Intel Mac detection (no Metal GPU for whisper), nvidia-smi probe for Windows/Linux NVIDIA GPUs, and diagnostic tracing at each decision point in detect_gpu(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * build(cargo): enable whisper-rs Metal feature on macOS (#558) Add target-specific dependency for macOS that enables the `metal` feature on whisper-rs, compiling whisper.cpp with Metal GPU support. Cargo merges features from both declarations so non-macOS builds are unaffected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(whisper): configure GPU params from device profile (#558) Accept has_gpu and gpu_description in load_engine() and explicitly set use_gpu and flash_attn on WhisperContextParameters instead of relying on the compile-time default. Log the selected acceleration backend at startup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(local_ai): pass GPU info to whisper engine load paths (#558) Thread DeviceProfile has_gpu and gpu_description through both the bootstrap (startup) and speech (lazy) whisper engine load calls so the engine can configure Metal or CUDA acceleration at runtime. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
13ce2cdcbf |
test(coverage): raise Rust unit test coverage to ≥80% on 10 critical modules (issue #530) (#567)
* test(coverage): raise 9 critical modules to ≥80% line coverage Pushes unit test coverage to meet issue #530's 80% target on 9 modules: socket (17% → 80%), credentials (46% → 81%), composio (55% → 81%), memory (75% → 80%), tools (73% → 83%), plus previously-passing cron, context, learning, embeddings. Additions span ~400+ new tests across 44 files: - Pure-function tests for types, schemas, parsers, URL builders, and error-classification helpers. - Mock-backend integration tests using axum for HTTP-dependent code (composio client + ops, socket ws_loop against a local WebSocket server). - End-to-end RPC handler tests using tempdir + OPENHUMAN_WORKSPACE env override (credentials, memory, config, cron). Also fixes 4 pre-existing flaky tests on macOS dev machines by pinning absolute paths (/bin/ls, /bin/sleep, /bin/sh, /usr/bin/touch) in cron scheduler tests so sh -lc does not pick up homebrew-shadowed binaries that macOS SIP refuses to execute, and relaxing a screen_intelligence capture-permission hang assertion. Remaining work: voice, config, screen_intelligence, channels, local_ai still below 80% (62%, 61%, 54%, 68%, 35% respectively). * test(coverage): add config module tests (62% → ~71%) Adds tests for: - config/ops.rs: env_flag_enabled, core_rpc_url_from_env, snapshot_config_json, workspace_onboarding_flag_exists/_set, set_browser_allow_all, agent_server_status - config/schemas.rs: catalog parity, all 21 registered schema keys, helpers - config/schema/proxy.rs: normalize_*, parse_proxy_scope, parse_proxy_enabled, validate_proxy_url, service_selector_matches, ProxyConfig defaults - config/schema/load.rs: apply_env_overrides for api_key, model, temperature, reasoning_enabled, web_search.*, storage.*; resolve_config_dir_for_workspace - config/settings_cli.rs: settings_section_json all sections (model/memory/runtime/browser/unknown) * test(coverage): config reaches 80.49%, socket back to 80.10% - config/ops.rs: apply_model/memory/runtime/browser/analytics/screen_intelligence_settings roundtrips via in-memory Config; load_and_apply_dictation/voice_server_settings activation-mode validation; get_dictation/voice_server/onboarding readers; workspace_onboarding_flag_set/resolve error and happy paths. - config/schema/load.rs: apply_env_overrides coverage for OPENHUMAN_MODEL, OPENHUMAN_TEMPERATURE (range clamp), OPENHUMAN_REASONING_ENABLED, OPENHUMAN_WEB_SEARCH_*, OPENHUMAN_STORAGE_* env branches. - config/schema/proxy.rs: normalize_* helpers, parse_proxy_scope/enabled, ProxyConfig defaults, validate_proxy_url schemes + hosts, service_selector_matches wildcards. - config/schemas.rs: every registered controller key, namespace parity. - config/settings_cli.rs: all section projections (model/memory/runtime/browser/unknown). - Shared `TEST_ENV_LOCK` at config::mod level so config::ops and config::schema::load test modules serialize OPENHUMAN_WORKSPACE mutations. - socket: a couple more schema assertions to keep module at 80%+. * test(coverage): channels partial push (68.12% → 68.91%) - channels/controllers/schemas.rs: every registered key resolves, required input coverage for describe/send_message/telegram_login_check. - channels/providers/web.rs: catalog parity, chat/cancel schema required inputs, unknown fallback, key_for, event_session_id_for stability, normalize_model_override trimming/empty, broadcast channel subscribe, field-builder helpers. - channels/providers/discord/api.rs: auth_header prefix, BotPermissionCheck serde with empty/full missing_permissions lists, permission bit flags are single-bit and distinct. Channels remains below the 80% issue target — the bulk of remaining uncovered code lives in telegram/channel.rs (574 lines), ops.rs (462), lark.rs (433) and runtime/startup.rs (350), which depend on live HTTP / socket / runtime bootstrap state that would require extensive mock infrastructure to exercise from unit tests. * test(coverage): partial push on local_ai (34→45%), screen_intelligence (54→62%), voice (62→63%) - local_ai/schemas.rs: catalog parity, every registered key resolves, field-builder helpers, deserialize_params happy/error, download_force optional. - local_ai/ops.rs: local-ai-disabled error paths for prompt/vision_prompt/ embed/summarize/transcribe/tts/chat; empty-messages rejection; suggestions return empty when disabled (graceful degradation). - local_ai/install.rs: find_system_ollama_binary env-override happy/missing/ empty cases; PATH-based lookup stub. - screen_intelligence/schemas.rs: catalog parity, all 15 registered keys resolve to non-unknown, unknown fallback. - screen_intelligence/ops.rs: accessibility_status/doctor_cli_json/ capture_image_ref/stop_session/vision_recent error-free behaviour. - voice/server.rs: truncate_for_log ellipsis + multibyte; try_global_server after init; additional hallucination-pattern coverage. Remaining gap on these modules lives almost entirely in: - local_ai/service/ollama_admin.rs (625 lines) — real HTTP + Ollama subprocess - local_ai/service/{assets,public_infer,vision_embed}.rs — same - voice/{server,audio_capture}.rs deep paths — audio hardware - screen_intelligence/{engine,processing_worker}.rs — active capture session * test(coverage): channels providers (+0.9%) — qq ensure_https, lark parsers - qq: ensure_https accept/reject, QQ_API_BASE/AUTH_URL constants, constructor. - lark: parse_post_content zh_cn/en_us fallback + links/mentions; invalid JSON returns None; strip_at_placeholders for @_user_N tokens; group should_respond_in_group mention gating. * test(coverage): push all 4 remaining modules - discord/api.rs: list_bot_guilds_at_base/list_guild_channels_at_base test seams with mock axum server; parse happy-path, error status, channel filter+sort, empty list. - channels/controllers/ops.rs: parse_allowed_users for string CSV/array/ newline/@-prefix/case-insensitive dedup/non-string; credential_provider; list_channels/describe_channel; connect_channel unknown-channel and non-object credentials. - local_ai/ollama_api.rs: `ollama_base_url()` honours OPENHUMAN_OLLAMA_BASE_URL env var so tests can point at mock servers; DEFAULT_OLLAMA_BASE_URL preserved. - local_ai/service/public_infer.rs: mock-backend tests for inference/prompt happy path, non-success status, suggest_questions parsing, disabled- local-ai short-circuits for summarize/prompt/suggest_questions/ inline_complete. - voice/schemas.rs: overlay_notify cancelled→released, unknown state errors, missing state errors, server_start handler, TranscribeParams + TtsParams deserialize happy/error paths, server_start all-optional invariant, description completeness. * test(coverage): local_ai HTTP mock tests (49→53%) - ollama_api: ollama_base_url() helper now used by ollama_admin/has_model + ollama_healthy (in addition to public_infer + vision_embed). - public_infer: inference against mock /api/generate happy/error/empty; suggest_questions parses line-separated output; disabled short-circuits for summarize/prompt/suggest/inline_complete. - vision_embed: mock /api/embed with /api/tags preflight; empty-input rejection; disabled short-circuits for embed and vision_prompt. - ollama_admin: has_model matches exact + prefixed tags; errors on 5xx /api/tags; ollama_healthy true on 200 and false on unreachable URL. * test(coverage): more local_ai + voice gains - local_ai/ollama_admin: diagnostics against mock Ollama (unreachable + missing models + all models present), list_models happy/error paths. - voice/dictation_listener: start_if_enabled early-returns for disabled/ empty-hotkey/unparseable-hotkey; normalize_hotkey_for_rdev coverage for Shift+Alt, lowercase, function keys, whitespace trimming. * test(coverage): local_ai schemas handlers + voice flakiness fix - local_ai/schemas: handle_device_profile; handle_presets tier+device shape; handle_apply_preset invalid/custom/valid paths; handle_set_ollama_path nonexistent/empty-to-clear paths. - voice/schemas: relax server_status/stop assertion to tolerate other tests in the same binary having initialised the global voice server (it's a OnceLock, so state is shared across the whole test process). * test(coverage): channels incremental push (71→73%) - presentation.rs: split_sentences, group_sentences, merge_short, segment_delay monotonic/bounded, is_structured_content detection, segment_for_delivery edge cases. - runtime/dispatch.rs: contains_any, starts_with_any, full coverage of select_acknowledgment_reaction across all 7 categories + deterministic + empty/single-char inputs. - commands.rs: doctor_channels with telegram/discord/slack/imessage/ multiple-config branches. - discord/api: check_channel_permissions mock-server tests — admin bypass, all-missing, everyone-allow, channel overwrite deny, member lookup failure. Added check_channel_permissions_at_base seam. - lark: should_refresh_last_recv, LarkChannel::new, is_user_allowed wildcard/empty allowlist, parse_event_payload edge cases (unsupported type / empty sender / missing event / post type). - email_channel: is_sender_allowed full matrix (empty/wildcard/exact/ @-prefix/bare-domain/subdomain-confusion), strip_html empty/tags-only/ unclosed/whitespace collapse. - voice/schemas: tolerate event interleaving in broadcast-channel test (schema bus is process-global). * test(coverage): address review findings — assertions, determinism, observability Tighten assertions so regressions surface: - credentials/ops: assert decrypt migrate path returns Ok - credentials/session_support: assert trimmed profile name directly - computer/mouse: check Err branch in single-axis scroll tests - filesystem/git_operations: assert exact error substrings and verify `git init` success before each test - channels/controllers/ops: exact credential_provider key + concrete parse_allowed_users expectation with accurate normalisation note; merged the three duplicate list/describe tests into existing coverage - tools/impl/browser/screenshot: cfg-branched support-matrix assertions - tools/impl/agent: replace misleading stub test with one that actually exercises dispatch_subagent's graceful-failure paths - local_ai/install: cfg-branched build_install_command expectations - local_ai/service/public_infer: exercise empty-response reject path via inference() (allow_empty=false) and assert the error - screen_intelligence: only take the macOS slow-path skip on macOS Test determinism: - local_ai/install: serialise env mutations via a module Mutex and RAII EnvGuard that restores prior values on drop - composio/ops: poll TCP readiness with backoff before returning the mock-backend URL - memory/global: bind TempDir at test scope so its workspace outlives any lazy-init reference Consistency: - local_ai/service/ollama_admin: route every Ollama HTTP call and the diagnostics URL through ollama_base_url(); drop the stale OLLAMA_BASE_URL import so /api/pull, /api/tags (runner check), /api/show, and the health message all honour the env override Observability: - local_ai/service/vision_embed: tracing::debug at entry/response and tracing::error on send/non-success - local_ai/service/ollama_admin::list_models: entry/response/parse logging including raw body on parse failure - channels/providers/discord/api: tracing::debug with endpoint, status, body, and context before every non-success bail! New coverage: - channels/providers/lark: anchor href-only fallback in parse_post_content - local_ai/ollama_api: five-case env-override suite for ollama_base_url (unset / normal / trimmed / trailing slashes / empty|whitespace) Miscellaneous: - voice/server: OnceCell-backed comment (was OnceLock); drop duplicate initial-status test; supply the HallucinationMode argument to two stale hallucination tests so the crate type-checks |
||
|
|
7ae2bf83b2 |
feat: disable permission auto-prompts + typing indicator on webhook channels (#552)
* feat(config): default screen intelligence, dictation, and vision model off Flip defaults so no macOS TCC permission prompt fires on first run: - `dictation.enabled`: `true` → `false` (was auto-starting rdev::listen, which requests Accessibility/Input Monitoring on macOS) - `screen_intelligence.use_vision_model`: `true` → `false` (fewer surprise vision-model calls; Pass 1 Apple Vision OCR still runs) Aligns all permission-gated auto-starts on a consistent opt-in posture: `screen_intelligence.enabled`, `autocomplete.enabled`, and `voice_server.auto_start` already default to `false`. Users must now explicitly flip each toggle (config or JSON-RPC) before the core triggers any OS permission dialog. * feat(channels): fire typing indicator on webhook-inbound path Two inbound flows exist today and only one fires typing: - Local bot (`channels_config.telegram.bot_token` set) → dispatch.rs already calls `channel.start_typing` + `spawn_scoped_typing_task` - Backend webhook (Telegram → backend → socket.io → core) → `ChannelInboundSubscriber` had **no typing call** — replies route via backend REST, so the local `Channel` trait isn't reachable. Close the gap by going through the backend: - `api/rest.rs`: add `send_channel_typing(channel, jwt, body)` hitting the new `POST /channels/:id/typing` backend route. - `channels/bus.rs`: extract the agent-wait loop into `run_agent_loop` and wrap it with a typing task that fires immediately on `start_chat` success, refreshes every 4s (beats Telegram's ~5s and Discord's ~10s typing TTLs), and cancels on every exit path (done / error / empty / bus-closed / lagged / timeout). Backend failures log at debug — a flaky typing call must never block the reply flow. Generalises to every channel with a backend adapter; adapters without a native typing API no-op gracefully. * Enhance test stability by introducing a Mutex guard for TRIAGE_DISABLED_ENV in tests - Added a static Mutex guard to ensure safe concurrent access to the `TRIAGE_DISABLED_ENV` variable during tests, preventing interleaved set_var/remove_var calls that could lead to spurious failures. - Updated relevant test cases to acquire the Mutex lock when accessing the environment variable, ensuring consistent behavior across concurrent test executions. |
||
|
|
933c233704 |
fix(voice): add hallucination filter to chat voice path (#553) (#556)
* fix(voice): add hallucination filter to chat voice path and improve detector (#553) The chat voice transcription pipeline (ops.rs voice_transcribe_bytes) had no hallucination filtering, unlike the desktop dictation server which has had it since inception. This caused Whisper to inject repetitive garbage text ("it... it... it...", "Thank you. Thank you. Thank you.") into chat voice input, especially on short/silent recordings. Changes: - Extract hallucination detection into shared voice/hallucination.rs module - Add hallucination filter to voice_transcribe_bytes (chat voice path) - Improve detector: strip punctuation before word comparison, add dominant-word ratio check (>40%), catch "it... it... it..." patterns - Add 14 unit tests covering exact match, repetition, ratio, and legitimate speech cases Closes #553 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(voice): introduce HallucinationMode enum with split pattern lists Split monolithic HALLUCINATION_PATTERNS into ALWAYS_HALLUCINATION (blank-audio, YouTube phrases — filtered in all modes) and DICTATION_ONLY_PATTERNS (single-word noise like "yes", "okay" — filtered only in desktop dictation). Add repeating n-gram detection for looping phrases ("Thank you. Thank you. Thank you.") and raise dominant-word ratio from >40%/3 to >60%/5 to prevent false positives on emphatic speech like "no no no don't do that". Addresses CodeRabbit review on PR #556. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(voice): use Conversation mode for chat, Dictation mode for desktop Wire HallucinationMode into both voice paths: - ops.rs (chat voice): HallucinationMode::Conversation — conservative filtering allows short replies like "yes", "okay", "thank you" - server.rs (desktop dictation): HallucinationMode::Dictation — aggressive filtering drops single-word noise artifacts - Update server.rs hallucination_detection test for new signature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(voice): redact user transcript content from debug logs Remove raw text interpolation (normalized, first, word, pattern) from hallucination detection debug logs to prevent leaking sensitive speech content. Retain non-PII metadata (repeat counts, ratios, n-gram length) for diagnostics. Addresses CodeRabbit review on PR #556. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
219a2ff9af |
Fix: GitHub composeio (#543)
* feat(composio): add GitHub repository management and trigger creation - Enhanced the ComposioConnectModal component to support loading and selecting GitHub repositories for connected users. - Introduced new API functions for listing GitHub repositories and creating triggers, improving integration capabilities with GitHub. - Added state management for repository loading, selection, and trigger action feedback, enhancing user experience during GitHub integration. - Updated types to include GitHub repository structures and responses, ensuring type safety and clarity in the codebase. * feat(composio): add GitHub repository listing and trigger creation APIs - Implemented new API endpoints for listing GitHub repositories and creating triggers, enhancing integration capabilities with GitHub. - Updated types to include responses for GitHub repositories and trigger creation, ensuring type safety and clarity. - Added corresponding handler functions and schemas to support the new operations, improving overall functionality and user experience in the Composio integration. * refactor(composio): remove GitHub repository and trigger management from ComposioConnectModal - Eliminated GitHub repository loading and trigger creation logic from the ComposioConnectModal component, streamlining its functionality. - Removed associated state management and API calls for GitHub repositories and triggers, enhancing code clarity and maintainability. - Updated types to reflect the removal of GitHub-related structures, ensuring consistency across the codebase. * format: ran format |
||
|
|
21e4a8b307 |
fix(onboarding): remove Screen & Accessibility Permissions step (#557)
* fix(onboarding): remove Screen & Accessibility Permissions step The permissions step added friction to onboarding without being essential — users can still configure screen intelligence permissions later via Settings. Steps are now: Welcome → Referral → Skills → Context Gathering. * fix(onboarding): remove Screen & Accessibility Permissions step The permissions step added friction to onboarding without being essential — users can still configure screen intelligence permissions later via Settings. Steps are now: Welcome → Referral → Skills → Context Gathering. * fix(onboarding): skip context gathering when no sources connected When the user clicks "Skip for Now" on the Gmail step, complete onboarding immediately instead of showing the context gathering step. * fix(onboarding): address CodeRabbit review feedback - Preserve accessibilityPermissionGranted from existing state instead of hardcoding false (matches ToolsPanel defensive pattern) - Update E2E test step comments and detection logic to match the real onboarding flow (WelcomeStep → ReferralApplyStep → SkillsStep → ContextGatheringStep) and use actual UI text |
||
|
|
d5be45d42d | chore(release): v0.52.9 v0.52.9 | ||
|
|
95ccf86069 | chore(release): v0.52.8 | ||
|
|
2824850708 |
feat(streaming): thinking tokens, tool call deltas, and progressive channel edits (#549)
* feat(conversations): implement live streaming for assistant responses - Added support for live streaming of assistant responses in the Conversations component, enhancing user experience during interactions. - Introduced new interfaces for handling streaming state, including `StreamingAssistantState` and related event handlers for text, thinking, and tool argument deltas. - Updated the state management to accommodate streaming data, ensuring smooth updates to the UI as new content arrives. - Enhanced the rendering logic to display provisional assistant bubbles and thinking indicators while responses are being composed. - Refactored existing event handling to integrate with the new streaming functionality, improving overall responsiveness and interactivity. This commit significantly improves the real-time interaction capabilities of the assistant, providing users with immediate feedback during conversations. * feat(channels): progressive-edit streaming for inbound channels ChannelInboundSubscriber now buffers text/tool delta events on a 1s timer and edits the outbound channel message in place, so Telegram/ Slack-style conduits can show a single evolving reply instead of a single atomic bubble at the end. Renders a "🔧 tool …" status line above the partial text and rewrites with the final canonical reply on chat_done. Falls back to atomic-final delivery if the backend's PATCH /channels/:channel/messages/:id endpoint is unavailable or repeatedly fails, so existing channels keep working while the edit endpoint is rolled out. New rest.rs helper: BackendOAuthClient::send_channel_edit. * style: cargo fmt on streaming-related files Auto-applied by cargo fmt after the streaming plumbing changes touched provider traits, the session turn loop, the channel inbound subscriber, and the compatible-provider SSE path. * feat(streaming): compact live preview + Telegram typing indicator UI: while streaming, show only the trailing ~120 chars of assistant text in a monospace ticker-tape bubble (cursor + ellipsis prefix) so the scroll position doesn't jump as tokens arrive. The full response still replaces the preview via addInferenceResponse on chat_done. Backend bridge: ChannelInboundSubscriber now fires Telegram's typing indicator as soon as an inbound message is received and refreshes it every 4 s while the turn is in flight (Telegram's sendChatAction lasts ~5 s). New BackendOAuthClient::send_channel_typing hits POST /channels/:channel/typing; the subscriber latches typing_disabled after two failures so channels without the endpoint stop getting hit. * fix(providers): fall back to JSON parse when upstream ignores stream=true Some OpenAI-compatible backends (including our e2e mock) accept `stream: true` in the request but reply with a regular `application/json` body rather than an SSE stream. The previous implementation blindly pushed the body through the SSE line parser, which produced an empty aggregated response because the body never contained `\n\n` event separators. Detect the non-SSE content-type and fall through to the existing `parse_native_response` path so the caller still gets the aggregated response. No deltas are emitted in this case — there's nothing to stream — but correctness is preserved. Unblocks the json_rpc_protocol_auth_and_agent_hello E2E test. * Enhance event handling for progressive-edit streaming in ChannelInboundSubscriber - Introduced a new `StreamingState` struct to manage the state of progressive-edit streaming, allowing for buffered text and tool deltas. - Implemented a timer-based flushing mechanism for edits, ensuring timely updates to the channel. - Refactored event handling logic to accommodate new event types (`text_delta`, `tool_call`, `tool_result`) and improved error handling for chat events. - Updated the logic for finalizing channel replies to handle both streaming and atomic delivery scenarios, enhancing overall responsiveness and user experience. This commit significantly improves the handling of real-time updates during user interactions, providing a smoother and more interactive experience. * Enhance tool call tracking in AgentProgress and parsing logic - Added a `call_id` field to `ToolCallStarted` and `ToolCallCompleted` variants in the `AgentProgress` enum to uniquely identify tool calls and link them to their respective events. - Updated the `ParsedToolCall` struct to include an optional `id` field for tool calls originating from native responses, ensuring consistent tracking across different call types. - Modified the `parse_tool_call_value` function to initialize the `id` field appropriately, enhancing the parsing logic for tool calls. - Adjusted the `run_tool_call_loop` function to utilize the new `call_id` for progress events, ensuring accurate tracking of tool execution across iterations. - Enhanced the `spawn_progress_bridge` function to handle the new `call_id` field in progress events, improving the overall event handling mechanism. These changes improve the robustness of tool call tracking and enhance the clarity of event relationships within the agent's progress reporting. * Enhance tool call tracking and event handling in Conversations component - Added a `tool_call_id` field to `ChatToolCallEvent` and `ChatToolResultEvent` interfaces for improved tracking of tool calls across events. - Updated event key generation in the Conversations component to include `tool_call_id`, ensuring unique identification of tool events. - Enhanced the logic for managing tool timelines to prevent duplication of entries by reconciling existing tool calls based on `tool_call_id`. - Improved handling of tool argument deltas and results, allowing for more accurate updates to the UI during tool execution. These changes significantly improve the robustness of tool call tracking and enhance the clarity of event relationships within the Conversations component. * Enhance tool call event handling and progress reporting in Agent - Updated the `run_tool_call_loop` function to include stable IDs for tool calls, ensuring unique identification across iterations. - Introduced early completion events for failed tool calls, improving client-side error handling and user experience. - Refactored the `emit_progress` function to use asynchronous sending, ensuring lifecycle events are not dropped due to backpressure. - Enhanced the `turn` method to await progress emissions, improving synchronization during user message processing. These changes significantly improve the robustness of tool call tracking and enhance the clarity of event relationships within the agent's progress reporting. * fix(channels): close stuck drafts, prevent duplicate post, add bridge logs Findings #3, #5, #6 from the follow-up review: channels/bus.rs - chat_done handler no longer returns early on empty reply — it now finalizes with a "(No response from agent.)" fallback so any draft we posted during streaming gets closed off instead of being left showing "_working…_" forever. - StreamingState gained `draft_sent: bool`, set whenever the initial send_channel_message succeeds (even when the backend's response didn't include an id). finalize_channel_reply now checks this flag and silently skips the "no draft → send atomic" fallback when a draft was posted but id was lost — fixes a duplicate-bubble bug where an id-less draft plus a chat_done finalize produced two messages in the user's channel. channels/providers/web.rs - spawn_progress_bridge now logs a scoped entry message on startup (client_id/thread_id/request_id), a per-variant trace/debug line on each AgentProgress event (with call_id/iteration correlation), and an exit message with final round + events_seen count. SubagentFailed is logged at warn level for visibility. |
||
|
|
3db06e8e92 |
feat(prompt): per-agent PROFILE.md + MEMORY.md injection, 2K-char cap (#550)
* Enhance debug-agent-prompts script and prompt rendering logic - Updated the `debug-agent-prompts.sh` script to always run `cargo build`, ensuring the latest binary is used and preventing stale binaries from affecting agent behavior. - Modified the output directory handling to wipe and recreate it at the start of each run, ensuring a clean snapshot of the current agent set. - Enhanced the `render_subagent_system_prompt` function to unconditionally inject `PROFILE.md`, ensuring it is included even when identity information is omitted, thus improving personalization for agents like `welcome`. - Added tests to verify the correct injection of `PROFILE.md` under various conditions, ensuring robust functionality and preventing regressions in prompt rendering. * Enhance debug-agent-prompts script to utilize the currently-logged-in user's workspace - Updated the `debug-agent-prompts.sh` script to point to the real user's workspace, ensuring onboarding-generated files like `PROFILE.md` are included in the dump. - Improved workspace resolution logic to prioritize the active user's workspace, falling back to default paths as necessary. - Added error handling for cases where the workspace is not found, providing clear guidance for users to complete onboarding or specify a different workspace. - Enhanced output to include the presence state of `PROFILE.md`, improving visibility into the onboarding process. * Add profile inclusion for user-facing agents to enhance personalization - Updated agent TOML configurations for orchestrator, trigger reactor, trigger triage, and welcome agents to include user profile data by setting `omit_profile = false`. This allows agents to personalize interactions based on user context derived from `PROFILE.md`. - Refactored the `AgentDefinition` struct to include a new `omit_profile` field, ensuring that agents can opt-in to utilize user profile information. - Enhanced prompt rendering logic to conditionally inject `PROFILE.md` based on the `omit_profile` flag, improving the relevance and personalization of agent responses. - Updated tests to verify the correct behavior of profile inclusion across various agents, ensuring robust functionality and preventing regressions. * Implement `omit_profile` flag in `AgentBuilder` and `Agent` for profile management - Added a new `omit_profile` field to the `AgentBuilder` struct, allowing agents to specify whether to include user profile data in their responses. - Updated the `Agent` struct to mirror the `omit_profile` flag, ensuring that the profile inclusion logic is consistent across agent instances. - Enhanced the `omit_profile` method in `AgentBuilder` to facilitate the configuration of this flag during agent construction. - Adjusted the default behavior to omit profiles for legacy agents while allowing opt-in for specific agents that require user context. - Updated documentation to clarify the purpose and usage of the `omit_profile` flag in agent definitions. * Implement profile management enhancements in Agent and prompt rendering - Introduced an `omit_profile` flag in the `AgentBuilder` and `Agent` to control the inclusion of user profile data in responses, defaulting to true for legacy paths. - Updated the `Agent` struct to utilize the `omit_profile` flag, ensuring consistent profile inclusion logic across agent instances. - Enhanced prompt rendering logic to conditionally include or exclude `PROFILE.md` based on the `omit_profile` setting, improving personalization for user-facing agents. - Added tests to verify the correct behavior of profile inclusion and omission across various scenarios, ensuring robust functionality and preventing regressions. * feat(prompt): per-agent MEMORY.md injection with 2000-char cap Add `omit_memory_md` to `AgentDefinition` (mirror of `omit_profile`) and inject `MEMORY.md` alongside `PROFILE.md` in both the main and sub-agent render paths. Both user-specific files are capped at `USER_FILE_MAX_CHARS = 2_000` (~1000 tokens each) via a new `inject_workspace_file_capped` helper so growing on-disk files can't balloon the system prompt. Opt-in on the same four user-facing agents (welcome, orchestrator, trigger_triage, trigger_reactor). Narrow specialists leave it at the `true` default. KV-cache contract is documented on the flag, the injection sites, and the capped helper: rendered bytes are frozen per session, and mid-session writes only surface on the next session. Pinned with a new `rendered_subagent_system_prompt_is_byte_stable_across_repeat_calls` test plus coverage for injection / opt-out / 2000-char cap. * refactor(tests): clean up test formatting and improve readability - Removed unnecessary line breaks and adjusted indentation in test files for better consistency and clarity. - Reformatted the `RewardsCouponSection` test to enhance readability and maintain a uniform style across test cases. - Ensured that all test cases align with the updated formatting standards, improving overall maintainability. * feat(debug-agent-prompts): enhance output directory validation and canonicalization - Improved the `debug-agent-prompts.sh` script to validate and canonicalize the output directory (`OUT_DIR`) before performing any file operations. - Added checks to reject relative paths and ensure the output directory is an absolute path, preventing potential catastrophic deletions. - Implemented a `canonicalize` function that uses `realpath` or `readlink` to resolve paths, with a fallback to Python for compatibility on barebones systems. - Enhanced error handling to provide clear feedback when the output directory cannot be validated or canonicalized. - Ensured that the script operates on the canonicalized path for all subsequent commands, maintaining consistency and safety. * style(turn): single-line rustfmt for redacted log branch |
||
|
|
8cbb425cea |
feat(onboarding): fire welcome agent immediately on completion (#548)
* Implement proactive welcome agent for onboarding experience
- Added a new module `welcome_proactive` to handle immediate welcome messages after user onboarding completion, enhancing user engagement.
- Updated `set_onboarding_completed` to trigger the proactive welcome agent upon onboarding status change, ensuring timely delivery of welcome messages.
- Refactored the onboarding process to streamline the integration of proactive messaging, improving overall user experience.
- Enhanced documentation and logging for better observability of the onboarding flow and proactive message handling.
- Introduced tests to validate the functionality of the new welcome agent and its integration into the onboarding process.
* fix(socketio): auto-join "system" room so proactive messages reach clients
The proactive message subscriber emits with `client_id="system"`, but
connected Socket.IO clients only auto-joined a room named after their
own sid — so the welcome agent's message was published into an empty
room and never reached any frontend.
Adds `socket.join("system")` at connect time alongside the existing
per-sid join, so every client now receives broadcast proactive events
(welcome agent, morning briefing, cron announcements).
Also adds scripts/test-proactive-welcome.sh — end-to-end smoke test
that resets onboarding flags, spawns a fresh core on port 7789,
connects a Socket.IO listener, fires the RPC, and reports pass/miss
for every checkpoint in the pipeline including client-side delivery.
* fix(welcome): PR review — tighter gating, legacy-cron prune, safer harness
- Gate proactive welcome spawn on `!was_chat_completed` so a user
whose chat flow already completed (legacy tool path or manual flip)
doesn't get a second welcome.
- Prune legacy `welcome` cron jobs in `seed_proactive_agents`: one-
shot entries left behind by an interrupted earlier run would
otherwise double-deliver once the scheduler picks them up. Added
a unit test covering the prune + morning-briefing seed in the same
call.
- Add a post-publish debug log in `welcome_proactive::run_proactive_welcome`
so "reached end successfully" is distinguishable from "silently
bailed above" by reading the log alone.
- Replace ignored `socket.join(...)` results with a helper that logs
success + failure per room + client id. Silent join failures on the
"system" room make proactive delivery vanish without a trace.
- Harden the test harness:
* Back up CONFIG_PATH before mutating and restore on exit so the
developer's staging profile is never permanently changed (unless
`--keep-flags` is passed).
* Tolerate inline comments + trailing whitespace in the TOML
rewrite; append-at-end instead of prepend when a key is missing,
so the rewrite can't accidentally land inside a section header.
Not applied:
- Unit tests for `run_proactive_welcome` empty-response / serialization-
failure paths: empty response is already `anyhow::bail!`-guarded, and
the serde_json failure branch is unreachable given a `json!`-built
value. Testing either requires mocking `Agent::from_config_for_agent`
which has heavy registry/provider dependencies — cost > value.
|
||
|
|
5a8a7edb91 |
Refine billing, settings, rewards, and usage UI (#547)
* feat: add react-icons support and refactor skill category handling - Added `react-icons` dependency to the project for enhanced icon usage. - Introduced new skill icons in the `toolkitMeta.tsx` component, replacing SVG icons with `react-icons` for improved maintainability and consistency. - Created a new `skillCategories.ts` file to define skill categories and their order, streamlining the management of skill categories across the application. - Refactored the `SkillCategoryFilter` component to utilize the new skill categories structure, enhancing clarity and reducing redundancy in the codebase. - Updated the `Skills` page to leverage the new icon rendering method and skill categories, improving the overall user experience. - Added tests to ensure the correct functionality of the new skill category and icon implementations. * feat: update environment configuration and enhance settings UI - Updated `.env.example` and `app/.env.example` to reflect new backend URL and added optional environment selector for staging. - Enhanced `SettingsHome` component by separating account and billing sections for improved clarity. - Introduced a new billing section in the settings menu to streamline user navigation. - Updated `useSettingsNavigation` hook to accommodate changes in settings structure. - Improved `BillingPanel` to handle session token checks and ensure accurate billing state retrieval. - Refactored `Rewards` page to enhance user experience with clearer progress indicators and improved layout. - Added tests to validate changes in the rewards and settings components. * feat(config): enhance API base URL handling and environment configuration - Introduced a new staging API base URL constant for better environment management. - Added app environment variable constants to streamline environment detection. - Refactored effective API URL resolution to accommodate environment-specific defaults. - Implemented functions to resolve app environment from process environment variables. - Added tests to validate the correct behavior of staging and production API URL handling. * feat(rewards): add community and referrals tabs for rewards management - Introduced `RewardsCommunityTab` and `RewardsReferralsTab` components to enhance the rewards management interface. - The `RewardsCommunityTab` displays user progress, Discord role statuses, and connection options, improving user engagement with rewards. - The `RewardsReferralsTab` allows users to manage their referral program, track progress, and access coupon rewards in a streamlined layout. - Updated the `Rewards` page to integrate these new tabs, enhancing overall user experience and navigation. * feat(rewards): introduce ReferralRewardsSection and RewardsRedeemTab components - Added `ReferralRewardsSection` to manage referral statistics and code application, enhancing user engagement with the referral program. - Created `RewardsRedeemTab` to streamline the process of applying reward codes, improving the overall rewards management experience. - Updated `Rewards` page to include the new redeem tab, allowing users to easily switch between referral and redeem functionalities. - Refactored `RewardsCommunityTab` to adjust the referral selection handler, ensuring consistent navigation across the rewards interface. - Removed redundant UI elements in `RewardsCouponSection` for a cleaner layout. - Enhanced tests to cover new functionalities and ensure robust performance across the rewards system. * feat(ui): introduce PillTabBar component and refactor SkillCategoryFilter and Rewards pages - Added a new `PillTabBar` component to enhance tab navigation with customizable styles and item rendering. - Refactored `SkillCategoryFilter` to utilize `PillTabBar`, improving code clarity and reducing redundancy in button rendering. - Updated the `Rewards` page to replace the existing tab navigation with `PillTabBar`, streamlining the user interface for switching between referral, rewards, and redeem tabs. - Enhanced the `ReferralRewardsSection` layout for better user experience and consistency across the rewards management interface. - Improved tests to cover the new `PillTabBar` functionality and ensure robust performance across the updated components. * fix(rewards): update placeholder and button text in RewardsCouponSection - Changed the input placeholder from "Promo code" to "Coupon code" for clarity. - Updated button text from "Apply code" to "Redeem Code" to better reflect the action being performed. - Adjusted loading state text from "Applying…" to "Redeeming..." for consistency in user feedback. * feat(composio): enhance toolkit handling and improve user messaging - Updated the `ComposioConnectModal` to simplify the connection message, removing unnecessary wording for clarity. - Introduced a `TOOLKIT_ALIASES` mapping in `toolkitMeta.tsx` to standardize toolkit slugs, improving consistency across the application. - Refactored the `composioToolkitMeta` function to utilize the new slug mapping, enhancing toolkit metadata retrieval. - Improved the `useComposioIntegrations` hook to leverage the canonicalized toolkit slugs for better integration handling. - Adjusted the `Skills` page to normalize toolkit slugs during rendering, ensuring a consistent user experience. - Updated tests to reflect changes in messaging and toolkit handling, ensuring robust functionality across the application. * feat(intelligence): add new tabs for Dreams, Memory, and Subconscious features - Introduced `IntelligenceDreamsTab`, which displays generated dreams based on daily life events, enhancing user engagement with a visually appealing layout. - Added `IntelligenceMemoryTab` to manage actionable items, featuring search and filter capabilities for improved user interaction with memory data. - Created `IntelligenceSubconsciousTab` to handle subconscious tasks and logs, providing users with insights and management options for their subconscious activities. - Refactored the `RewardsCommunityTab` to remove unused Discord role status logic, streamlining the component for better performance. - Implemented a new `PageBackButton` component for consistent navigation across settings pages. - Enhanced the `BillingPanel` and its subcomponents to improve user experience in managing billing and subscription details, including transaction history and payment methods. - Added new billing-related tabs for better organization and access to billing features, including `BillingOverviewTab`, `BillingPaymentsTab`, and `BillingPlansTab`. - Updated tests to ensure functionality across new and refactored components, maintaining robust application performance. * refactor(billing): update BillingPanel and BillingPlansTab for improved user experience - Changed the default selected tab in `BillingPanel` from 'overview' to 'plans' to prioritize subscription management. - Removed the `BillingOverviewTab` from the `BillingPanel`, streamlining the billing interface. - Enhanced the `BillingPlansTab` header to clarify the purpose, changing "Explore tiers" to "Choose a Subscription Plan". - Updated the description in `BillingPlansTab` for better clarity on payment options. - Improved the layout of the `SubscriptionPlans` component to better highlight crypto payment options and their availability. - Cleaned up unused code and comments for better maintainability. * refactor(billing): streamline BillingPanel and BillingPlansTab components - Removed unused `teamUsage` state and related API call from `BillingPanel` to simplify data management. - Adjusted layout in `BillingPlansTab` for improved visual hierarchy and user experience. - Cleaned up code by eliminating unnecessary comments and enhancing maintainability. * refactor(billing): enhance SubscriptionPlans layout for improved responsiveness - Updated the layout of the `SubscriptionPlans` component to ensure better responsiveness and visual consistency. - Adjusted class names to include minimum height and width properties for better alignment across different screen sizes. - Enhanced the layout of the pricing display section for improved clarity and user experience. * refactor(billing): update subscription plans and billing components for improved clarity and user experience - Adjusted pricing for BASIC and PRO plans to reflect new monthly and annual rates. - Enhanced feature descriptions for subscription plans to better communicate value. - Removed redundant UI elements in the BillingPaymentsTab and PayAsYouGoCard for a cleaner layout. - Added loading and confirmation messages in SubscriptionPlans to improve user feedback during payment processes. - Updated class names for better responsiveness and visual consistency across billing components. * refactor(billing): improve error messaging and UI consistency in billing components - Updated error message in BillingPanel to specify adding a payment card on Stripe for clarity. - Changed header text in AutoRechargeSection to "Enable Auto-Recharge" for better user understanding. - Modified button text in AutoRechargeSection to "Add card on Stripe" for consistency. - Enhanced styling in PayAsYouGoCard for improved visual appeal and user interaction. - Removed redundant UI elements in PayAsYouGoCard for a cleaner layout. * refactor(billing): remove unused error handling and improve UI consistency across billing components - Eliminated `setArError` prop from BillingPanel, AutoRechargeSection, and BillingPaymentsTab to streamline error handling. - Enhanced layout and styling in BillingHistoryTab and SubscriptionPlans for better visual consistency and user experience. - Removed the BillingOverviewTab component to simplify the billing interface and improve maintainability. * refactor(billing): update feature descriptions and enhance SubscriptionPlans display - Revised feature descriptions in the PLANS array for clarity and conciseness. - Increased the number of displayed features in the SubscriptionPlans component to provide users with more information at a glance. * refactor(billing): update billing components for improved clarity and functionality - Revised feature descriptions in the PLANS array to reflect increased usage limits. - Renamed header in BillingHistoryTab to "Transaction History" and updated description for clarity. - Adjusted transaction amount formatting in BillingHistoryTab to display five decimal places. - Removed redundant UI elements in BillingPaymentsTab to streamline the layout. - Enhanced PayAsYouGoCard with improved credit balance display and top-up options, including validation for custom amounts. * feat(usage): add budget completion message logic and update tests - Introduced `shouldShowBudgetCompletedMessage` to the `UsageState` interface to indicate when the budget completion message should be displayed. - Updated the `useUsageState` hook to calculate the budget completion message based on user credits and budget status. - Enhanced tests for `useUsageState` to verify the correct behavior of the budget completion message under various scenarios. - Modified the `Conversations` component to display the budget completion message appropriately based on the new logic. * style: apply formatter fixes from pre-push hook * refactor(rewards): update coupon section and test cases for clarity and consistency - Renamed placeholder text and button labels in the RewardsCouponSection test to reflect updated terminology. - Adjusted test assertions to ensure they align with the new button and placeholder names. - Updated pricing details in billingHelpers tests to reflect new monthly and annual rates for BASIC and PRO plans. - Enhanced the ContextGatheringStep labels for better clarity regarding email and LinkedIn processing stages. * style(tests): format coupon code input changes for consistency - Reformatted the coupon code input changes in the RewardsCouponSection test for improved readability and consistency. - Ensured that the test cases maintain a uniform style for better maintainability. * refactor: enhance accessibility and improve code structure in various components - Added ARIA roles and attributes to the PillTabBar for better accessibility. - Refactored the canonicalization logic for toolkit slugs into a new file for improved organization. - Updated the IntelligenceDreamsTab and IntelligenceMemoryTab components for better readability and accessibility. - Enhanced error handling and logging in the IntelligenceSubconsciousTab for improved debugging. - Streamlined the ReferralRewardsSection and RewardsCommunityTab components by normalizing referral code input handling. - Removed unused props and improved layout consistency in BillingPanel and related components. - Updated the Skills page to handle subconscious escalation dismissals more effectively. * feat(release): configure staging environment for deployment - Added steps to configure the staging app environment in the release workflow. - Set environment variables for staging, including OPENHUMAN_APP_ENV and VITE_OPENHUMAN_APP_ENV. - Updated build and deployment steps to conditionally use staging settings based on the build target. - Ensured proper handling of workspace paths for staging deployments. * chore(env): add optional staging environment variable to .env.example - Introduced OPENHUMAN_APP_ENV variable to specify the app environment as 'staging'. - Updated .env.example to include new environment configuration for clarity. * refactor(intelligence): streamline navigation and improve text formatting - Simplified the navigation logic in the IntelligenceSubconsciousTab for better readability. - Improved text formatting in the IntelligenceDreamsTab for enhanced clarity and consistency. - Refactored import statements in toolkitMeta.tsx for better organization. |
||
|
|
f26a0c50b0 |
feat(referral): switch to link-based claims with flat $5 rewards (#546)
* refactor(referral): update referral system to a one-time flat reward structure - Transitioned to a link-based referral system offering a one-time $5 credit to both the referrer and the referred user upon the first subscription payment. - Removed the previous reward rate in basis points and eliminated recurring rewards, ensuring clarity in the referral process. - Updated API endpoints and service methods to reflect the new `claimReferral` functionality, enhancing user experience and eligibility checks. - Revised documentation and tests to align with the new referral structure, ensuring comprehensive coverage and understanding of the changes. * refactor(referral): simplify JSON response handling in referral claim function - Streamlined the `handle_referral_claim` function by removing unnecessary `as_deref()` and `filter()` calls, enhancing code clarity and performance. - Updated the JSON response construction to eliminate redundant line breaks, improving readability without altering functionality. |
||
|
|
7685e877ee |
feat(agent): welcome->orchestrator routing + per-agent tool scoping (#525, #526) (#544)
* feat(agent): add subagents + delegate_name fields to AgentDefinition (#525, #526) Introduces the schema change needed to make agent definitions the single source of truth for both direct tools and delegation targets: - `subagents: Vec<SubagentEntry>` — declarative list of agents this agent can spawn, expanding at build time into synthesised delegate_* tools on the LLM's function-calling surface. Supports two TOML shapes via `#[serde(untagged)]`: * Bare string (`"researcher"`) → `SubagentEntry::AgentId` * Inline table (`{ skills = "*" }`) → `SubagentEntry::Skills(SkillsWildcard)` The `Skills` variant expands dynamically to one delegate_{toolkit} tool per connected Composio toolkit at runtime. - `delegate_name: Option<String>` — optional override for the tool name this agent is exposed as when another agent lists it in `subagents`. Defaults to `delegate_{id}` when absent, lets the researcher agent be exposed as `research`, code_executor as `run_code`, etc. Schema only — no runtime behavior change yet. Follow-up commits wire the field into `collect_orchestrator_tools`, the dispatch path, and the debug dump. TOML placement note: `subagents = [...]` must appear before the `[tools]` table header in agent TOMLs. Once a table section opens, every subsequent top-level key is consumed by that table, so placing `subagents` after `[tools]` parses it as `tools.subagents` and fails deserializing ToolScope. The test doc-comment records this constraint. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(agent): drive orchestrator delegation tools from TOML subagents (#525, #526) Completes the half-built migration from a hardcoded ARCHETYPE_TOOLS table + orphan skill_delegation.rs to a TOML-driven delegation surface where each agent declares its subagents and the tool list is synthesised from the registry at agent-build time. Rewrites `collect_orchestrator_tools` to take the orchestrator's AgentDefinition, the global AgentDefinitionRegistry, and the slice of connected Composio integrations, then iterates the definition's `subagents` field: * `SubagentEntry::AgentId` → one ArchetypeDelegationTool. The tool's `name()` comes from the target agent's `delegate_name` override (or `delegate_{id}` fallback) and its `description()` is the target's `when_to_use`. Editing an agent's TOML when_to_use now immediately updates the tool schema the orchestrator LLM sees — zero drift, no hardcoded description strings to keep in sync. * `SubagentEntry::Skills { skills = "*" }` → one SkillDelegationTool per connected Composio toolkit. Each routes to the generic skills_agent with `skill_filter` pre-populated. Empty integrations list (CLI path, or user not yet connected) produces zero tools rather than phantom `delegate_*` entries for unconnected toolkits. Also in this commit: - Wire the orphan `skill_delegation.rs` into `impl/agent/mod.rs` via `mod skill_delegation;` + `pub use SkillDelegationTool;`. The file has existed since earlier work but was never declared in the module tree, so it compiled as dead code. - Delete the legacy `MAIN_AGENT_TOOL_ALLOWLIST` constant and the `main_agent_tools` filter in `tools/ops.rs`. They were documented as "no longer the primary source of truth" since the from_config builder switched to `collect_orchestrator_tools`, and grep confirms no external callers remain. Clean deletion. - Delete the hardcoded `ARCHETYPE_TOOLS` const in `tools/impl/agent/mod.rs`. The 4-entry table has been replaced by the orchestrator TOML's `subagents` list (which covers those 4 plus archivist plus the skills wildcard), and the re-export in `tools/mod.rs` is removed accordingly. - Update `agents/orchestrator/agent.toml`: add the `subagents` field listing researcher / planner / code_executor / critic / archivist / { skills = "*" }. Keep `spawn_subagent` in `[tools] named` as an advanced fallback so power users can still spawn custom workspace- override agent ids that aren't in the declarative subagents list. - Add `delegate_name = "..."` to the 5 archetype TOMLs so the orchestrator LLM sees natural tool names (`research`, `plan`, `run_code`, `review_code`, `archive_session`) rather than the `delegate_<agent_id>` fallback. - Update `agent/harness/session/builder.rs` (line ~461) to call the new `collect_orchestrator_tools` signature. Looks up the orchestrator definition from the global registry; passes an empty integrations slice because the builder is synchronous and cannot await Composio's async fetch. The channel-dispatch path will populate integrations in a later commit — the CLI/REPL path ships without per-toolkit delegation tools, which is acceptable regression since CLI users still reach Composio via `composio_execute` and the retained `spawn_subagent` fallback. Tests: * 5 new unit tests in `orchestrator_tools.rs` cover the baseline AgentId + Skills wildcard expansion, empty-integrations edge case, unknown-id graceful skip, non-delegating agent with empty subagents, and the slug sanitiser for tool-name-safe Composio toolkit names. * Runs clean alongside all existing agent-module tests (323 pass; one pre-existing Windows-path failure in `self_healing::tests:: tool_maker_prompt_includes_command` is unrelated to this PR and fails identically on the upstream baseline). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(agent): plumb per-agent tool scoping through bus + tool loop (#525, #526) Adds the parameter plumbing for agent-aware tool filtering without changing any runtime behaviour. Every existing call site continues to pass `None` / empty extras, so the LLM still sees the full unfiltered registry — the actual routing logic that populates these fields lands in commit 4b (dispatch.rs onboarding-flag → target_agent_id). Why two parameters and not one filter: Tools in this codebase are `Box<dyn Tool>` — owned trait objects with no Clone impl, stored in a shared `Arc<Vec<Box<dyn Tool>>>`. We can't cheaply build a per-turn filtered subset of the global registry, and we can't mutate the Arc to remove entries. Two new parameters work around this without touching the global registry's lifetime model: * `visible_tool_names: Option<&HashSet<String>>` — whitelist filter applied at the iteration site inside `run_tool_call_loop`. When `Some(set)`, only tools whose `name()` is in the set contribute to the function-calling schema and are eligible for execution; every other tool in the combined registry is hidden from the model and rejected if the model emits a call for it. `None` preserves the legacy "everything visible" behaviour. * `extra_tools: &[Box<dyn Tool>]` — per-turn synthesised tools spliced alongside `tools_registry`. The dispatch path will use this to surface delegation tools (`research`, `delegate_gmail`, …) that are built fresh each turn from the active agent's `subagents` field and the current Composio integration list — tools that don't exist in the global startup-time registry because they depend on per-user runtime state. Empty slice for agents that don't delegate. Inside the loop, `tool_specs` is built from `tools_registry.iter().chain(extra_tools.iter()).filter(is_visible)`, and the tool-execution lookup uses the same chain + filter so the function-calling schema and the execution surface stay in sync. Files touched in this commit: src/openhuman/agent/harness/tool_loop.rs - Add `visible_tool_names` and `extra_tools` parameters to `run_tool_call_loop`. Build `tool_specs` from chained iteration with the visibility filter applied. Replace the `find_tool` call at the execution site with an inline chain+filter lookup so hallucinated calls to filtered-out tools surface as "unknown tool" errors. Drop the now-unused `find_tool` import. - Update the legacy `agent_turn` wrapper to pass `None, &[]`, preserving its existing unfiltered behaviour. - Update all 9 in-file test sites to pass `None, &[]`. src/openhuman/agent/harness/tests.rs - Update all 3 `run_tool_call_loop` test sites to pass `None, &[]`. src/openhuman/agent/bus.rs - Add `target_agent_id: Option<String>`, `visible_tool_names: Option<HashSet<String>>`, and `extra_tools: Vec<Box<dyn Tool>>` fields to `AgentTurnRequest`, with rustdoc explaining each. - Destructure the new fields in the `agent.run_turn` handler; thread `visible_tool_names.as_ref()` and `&extra_tools` through to `run_tool_call_loop`. Augment the dispatch trace with target_agent / extra_tool_count / visible_tool_count / filter_active so production logs show whether scoping is active. - Update the in-test `test_request()` helper to populate the new fields with safe defaults. src/openhuman/agent/triage/evaluator.rs - Update the triage `AgentTurnRequest` initializer to set `target_agent_id = Some("trigger_triage")` (for tracing) with `visible_tool_names: None` + `extra_tools: Vec::new()` because the classifier intentionally runs against an empty registry and emits a structured JSON decision rather than calling tools. src/openhuman/channels/runtime/dispatch.rs - Update the channel-message `AgentTurnRequest` initializer to set the three new fields to safe defaults (`None` / `None` / empty vec). Commit 4b will replace these with the real onboarding-flag based routing. src/openhuman/tools/impl/agent/mod.rs - Bug fix: `dispatch_subagent` previously took `_skill_filter: Option<&str>` but discarded the value, hardcoding `SubagentRunOptions::skill_filter_override = None`. That meant `SkillDelegationTool::execute()` synthesising `dispatch_subagent("skills_agent", ..., Some("gmail"))` never actually narrowed `skills_agent`'s tool list — so even with the orchestrator's view scoped, the spawned `skills_agent` subagent would still see the full Composio catalog. Drop the underscore, propagate `skill_filter` into `skill_filter_override`, and add a tracing log line to make this path observable. This is the downstream half of the #526 leak that commit 3's orchestrator- side scoping alone wouldn't have caught. Tests: 8/8 `tool_loop` tests pass, 3/3 harness `tests.rs` cases pass, 323/324 agent module tests pass overall (the one failure is the same pre-existing Windows-path bug in `self_healing::tool_maker_prompt_ includes_command` that fails identically on the upstream baseline). No existing test expectations were changed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(dispatch): route channel messages to welcome/orchestrator by onboarding flag (#525) Wires the per-agent tool scoping plumbing from commit 4a into the channel-message dispatch path. Each incoming channel message now picks the active agent — `welcome` pre-onboarding, `orchestrator` post — based on `Config::onboarding_completed`, loads the matching definition from the global `AgentDefinitionRegistry`, synthesises any `delegate_*` tools the agent declares in its `subagents` field, and passes everything through to `agent.run_turn` on the bus. This is the half of #525 that makes the welcome agent actually run for new users — the welcome definition has existed since upstream PR #522 but had no caller; nothing in dispatch consulted the onboarding flag, so every channel message ran through the same generic tool loop with the full registry exposed. Changes: src/openhuman/channels/runtime/dispatch.rs - New `AgentScoping` struct carrying the three new `AgentTurnRequest` fields (`target_agent_id`, `visible_tool_names`, `extra_tools`) plus an `unscoped()` constructor for safe-fallback paths. - New async `resolve_target_agent(channel)` helper: * fresh `Config::load_or_init().await` per turn (no cache — the loader reads from disk every call, verified at `config/schema/load.rs:409`, so the welcome→orchestrator handoff is observed on the next message after `complete_onboarding(complete)` flips the flag, with no need for an explicit handoff event); * picks `"welcome"` or `"orchestrator"` based on the flag and emits a structured `[dispatch::routing] selected target agent` info trace recording the choice + the flag value, satisfying the #525 acceptance criterion `"agent-selection logs clearly record why each agent was selected at onboarding boundaries"`; * looks up the definition in `AgentDefinitionRegistry::global()`, gracefully falling back to `AgentScoping::unscoped()` (= legacy behaviour, no filter, no extras) if the registry isn't initialised or the definition isn't found, so a routing miss never fails the user message; * for agents with a non-empty `subagents` field, awaits `composio::fetch_connected_integrations(&config)` and runs `orchestrator_tools::collect_orchestrator_tools` to materialise per-turn delegation tools (`research`, `plan`, `delegate_gmail`, …). Agents with empty `subagents` get an empty extras vec. - New `build_visible_tool_set(definition, &extra_tools)` helper that returns `Some(union)` for `ToolScope::Named` agents (their named list ∪ the names of the synthesised delegation tools) and `None` for `ToolScope::Wildcard` agents to preserve the unfiltered semantics — so agents like `skills_agent` and `morning_briefing` that already work via `wildcard + category_filter` keep their existing behaviour without this layer interfering. - `process_channel_message` calls `resolve_target_agent` once per turn, drops the placeholder defaults from commit 4a, and feeds the real `target_agent_id`/`visible_tool_names`/`extra_tools` into `AgentTurnRequest`. - New imports: `AgentDefinition`, `AgentDefinitionRegistry`, `ToolScope`, `Config`, `fetch_connected_integrations`, `orchestrator_tools`, `Tool`, `HashSet`. End-to-end behaviour after this commit: 1. New user, `onboarding_completed=false`: dispatch picks `welcome`, loads its 2-tool TOML scope, builds `visible_tool_names = {complete_onboarding, memory_recall}`, no extras, hands off to the bus. Bus handler applies the filter → welcome's LLM sees exactly 2 tools. 2. Welcome agent guides the user through setup, eventually calls `complete_onboarding(action="complete")` → flag persists to disk via `config.save()`. 3. Next user message: dispatch reads the flag fresh, picks `orchestrator`, fetches connected Composio integrations, expands `subagents = ["researcher", "planner", "code_executor", "critic", "archivist", { skills = "*" }]` into delegate_research / delegate_plan / delegate_run_code / delegate_review_code / delegate_archive_session + one delegate_<toolkit> per connected integration. visible_tool_names is the union with the 4 direct tools from orchestrator's `[tools] named` list. LLM sees the scoped delegation surface, not the full 1000+ Composio catalog. #526's runtime leak is now fixed end-to-end: the orchestrator's LLM prompt only contains the tools its TOML allows, and the SkillDelegationTool path narrows skills_agent to a single toolkit via the `skill_filter` propagation fix from commit 4a. No agent at any layer sees more than its definition declares. Tests: 599/599 channel module tests pass — including `runtime_dispatch::dispatch_routes_through_agent_run_turn_bus_handler` and the telegram integration variant, which exercise the full bus roundtrip with the new fields populated. No existing assertions were modified. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(debug_dump): apply orchestrator definition filter to main dump (#526) Replaces the explicit `empty_filter: HashSet::new()` in `render_main_agent_dump` with a real visibility whitelist derived from the orchestrator's `AgentDefinition`. The "main" dump path now mirrors the runtime dispatch path from commits 4a/4b — same definition, same delegation tool synthesis, same filter — so `openhuman agent dump-prompt main` shows what the LLM actually sees in production instead of the unfiltered global registry. Before this commit, `dump-prompt main` always rendered every tool in the registry regardless of which agent was supposed to run, which is exactly the symptom #526 reports: "agent prompt tool scopes leak full GitHub tool catalog". The runtime fix in commit 4b stops the leak in production but the dump path was the user's primary observability tool for inspecting prompts, so leaving it unscoped would mask future regressions and confuse debug sessions. Changes in `src/openhuman/context/debug_dump.rs`: * `dump_agent_prompt` now loads `AgentDefinitionRegistry` once at the top (previously only loaded inside the sub-agent branch). When the request is for "main" or "orchestrator_main", it looks up the "orchestrator" definition from the registry and passes it into `render_main_agent_dump` along with the registry itself. Missing orchestrator entry → structured error listing known agents instead of silently rendering an unfiltered prompt. * `render_main_agent_dump` signature gains `registry: &AgentDefinitionRegistry` and `orchestrator_def: &AgentDefinition`. Inside, it: - calls `collect_orchestrator_tools(orchestrator_def, registry, connected_integrations)` to synthesise the same per-turn delegation tools (`research`, `plan`, `delegate_<toolkit>`, …) that dispatch generates; - extends `prompt_tools` with the synthesised extras so they contribute to the rendered tool catalogue; - builds `visible_filter: HashSet<String>` from `orchestrator_def.tools` (the `[tools] named` list) ∪ the names of the synthesised extras, falling back to an empty HashSet when the orchestrator definition uses `ToolScope::Wildcard` (which the prompt builder treats as "no filter, every tool visible") so dump consumers that supply a wildcard orchestrator (custom workspace overrides, tests) retain the legacy unscoped behaviour; - replaces `visible_tool_names: &empty_filter` in the `PromptContext` with `&visible_filter`; - filters the returned `tool_names` and `skill_tool_count` by the same predicate so the `DumpedPrompt` summary fields match what the prompt text actually contains. Tests: * Replaces the previous `render_main_agent_dump_includes_tool_ instructions_and_skill_count` test with two more focused cases: 1. `render_main_agent_dump_wildcard_scope_shows_full_tool_set` — regression guard for the legacy wildcard path. Builds a wildcard-scoped orchestrator definition, asserts every tool from `tools_vec` survives, and checks the standard system- prompt skeleton (Tools section, Tool Use Protocol, cache boundary) still renders. 2. `render_main_agent_dump_named_scope_filters_to_whitelist` — the #526 regression guard. Builds an orchestrator with `ToolScope::Named(["query_memory", "ask_user_clarification"])` and a `tools_vec` containing `shell`, `query_memory`, and `GMAIL_SEND_EMAIL`. Asserts the dump's `tool_names` is exactly `["query_memory"]` — `shell` and `GMAIL_SEND_EMAIL` are in the global registry but NOT in the whitelist, so they MUST be excluded. If a future change reintroduces the unfiltered behaviour this test fails immediately. * Adds two test helpers: `wildcard_orchestrator_def()` builds a minimal orchestrator definition with all `omit_*` flags set and `ToolScope::Wildcard`, and `registry_with_orchestrator(orch)` wraps it in an `AgentDefinitionRegistry` so the tests can call `render_main_agent_dump` without going through the full TOML loader. 11/11 debug_dump tests pass. The two new guards plus the 9 existing sub-agent / filter / composio-stub tests all run clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(dispatch): unit tests for build_visible_tool_set + cargo fmt cleanup (#525, #526) Adds focused unit tests for the per-agent scoping helper landed in commit 4b and runs `cargo fmt` across the files touched by this PR. Why scoping unit tests, not full integration tests: `resolve_target_agent` is async and reads `Config::load_or_init().await` which does a real disk read every call (no cache, verified at `config/schema/load.rs:409`). Mocking that requires either spinning up a full workspace under a temp dir with a config.toml containing the right `onboarding_completed` value, or adding a test-only injection point on the public Config API. Both are tractable but invasive enough to belong in their own follow-up PR. The end-to-end dispatch path is already covered by the existing channel integration tests (`dispatch_routes_through_agent_run_turn_bus_handler` etc.) which exercise the full bus roundtrip with the new fields populated, and which still pass after the new resolver landed (it gracefully falls back to `AgentScoping::unscoped()` when no orchestrator definition is registered in the test environment). Pure-function unit tests for `build_visible_tool_set` cover the branching logic that does the actual scoping work: how the named whitelist + extras union is built, how Wildcard scope is preserved, how duplicates are de-duplicated, etc. That's the part most likely to drift in future changes, so it's the part most worth fencing with focused tests. Tests added (all in `src/openhuman/channels/runtime/dispatch.rs` under the new `scoping_tests` module): * `wildcard_scope_yields_none_filter` — `ToolScope::Wildcard` must produce `None` regardless of whether extras are present, so skills_agent / morning_briefing keep their full skill-category catalogue. * `named_scope_without_extras_returns_named_only` — the welcome agent's path: 2 named tools, no delegation, exactly 2 entries in the visibility whitelist. * `named_scope_with_extras_returns_union` — the orchestrator's path: 3 direct named tools + 3 synthesised extras (research, delegate_gmail, delegate_github) → 6 entries. * `empty_named_with_extras_returns_extras_only` — guards a future "delegation-only" agent layout where the agent has no direct tools of its own, just spawns subagents. * `empty_named_with_no_extras_returns_empty_set` — guards the distinction between `None` (no filter, all visible) and `Some(empty)` (filter active, nothing matches). Important because the prompt loop's `is_visible` check treats them differently. * `duplicate_names_across_named_and_extras_are_deduplicated` — the HashSet handles collisions automatically, but the test pins that behaviour so a future migration to `Vec<String>` (which would silently double-count) gets caught. * `agent_scoping_unscoped_has_no_filter_or_extras` — pins the safe-fallback constructor's contract. Used when the registry is uninitialised or the target agent is missing — every field must default to "no scoping" so the channel turn falls back to legacy unfiltered behaviour rather than crashing. Plus `cargo fmt` run across the 6 files modified by this PR. No behavioural changes. Final test status across all commits 2-6 in this PR: * agent::harness::definition: 10/10 ✅ (4 new for Subagents schema) * agent::harness::tool_loop: 8/8 ✅ * agent::harness::tests: 3/3 ✅ * tools::orchestrator_tools: 5/5 ✅ (5 new) * channels::*: 599/599 ✅ (incl. dispatch integration) * channels::runtime::dispatch::scoping_tests: 7/7 ✅ (7 new) * context::debug_dump: 11/11 ✅ (1 replaced + 1 new) * Total agent module: 323/324 (one pre-existing Windows path failure in `self_healing::tool_maker_prompt_includes_command` confirmed identical against upstream/main baseline) Pre-existing Windows-environment test failures NOT caused by this PR and out of scope (all confirmed identical on upstream baseline; CI on Linux is unaffected): * self_healing::tool_maker_prompt_includes_command (PathBuf separator) * cron::scheduler::run_job_command_success / _failure (Unix shell) * composio::trigger_history::archives_triggers_in_daily_jsonl... (path) * local_ai::paths::target_paths_preserve_absolute_overrides (path) * security::policy::checklist_root_path_blocked (POSIX absolute) * security::policy::checklist_workspace_only_blocks_all_absolute (POSIX) * tools::implementations::browser::screenshot::screenshot_command_ contains_output_path (browser binary lookup) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(welcome): upgrade bare-install nudge with concrete integration pitches (#525) Follow-up to #522 that addresses a rough UX edge in the welcome agent prompt: users who arrive with only an API key configured (no channels, no Composio integrations, no web search / browser / local AI) were getting a "gentle suggestion" to connect something without any concrete picture of what they'd actually unlock. The welcome agent would finish onboarding, hand off to orchestrator, and leave the user staring at a functional-but-empty assistant with no roadmap for how to make it useful. This commit rewrites the prompt to handle sparse setups explicitly. No Rust changes — this is prompt.md only, picked up at build time via the existing `include_str!` loader in `agents/mod.rs`. Changes to `src/openhuman/agent/agents/welcome/prompt.md`: * Step 2's "point out what's missing" sub-point is rewritten from a single "gently suggest" line into a four-case decision tree keyed off `check_status` state: - No API key → critical, block completion. - Integrations yes, channels no → note the Tauri-only reach limitation, suggest a messaging platform. - Channels yes, integrations no → degraded assistant, nudge toward Composio. - Nothing beyond the API key → the "bare install" case, gets the new Step 2.5 treatment. * New **Step 2.5: Handling a bare install** section added after Step 2. Spells out what the user DOES have (sandboxed reasoning + coding assistant with memory), what they're MISSING (any external action), and how to structure the message: state the current capability honestly, pitch 2-3 specific integrations with concrete example prompts, point to Settings → Integrations / Channels, and leave room for the user to opt into the coding-only experience if that's what they actually want. For bare-install users the word budget stretches to 250-400 words (up from 200-350) so the concrete pitches and example prompts actually fit without cramming. * New **Integration capability reference** section giving the LLM a menu it can draw from when pitching integrations. Each entry is a one-line "connect X → I can Y" with a concrete example prompt the user could send next: - Gmail: "Summarise the most important emails that came in overnight and flag anything that needs a reply today." - Google Calendar: "What's on my calendar tomorrow, and do I have a 30-minute gap before 2pm?" - GitHub: "List open issues on my main project tagged 'bug' and summarise which ones look newest or most urgent." - Notion: "Pull up my 'Ideas' Notion database and show me the three newest entries." - Slack / Discord / Linear / Jira / etc. with similar shapes. Plus a sub-section for messaging platforms (Telegram / Discord / Slack / iMessage / WhatsApp / Signal / web-fallback) that clarifies which each is best for, and a sub-section for the other capabilities (web search, browser automation, HTTP requests, local AI) that explains what breaks without them. The LLM is told NOT to list everything — just pick 2-3 most likely to matter, defaulting to Gmail + GitHub + one of {Calendar, Notion} as the top-3 pitch when no profile context is available. * Tone guidelines updated to document the stretched word budget for bare installs (200-350 for configured users, 250-400 for bare installs). * "What NOT to do" list updated: - Explicitly allows product-tour-style listing ONLY in the bare-install case (Step 2.5), forbids it elsewhere. - Clarifies that describing what WOULD unlock with integration X is fine and encouraged; claiming a capability the user doesn't have is still forbidden. - Adds a new "Don't gloss over a bare install" entry that pins the rule: API-key-only users get concrete pitches and example prompts, not vague suggestions. Scope note: this commit does NOT change the completion logic. `complete_onboarding(complete)` still accepts API-key-only as the minimum bar — that's a separate design question for the maintainer about whether zero-integration users should be gatekept. This change improves what the welcome agent SAYS to those users, not whether they're allowed to proceed. Tests: all 14 `agent::agents::tests` pass (including `welcome_has_onboarding_and_memory_tools` which validates the welcome agent's declarative shape is unchanged). The prompt.md edit is pure content — no schema changes, no tool additions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(web-channel): route Tauri in-app chat to welcome/orchestrator + Windows fsync fix (#525) Closes the web-channel-side half of the #525 welcome agent routing. Also bundles a small pre-existing Windows compatibility fix for `app_state::ops::sync_parent_dir` that was blocking end-to-end testing of this branch on Windows. ## Web channel routing (primary change) Commit 4b ( |
||
|
|
8057f2283c |
feat: onboarding Gmail integration + LinkedIn profile enrichment (#524)
* refactor(composio): restructure toolkit metadata handling and onboarding steps - Removed the old `toolkitMeta.ts` file and replaced it with a new `toolkitMeta.tsx` file that includes updated metadata handling for Composio toolkits, enhancing the integration with React components. - Updated the `ComposioConnectModal` to directly render icons without additional markup, streamlining the component structure. - Modified the `Skills` page to utilize the new icon rendering method, improving consistency across the application. - Enhanced the onboarding process by introducing a new `ContextGatheringStep` component, which gathers user context from connected integrations, improving the onboarding experience. - Updated the `SkillsStep` to reflect changes in toolkit connection handling and display, ensuring a smoother user interaction during onboarding. * feat(apify): introduce Apify integration tools for actor execution and status retrieval - Added new tools for running Apify actors and fetching their run statuses, enhancing automation capabilities. - Updated the integration schema to include an `apify` toggle for user configuration, allowing for flexible integration management. - Enhanced the onboarding experience by modifying the SkillsStep to focus on Gmail integration, streamlining user interactions. - Improved documentation and comments for clarity on the new Apify functionalities and their usage. * feat(learning): add LinkedIn enrichment module and schemas - Introduced a new `linkedin_enrichment` module for enriching user profiles by scraping LinkedIn data from Gmail. - Implemented the `run_linkedin_enrichment` function to handle the enrichment pipeline, including Gmail search, scraping via Apify, and data persistence. - Added controller schemas for the learning domain, enabling integration with the existing controller framework. - Updated the `all.rs` file to register the new learning controllers and schemas, enhancing the overall functionality of the learning system. * feat(linkedin): implement PROFILE.md generation for LinkedIn enrichment - Added functionality to generate a PROFILE.md file from scraped LinkedIn data, summarizing user profiles for agent context. - Updated the `run_linkedin_enrichment` function to write PROFILE.md to the workspace, enhancing data persistence. - Introduced helper functions for rendering and summarizing LinkedIn profiles, improving the overall enrichment process. - Ensured minimal PROFILE.md creation even when scraping fails, maintaining essential user context. * feat(onboarding): enhance ContextGatheringStep for LinkedIn enrichment pipeline - Updated the ContextGatheringStep to integrate a new pipeline for LinkedIn enrichment, replacing the previous Gmail profile fetching stages. - Implemented a progress animation and logging for the enrichment process, improving user feedback during data retrieval. - Refactored stage definitions to align with the new pipeline structure, enhancing clarity and maintainability. - Introduced error handling and status updates for each stage of the enrichment process, ensuring robust user experience. * feat(instructions): refactor tool instruction generation for clarity and flexibility - Introduced helper functions `tool_instructions_preamble` and `append_tool_entry` to streamline the construction of tool instructions. - Updated `build_tool_instructions` to utilize the new helper functions, improving code readability and maintainability. - Added `build_tool_instructions_filtered` to allow for generating instructions from a filtered list of tools, enhancing flexibility in tool usage. - Adjusted the startup process to use the filtered instructions, ensuring only relevant tools are included in the system prompt. * refactor(toolkitMeta): simplify component structure and improve readability - Refactored the `BrandIcon` component to streamline its props definition, enhancing code clarity. - Consolidated SVG path definitions in various icons for better readability and maintainability. - Updated the `ContextGatheringStep` to simplify the RPC call syntax, improving code conciseness. - Enhanced logging in the LinkedIn enrichment process for clearer tracking of Gmail searches and scraping stages. * fix: address PR review — USER.md→PROFILE.md consistency, Composio tool filtering, and quality fixes - Replace USER.md with PROFILE.md across all prompt paths: channels_prompt.rs, subconscious/prompt.rs, workspace/ops.rs bootstrap, and channel tests - Remove Composio tool description from main agent system prompt (tool_descs) so skills_agent is the only agent that sees Skill-category tools - Add "learning" namespace description for CLI help discovery - Fix react-hooks/set-state-in-effect: wrap synchronous setState in queueMicrotask in ContextGatheringStep - Derive SkillsStep displayToolkits from backend allowlist with error/retry UI - Add KNOWN_COMPOSIO_TOOLKITS alternate slug variants (google_calendar, etc.) - Add namespaced debug logging to onboarding handlers and pipeline - Deduplicate MemoryClient creation in linkedin_enrichment persist functions * fix: use setTimeout instead of queueMicrotask for ESLint compatibility * refactor(onboarding): streamline debug logging in handleContextNext function - Consolidated debug logging in the handleContextNext function to improve clarity and reduce verbosity. - Removed unnecessary line breaks for a more concise code structure. * refactor(linkedin): enhance enrichment pipeline with structured stage results - Introduced a new `EnrichmentStage` struct to capture detailed results for each stage of the LinkedIn enrichment process. - Updated the `LinkedInEnrichmentResult` to include a vector of stages, allowing for structured reporting of success, failure, and skipped stages. - Improved error handling and logging throughout the enrichment pipeline, ensuring better traceability of issues during execution. - Adjusted the API response to include stage results, enhancing the frontend's ability to display detailed enrichment outcomes. * chore(workflows): update macOS E2E test configuration and comment out Linux E2E job - Modified the description and default values in the macOS E2E test input options for clarity. - Commented out the entire Linux E2E job configuration to prevent execution while maintaining the setup for future use. |
||
|
|
08d9fd2d4d |
fix(voice): recover buffered hotkey events after select! race (#527) (#545)
* fix(voice): return receiver count from publish_transcription publish_transcription now returns the number of active TRANSCRIPTION_BUS subscribers that received the message. When no receivers are connected (e.g. Socket.IO bridge not yet subscribed), the function logs a warning instead of silently discarding the broadcast. This makes it possible to diagnose "transcription produced but never delivered" scenarios from logs alone. Closes #527 (partial) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(voice): recover buffered hotkey events after select! race On warm CPAL init (second+ recording), audio_capture::start_recording() completes fast enough that the pending_ready branch and the hotkey_rx branch are both ready simultaneously inside tokio::select!. select! picks one pseudo-randomly — when it picks pending_ready, the Released event sits unprocessed in hotkey_rx. The recording is stored as "live" with no deferred stop, then the next loop iteration processes the buffered Released and stops the recording almost immediately, producing a near-zero-length clip that the duration gate silently drops. Fix: after pending_ready resolves, call hotkey_rx.try_recv() to check for a buffered stop event that lost the race. If found, apply the deferred stop mechanism (MIN_RECORDING_AFTER_SETUP = 1500ms) instead of treating the recording as live. Also adds pipeline_id (UUID prefix) to all process_recording_bg log lines for end-to-end correlation, and labels each pipeline stage (stop_recording, gate_duration, gate_silence, transcribe, deliver) so dropped recordings are diagnosable from logs. Closes #527 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
57a8bedddf | chore(release): v0.52.7 v0.52.7 | ||
|
|
af454afbb3 | chore(release): v0.52.6 v0.52.6 | ||
|
|
ec138c8491 |
feat(composio): provider folder modules + user profile persistence (#523)
* feat(composio): implement profile persistence for user data
- Introduced a new `profile` module to handle the persistence of user profile data from various providers into the local `user_profile` facet table.
- Enhanced the `composio_get_user_profile` and `fetch_user_profile` functions to call `persist_provider_profile`, ensuring that profile fields like display name, email, and avatar are stored locally for quick access.
- Added debug logging to track the number of facets written during the persistence process, improving observability of profile updates.
- This change aims to enhance user experience by reducing the need for repeated upstream API calls for frequently accessed profile information.
* style: apply cargo fmt to profile.rs and client.rs
* fix: PR review — cursor whitespace, stale profile values, test precision, log level
- Trim whitespace in cursor_to_gmail_after_filter before parsing so
leading/trailing spaces don't silently bypass the date filter.
- Change profile_upsert condition from `>` to `>=` so equal-confidence
provider refreshes replace stale values instead of only bumping
evidence_count.
- Tighten epoch millis test to assert exact date "2026/03/31" instead
of loose contains('/') check.
- Lower profile persistence log from info to debug to reduce noise in
normal connect/sync flows.
|
||
|
|
ae9ac30db6 |
feat: add proactive welcome onboarding flow (#522)
* feat: add proactive agents for onboarding experience - Introduced two new proactive agents: "Morning Briefing" and "Welcome Message". - The Morning Briefing agent provides a daily summary of the user's calendar, tasks, and relevant context, scheduled to run automatically at 7 AM. - The Welcome Message agent delivers a personalized greeting after onboarding, utilizing user information for a tailored experience. - Updated the cron job system to seed these agents upon onboarding completion, enhancing user engagement from the start. - Added comprehensive tests to ensure the correct functionality of the new agents and their integration into the system. * feat: implement proactive message handling for user engagement - Added a new `ProactiveMessageSubscriber` to route proactive messages (e.g., morning briefings, welcome messages) to the user's active channel, enhancing user engagement. - Introduced `ProactiveMessageRequested` event in the event bus to facilitate proactive message delivery. - Updated the configuration schema to include a preferred channel for proactive messages, allowing for tailored user experiences. - Seeded default proactive agent cron jobs to ensure timely delivery of messages post-onboarding. - Enhanced the startup process to register the proactive message subscriber, ensuring proactive messages are consistently routed. - Comprehensive tests added to validate the functionality of proactive message handling and delivery mechanisms. * feat: enhance welcome agent functionality and onboarding process - Updated the welcome agent's description to clarify its role as the first point of contact for new users, focusing on guiding them through remaining onboarding steps. - Increased the maximum iterations for the agent from 4 to 6 to allow for more complex interactions. - Introduced a new `complete_onboarding` tool to check the user's setup status and mark onboarding as complete, improving the onboarding experience. - Enhanced the prompt structure to provide clearer guidance on the agent's workflow, including steps for checking setup status, greeting users, and completing onboarding. - Updated the tools list to include `complete_onboarding`, ensuring the welcome agent can effectively manage user onboarding. - Comprehensive documentation added to clarify the agent's functionality and improve user engagement. * feat: enhance welcome agent functionality and onboarding process - Updated the welcome agent's description to clarify its role as the first point of contact for new users, focusing on guiding them through setup and onboarding. - Increased the maximum iterations for the agent from 4 to 6 to allow for more comprehensive interactions. - Introduced a new `complete_onboarding` tool to check the user's setup status and mark onboarding as complete, improving the onboarding experience. - Enhanced the prompt structure to provide clearer guidance on the agent's workflow, including steps for checking setup status, greeting users, and completing onboarding. - Updated the tools list to include the new `complete_onboarding` tool, ensuring it is available for the welcome agent's operations. - Improved documentation for the welcome agent's prompt, emphasizing tone guidelines and what not to do during user interactions. * style: apply rustfmt to onboarding flow changes * refactor: streamline proactive message subscriber registration and enhance onboarding agent tests - Replaced the direct registration of the proactive message subscriber with a new `register_web_only_proactive_subscriber` function, ensuring it is only registered once during domain startup. - Updated the welcome agent test to reflect the addition of the `complete_onboarding` tool, verifying its presence and adjusting the expected number of tools. - Enhanced the onboarding process by improving logging for proactive agent seeding transitions, providing clearer insights during onboarding state changes. - Refactored the cron job system to support agent definitions, allowing for more flexible job scheduling and execution based on defined agent parameters. - Improved documentation and comments across the affected modules to clarify the purpose and functionality of changes made. * refactor: improve proactive subscriber registration and logging - Streamlined the registration process for the web-only proactive message subscriber, enhancing clarity and maintainability. - Consolidated logging statements in the onboarding completion function for improved readability and consistency. - These changes aim to enhance the overall structure and logging clarity within the proactive messaging and onboarding processes. |
||
|
|
4cf608c2be |
feat: native embeddings module with Ollama and vector store (#521)
* feat: replace fastembed with candle for local embeddings - Introduced a new `CandleEmbedding` provider using the `candle` ML framework, eliminating C++ dependencies and enhancing performance. - Updated configuration to default to `candle` for embedding provider settings, replacing the previous `fastembed` references. - Added new modules for embedding providers, including `candle_embed`, `noop`, and `openai`, to support various embedding strategies. - Enhanced the `EmbeddingProvider` interface to accommodate the new `CandleEmbedding` implementation. - Refactored related tests to ensure comprehensive coverage of the new embedding functionalities and maintain backward compatibility with existing configurations. * feat: update embedding provider to Ollama - Replaced the default embedding provider from Candle to Ollama, enhancing local embedding capabilities with improved model management and GPU acceleration. - Updated configuration defaults for embedding model and dimensions to align with Ollama specifications. - Introduced a new Ollama embedding module, including necessary constants and functionality for embedding requests. - Refactored related code and tests to ensure compatibility with the new provider, maintaining backward compatibility with existing configurations. * refactor: remove Candle embedding provider and related dependencies - Deleted the `CandleEmbedding` module and its associated files, streamlining the embedding provider architecture. - Updated `Cargo.toml` and `Cargo.lock` to remove references to Candle-related packages, ensuring a cleaner dependency tree. - Refactored the `EmbeddingProvider` interface to eliminate support for the Candle provider, maintaining compatibility with existing providers. - Adjusted tests and documentation to reflect the removal of the Candle embedding functionality, ensuring clarity and consistency across the codebase. * feat: add SQLite-backed vector store for embeddings - Introduced a new `store` module to implement a local vector store backed by SQLite, enabling efficient storage and retrieval of text embeddings. - Added functionality for inserting, updating, and searching embeddings using cosine similarity, enhancing the embedding management capabilities. - Updated the `mod.rs` file to include the new `store` module and expose relevant functions for cosine similarity and vector operations. - Enhanced documentation to provide usage examples and clarify the integration of the vector store with existing embedding providers. * Add fs2 dependency for improved file locking in ComposeIO trigger history * test: boost embeddings module coverage to 97%+ Add tests for batch insert mismatch error path, invalid metadata JSON handling, disk store parent directory creation, and fake embedding dimensions accessor. 95 tests total across the module, all files at 97-100% line coverage. * style: apply cargo fmt to embeddings module * feat: enhance embedding provider creation with error handling - Updated the `create_embedding_provider` function to return an `anyhow::Result`, allowing for immediate error reporting on unrecognized provider names. - Added support for a "none" provider that returns a no-op embedding. - Enhanced tests to cover new error handling paths and validate behavior for known and unknown providers, improving overall test coverage. * feat: enhance Ollama and OpenAI embedding providers with improved handling for blank inputs and response validation - Updated the `embed` method in both `OllamaEmbedding` and `OpenAiEmbedding` to skip blank inputs while preserving their positions in the output as zero-vectors. - Added validation to ensure the response count matches the input count, with appropriate error handling for dimension mismatches. - Enhanced tests to cover new behavior for blank inputs and response validation, ensuring robustness in embedding functionality. * fix: address PR review findings for embeddings module - Factory returns Result for unknown providers instead of silent noop - Ollama: preserve positional alignment when blank texts are filtered - Ollama: validate response count and dimensions before returning - OpenAI: strict parsing errors on non-numeric embedding values - OpenAI: skip Authorization header when api_key is empty - OpenAI: validate response count and dimensions - OpenAI/Ollama: add tracing at entry, success, and error paths - Store: add store_meta table to persist and validate embedding provider/dimensions on open — errors on dimension mismatch - Store: propagate row decode errors instead of filter_map(ok) - Store: add tracing to search, insert, delete, and count paths - Update factories.rs caller for Result-returning factory 101 tests pass, all files at 97%+ coverage. |
||
|
|
3a20599f45 |
feat: dynamic connected integrations in agent system prompts (#520)
* feat(agent): add support for connected integrations in system prompts - Introduced a new `fetch_connected_integrations` method to retrieve and populate active Composio integrations for the agent. - Updated the `Agent` struct to include a `connected_integrations` field, allowing the system prompt to display available external services. - Enhanced the `build_system_prompt` method to incorporate connected integrations, improving the context provided to users during interactions. - Added a `ConnectedIntegrationsSection` to the prompt rendering, ensuring visibility of active integrations in the system prompt output. - Overall, these changes enhance the agent's ability to leverage connected services, improving user experience and interaction capabilities. * feat(debug_dump): integrate connected integrations into agent prompt dumps - Added a new `fetch_connected_integrations_for_dump` function to retrieve active integrations for the agent during prompt dumps. - Updated the `render_main_agent_dump` function to include connected integrations, enhancing the context provided in the debug output. - Improved the overall structure and clarity of the debug dump process, ensuring that connected integrations are accurately represented in the agent's prompt context. * refactor(agent): streamline integration fetching for system prompts - Refactored the `fetch_connected_integrations` method in the `Agent` struct to delegate integration fetching to a new centralized function in the `composio` module, enhancing code clarity and maintainability. - Updated the `fetch_connected_integrations_for_dump` function to utilize the new centralized fetching logic, ensuring consistent integration retrieval across different contexts. - Improved the overall structure of integration handling, allowing for better error management and logging during the fetching process. * feat(agent): add connected integrations support to parent execution context - Introduced a new field `connected_integrations` in the `ParentExecutionContext` struct to store active Composio integrations. - Updated relevant functions to utilize the new `connected_integrations` field, ensuring that system prompts and agent dumps reflect the current integrations. - Enhanced the integration cache management by implementing cache invalidation logic when connections are created or deleted, improving the accuracy of integration data across sessions. - Overall, these changes enhance the agent's ability to leverage connected services, providing users with better context during interactions. * feat(agent): initialize connected integrations in subagent context - Added a `connected_integrations` field to the `ParentExecutionContext` and `Agent` struct, allowing for the storage and retrieval of active Composio integrations. - Updated the `dispatch_target_agent` function to populate the `connected_integrations` field when creating a new sub-agent context. - Enhanced the `fetch_connected_integrations` method to return an `Option<Vec<ConnectedIntegration>>`, improving error handling and caching logic. - These changes improve the agent's ability to manage and utilize connected integrations, enhancing user interactions and context awareness. * refactor(agent): improve caching logic in fetch_connected_integrations - Updated the `fetch_connected_integrations` function to handle caching more effectively by using a match statement. - The function now caches results only when the backend is reachable, preventing unnecessary caching when the client is unavailable. - This change enhances error handling and ensures that subsequent calls with different configurations can retry without stale data. * style: apply cargo fmt formatting * feat(agent): enhance connected integrations handling and caching - Updated the `dispatch_target_agent` function to initialize connected integrations for sub-agents, ensuring they have access to the latest integrations. - Improved the caching mechanism for connected integrations by using a `HashMap` keyed by configuration identity, allowing for user-specific caching and better isolation of integration data. - Refactored the `invalidate_connected_integrations_cache` function to clear the entire cache instead of setting it to `None`, enhancing cache management. - Added a new method `load_from_default_paths` in the `Config` struct to reliably load user configurations without being affected by environment variable overrides, improving the debug dump process. - Enhanced the rendering of connected integrations in system prompts to provide clearer instructions based on available tools, improving user interaction clarity. * feat(agent): add method to set connected integrations - Introduced a new `set_connected_integrations` method in the `Agent` struct to allow for replacing the agent's connected integrations from external sources, enhancing flexibility in integration management. - Updated the caching mechanism for connected integrations to utilize `LazyLock`, improving initialization efficiency and thread safety. * style: apply cargo fmt |