sanil-23andGitHub 945a5c4a02 feat: subconscious loop — local-model background awareness via heartbeat (#268)
* feat: subconscious loop — local-model background awareness via heartbeat

Add a subconscious inference layer to the heartbeat engine. On each
tick, the engine reads HEARTBEAT.md tasks, builds a delta-based
situation report (memory docs, graph relations, skills health,
environment), and evaluates them with the local Ollama model.

Architecture:
- HeartbeatEngine (scheduler) delegates to SubconsciousEngine (brain)
- HeartbeatConfig extended with inference_enabled, context_budget_tokens
- No separate SubconsciousConfig — all config lives under [heartbeat]
- Default HEARTBEAT.md ships with 3 active tasks (email, deadlines, skills)

Subconscious module (src/openhuman/subconscious/):
- engine.rs: tick logic, local model inference, escalation to cloud model
- situation_report.rs: delta assembler (memory, graph, skills, env, tasks)
- prompt.rs: task-driven system prompt for local model
- decision_log.rs: dedup tracking with 24h TTL and acknowledgment
- types.rs: Decision (noop/act/escalate), TickOutput, RecommendedAction
- schemas.rs: RPC controllers (subconscious_status, subconscious_trigger)
- integration_test.rs: two-tick lifecycle test with fixtures

Decision flow:
- noop: no changes, skip — no LLM call wasted
- act: local model recommends actions → stored in memory KV
- escalate: calls cloud model to resolve → concrete actions stored

Verified with real Ollama inference (gemma3:4b):
- Tick 1: ingested gmail+notion → "act: deadline needs attention" (high)
- Tick 2: ingested state changes → "act: deadline moved" (high)
- Skills health section populated from live skill registry

Closes #145

* feat: add subconscious_actions RPC endpoint

New endpoint openhuman.subconscious_actions returns stored action
entries from the subconscious KV namespace, sorted by most recent
first, with configurable limit (default 20).

Response format:
{
  "entries": [
    { "tick_at": 1775117975.58, "actions": [...] }
  ],
  "count": 1
}

The upcoming subconscious page will call this to display
notifications and recommended actions to the user.

* fix: budget underflow and UTF-8 panic in situation report truncation

- Use saturating_add for newline byte to prevent underflow when
  section exactly fills the remaining budget
- Truncate at valid UTF-8 char boundary using char_indices instead
  of raw byte slicing, which panicked on multibyte characters
- Add tests for exact-fit and multibyte truncation

* fix: address CodeRabbit review — shared engine, dedup, consistent schema

Fixes from CodeRabbit review on PR #268:

- #8 Two engine instances: Add global.rs singleton shared between
  HeartbeatEngine::run() and RPC handlers. Both use get_or_init_engine()
  so decision log, counters, and last_tick_at are always in sync.

- #3 Dedup disabled: tick() now extracts actual document IDs from
  memory via build_situation_report_with_doc_ids() and passes them
  to decision_log.record(). filter_unsurfaced() actually filters now.

- #5 Decision log not loaded on trigger: tick() loads persisted log
  from KV on first execution (total_ticks == 0), not only from run().

- #4 Inconsistent action schema: handle_escalation() normalizes agent
  response into RecommendedAction[] via normalize_escalation_response().
  Both act and escalate paths store the same schema.

- #7 Key collision: store_actions() uses millisecond timestamp + random
  suffix instead of second-precision truncation.

- #10 No-changes unreachable: tick() checks has_new_data (unsurfaced
  doc IDs) OR has_memory_changes (report text) instead of naive string
  matching on environment section.

* fix: include document content in situation report, not just titles

The local model needs actual content to evaluate HEARTBEAT.md tasks
meaningfully. Previously it only saw titles like "Deadline reminder"
with no way to know if it's urgent.

Now recalls content per namespace (up to 500 chars each, max 10
namespaces) via client.recall_namespace(). The model sees actual
email text and page content alongside the task checklist.

* fix: timestamp parsing, byte-boundary slicing, and truncation overshoot

- schemas.rs: split on first ':' after 'actions:' prefix before parsing
  timestamp, so keys like 'actions:123456:xyz' parse correctly
- situation_report.rs: use truncate_at_char_boundary() for error strings
  instead of raw byte slice which panics on multibyte characters
- situation_report.rs: fix append_section and truncate_at_char_boundary
  to use char END offset (i + len_utf8) in take_while condition, so
  multibyte chars that start before but end after the budget are excluded
2026-04-02 21:51:09 +05:30
2026-03-29 10:30:18 -07:00
2026-04-02 20:54:46 +05:30
2026-03-26 17:04:46 -07:00
2026-02-20 13:03:15 +04:00
2026-02-20 13:03:15 +04:00

OpenHuman

The age of super intelligence is here. OpenHuman is your Personal AI super intelligence. Private, Simple and extremely powerful.

DiscordRedditX/TwitterDocs

Early Beta Platforms: desktop only Latest Release

The Tet

"The Tet. What a brilliant machine" — Morgan Freeman as he reminisces about alien superintelligence in the movie Oblivion

Early Beta — Under active development. Expect rough edges.

To install or get started, either download from the website over at tinyhumans.ai/openhuman or run

# For MacOS/Linux
curl -fsSL https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.sh | bash

# For Windows
irm https://raw.githubusercontent.com/tinyhumansai/openhuman/main/scripts/install.ps1 | iex

What is OpenHuman?

OpenHuman is an open-source agentic assistant that is designed to integrate with you in your daily life. Here's what makes OpenHuman special:

  • One subscription, many providers — One assistant wired to skills and backend models so you are not juggling a separate subscription stack for every integration surface.

  • Incredible memoryRust-side memory (store / recall / namespaces) plus optional TinyHumans Neocortex-backed context when configured, so the agent can retain and retrieve more than a single chat window. Channels and ongoing conversations feed the same loop so day-to-day context does not reset every session.

  • Screen intelligence — Regular screen capture (on a cadence or when triggered) feeds an on-device pipeline that understands what is on screen, distills it into memory (facts, UI state, workflows), and can propose actions the agent executes for you. OS permissions and capture APIs vary by platform; the goal is your machine first, not shipping raw frames to the cloud by default.

  • Voice & meetings — A Local-model speech stack (listen / TTS) let the assistant talk back and capture or work with meeting audio with a privacy-first default when you route inference locally. Transcripts and summaries land in the same memory + agent loop so OpenHuman can follow up: tasks, drafts, calendar nudges, or skill-backed workflows—without treating a meeting as a one-off chat.

  • Memory-aware autocompleteKeyboard autocomplete is built for right-context suggestions: it consults memory namespaces and recent context so completions stay aligned with you, your workspace, and prior sessions—not a blank model every keystroke.

  • Runs a local AI model — The Rust core exposes local AI paths (and the desktop bundle can ship local/bundled runners where applicable) for the workloads above—vision snippets, speech helpers, summarization, tooling—so sensitive steps can stay off the cloud when you choose.

  • Simple or advancedSkill setup wizards and defaults for common tools, with room to go deeper via settings, credentials, and core RPC when you need control and privacy.

Architecture: docs/ARCHITECTURE.md. Contributor orientation: CONTRIBUTING.md.

Under the hood (Architecture)

OpenHuman is a desktop monorepo: Rust owns business logic and execution; the UI owns interaction, layout, and OS integration.

Rust (openhuman / openhuman_core). The repo root src/ crate is the brain: JSON-RPC over HTTP (core_server), domain modules (auth, config, memory, skills, channels, screen intelligence, local AI, cron, …), and a QuickJS runtime for sandboxed JavaScript skills. The openhuman binary is built and staged next to the Tauri app so the desktop shell can spawn it as a sidecar. Heavy work—SQLite, sockets, crypto, skill lifecycle—runs there under Tokio, not in the WebView.

UI (app/). Vite + React (TypeScript) implements screens, onboarding, settings, and realtime UX. Redux Toolkit holds client state; Socket.io and the MCP-style client stack stay in sync with the cores realtime surface. Tauri v2 (app/src-tauri/) is a thin Rust host: windowing, filesystem hooks where needed, and core_rpc_relay—forwarding JSON-RPC from the WebView to the openhuman process so the UI never re-implements domain rules.

Controllers and the RPC surface. Features are exposed as registered controllers: each domain declares schemas (namespace, function name, parameter shapes) and a handler. At runtime, calls are validated, dispatched by method name (e.g. openhuman.auth_get_state, openhuman.local_ai_agent_chat), and return structured outcomes. CLI and HTTP share the same controller catalog, so automation, tests, and the app all hit one contract.

What ties it together: one registry of controllers, one sidecar process for execution, Tauri IPC for shell-only capabilities, and HTTP JSON-RPC for everything else—plus skills and dual-socket behavior documented in the architecture guide.

Read more: docs/ARCHITECTURE.md · Frontend tree: docs/src/README.md · Tauri commands: docs/src-tauri/README.md

Contributors Hall of Fame

Show some love and end up in the hall of fame

OpenHuman contributors
S
Description
No description provided
Readme GPL-3.0
214 MiB
Languages
Rust 59.1%
TypeScript 37.9%
JavaScript 1.6%
Shell 1.2%
CSS 0.1%